Grouping points after cut plane three js

后端 未结 1 1868
太阳男子
太阳男子 2020-12-29 17:14

I found all intersection points between the object and plane, as in this great example. But now I want to connect these points between themselves (dividing into separate arr

相关标签:
1条回答
  • 2020-12-29 17:45

    So, yes, this answer based on that one and extends it. The solution is rough and can be optimized.

    I've used modified .equals() method of THREE.Vector3() (I hope it (or something similar) will be a part of the core one day as it's a very useful feature), taken from here:

    THREE.Vector3.prototype.equals = function(v, tolerance) {
      if (tolerance === undefined) {
        return ((v.x === this.x) && (v.y === this.y) && (v.z === this.z));
      } else {
        return ((Math.abs(v.x - this.x) < tolerance) && (Math.abs(v.y - this.y) < tolerance) && (Math.abs(v.z - this.z) < tolerance));
      }
    }
    

    The idea:

    When we're getting points of intersection, to each point we add information about which face a point belongs to. It means that there are always pairs of points with the same face index.

    Then, we recursively find all the contours our points form.

    Also, all points mark as unchecked (.checked = false).

    1. Find first unchecked point. Add it to the array of the current contour.

    2. Find its pair point (with the same face index). Add it to the array of the current contour.

    3. Find an unchecked point, the closest one to the point found last. Makr it as checked .checked = true.

    4. Find its pair point (with the same face index). Mark it as checked .checked = true.

    5. Check, if the last found point equals (with some tolerance) to the first found point (the beginning of the contour)

      5.1. If no, then just add the last found point in the array of the current contour and go to step 3.

      5.2. If yes, then clone the first point of the current contour and add it to the array of the current contour, add the contour to the array of contours.

    6. Check, if we have have all points marked as checked.

      6.1. If no, then go to step 1.

      6.2. If yes, we finished. Return the array of contours.

    Modified function of setting a point of intersection:

    function setPointOfIntersection(line, plane, faceIdx) {
      pointOfIntersection = plane.intersectLine(line);
      if (pointOfIntersection) {
        let p = pointOfIntersection.clone();
        p.faceIndex = faceIdx;
        p.checked = false;
        pointsOfIntersection.vertices.push(p);
      };
    }
    

    How to get contours and how to draw them:

    var contours = getContours(pointsOfIntersection.vertices, [], true);
    
    contours.forEach(cntr => {
        let cntrGeom = new THREE.Geometry();
        cntrGeom.vertices = cntr;
        let contour = new THREE.Line(cntrGeom, new THREE.LineBasicMaterial({
          color: Math.random() * 0xffffff
        }));
        scene.add(contour);
      });
    

    Where

    function getContours(points, contours, firstRun) {
      console.log("firstRun:", firstRun);
    
      let contour = [];
    
      // find first line for the contour
      let firstPointIndex = 0;
      let secondPointIndex = 0;
      let firsPoint, secondPoint;
      for (let i = 0; i < points.length; i++) {
        if (points[i].checked == true) continue;
        firstPointIndex = i;
        firstPoint = points[firstPointIndex];
        firstPoint.checked = true;
        secondPointIndex = getPairIndex(firstPoint, firstPointIndex, points);
        secondPoint = points[secondPointIndex];
        secondPoint.checked = true;
        contour.push(firstPoint.clone());
        contour.push(secondPoint.clone());
        break;
      }
    
      contour = getContour(secondPoint, points, contour);
      contours.push(contour);
      let allChecked = 0;
      points.forEach(p => { allChecked += p.checked == true ? 1 : 0; });
      console.log("allChecked: ", allChecked == points.length);
      if (allChecked != points.length) { return getContours(points, contours, false); }
      return contours;
    }
    
    function getContour(currentPoint, points, contour){
      let p1Index = getNearestPointIndex(currentPoint, points);
      let p1 = points[p1Index];
      p1.checked = true;
      let p2Index = getPairIndex(p1, p1Index, points);
      let p2 = points[p2Index]; 
      p2.checked = true;
      let isClosed = p2.equals(contour[0], tolerance);
      if (!isClosed) {
        contour.push(p2.clone());
        return getContour(p2, points, contour);
      } else {
        contour.push(contour[0].clone());
        return contour;
      }
    }
    
    function getNearestPointIndex(point, points){
      let index = 0;
      for (let i = 0; i < points.length; i++){
        let p = points[i];
        if (p.checked == false && p.equals(point, tolerance)){ 
          index = i;
          break;
        }
      }
      return index;
    }
    
    function getPairIndex(point, pointIndex, points) {
      let index = 0;
      for (let i = 0; i < points.length; i++) {
        let p = points[i];
        if (i != pointIndex && p.checked == false && p.faceIndex == point.faceIndex) {
          index = i;
          break;
        }
      }
      return index;
    }
    

    jsfiddle example r87.

    0 讨论(0)
提交回复
热议问题