切割平面三js后分组点

时间:2017-10-10 08:17:43

标签: three.js

我找到了物体和飞机之间的所有交叉点,就像在这个伟大的example中一样。但现在我想在它们之间连接这些点(分成不同的数组),飞机经过这些点并再次连接它们。我试图通过距离连接它们,但这没有给出有效的结果

//SORT POINTS DISTANCE
var pointsArray = []; //point after intersection
var sortedPoints = [];
var sortedPointsDis = [];

sortedPoints.push( pointsArray.pop() );

while( pointsArray.length ) {
  var distance = sortedPoints[sortedPoints.length - 1].distanceTo( pointsArray[0] );
  var index = 0;
  for(var i = 1; i < pointsArray.length; i++) {
      var tempDistance = sortedPoints[sortedPoints.length - 1].distanceTo( pointsArray[i] );
      if( tempDistance < distance ) {
          distance = tempDistance;
          index = i;
      }
  }
  sortedPoints.push( pointsArray.splice(index, 1)[0] );
  sortedPointsDis.push( distance );
 }

 //GROUP POINTS
 var result = [[]];

 for(var i = 0; i < sortedPoints.length; i++) {
  var lastArr = result[result.length - 1];
  if( lastArr.length < 3 ) {
      lastArr.push( sortedPoints[i] );
  } else {
      var distance = lastArr[0].distanceTo( sortedPoints[i] );
      if( distance < sortedPointsDis[i - 1] ) {
          result.push([]);
          lastArr = result[result.length - 1];
      }
      lastArr.push(sortedPoints[i]);
  }
}

JSfiddle。 想法?例子?提前感谢您的回复!

1 个答案:

答案 0 :(得分:4)

所以,是的,这个答案基于that one并扩展了它。解决方案很粗糙,可以进行优化。

我使用.equals()的修改后的THREE.Vector3()方法(我希望它(或类似的东西)将成为核心的一部分,因为它是一个非常有用的功能),取自{{ 3}}:

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));
  }
}

here

这个想法:

当我们获得交叉点时,我们会为每个点添加关于点所属的面的信息。这意味着总有一对具有相同面部索引的点。

然后,我们递归地找到我们的点形成的所有轮廓。

此外,所有点都标记为未选中(.checked = false)。

  1. 找到第一个未选中的点。将其添加到当前轮廓的数组中。

  2. 找到它的对点(具有相同的面部索引)。将其添加到当前轮廓的数组中。

  3. 找到一个未选中的点,与最后找到的点最接近的点。将其作为已检查.checked = true

  4. 找到它的对点(具有相同的面部索引)。将其标记为已选中.checked = true

  5. 检查最后找到的点是否等于(有一定的公差)第一个找到的点(轮廓的开头)

    5.1。如果不是,则只需在当前轮廓的数组中添加最后找到的点,然后转到步骤3

    5.2。如果是,则克隆当前轮廓的第一个点并将其添加到当前轮廓的数组中,将轮廓添加到轮廓阵列中。

  6. 检查我们是否已将所有点标记为已选中。

    6.1。如果不是,请转到第1步

    6.2。如果是,我们完成了。返回轮廓阵列。

  7. 设定交点的修改功能:

    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);
      };
    }
    

    如何获得轮廓以及如何绘制它们:

    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);
      });
    

    其中

    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;
    }
    

    enter image description here示例r87。