切平面三个js后的分组点 [英] Grouping points after cut plane three js

查看:23
本文介绍了切平面三个js后的分组点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我找到了物体和平面之间的所有交点,就像在这个很棒的

想法:

当我们获得交点时,我们会向每个点添加有关该点属于哪个面的信息.这意味着始终存在具有相同人脸索引的点对.

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

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

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

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

  3. 找到一个未选中的点,离最后找到的点最近的点.将其标记为已检查 .checked = true.

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

  5. 检查,最后找到的点是否等于(有一些容差)第一个找到的点(轮廓的开始)

    5.1.如果没有,则只需在当前轮廓的数组中添加最后找到的点并转到步骤 3.

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

  6. 检查,如果我们已将所有点标记为已检查.

    6.1.如果否,则转到步骤 1.

    6.2.如果是,我们就完成了.返回轮廓数组.

修改设置交点功能:

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

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

var contours = getContours(pointsOfIntersection.vertices, [], true);轮廓.forEach(cntr => {让 cntrGeom = new THREE.Geometry();cntrGeom.vertices = cntr;让轮廓 = new THREE.Line(cntrGeom, new THREE.LineBasicMaterial({颜色:Math.random() * 0xffffff}));场景添加(轮廓);});

哪里

function getContours(points, contours, firstRun) {console.log("firstRun:", firstRun);让轮廓 = [];//找到轮廓的第一行让 firstPointIndex = 0;让第二点索引 = 0;让第一点,第二点;for (let i = 0; i  { allChecked += p.checked == true ? 1 : 0; });console.log("allChecked: ", allChecked == points.length);if (allChecked != points.length) { return getContours(points, contours, false);}返回轮廓;}函数getContour(当前点,点,轮廓){让 p1Index = getNearestPointIndex(currentPoint, points);让 p1 = 点 [p1Index];p1.checked = true;让 p2Index = getPairIndex(p1, p1Index, points);让 p2 = 点 [p2Index];p2.checked = true;让 isClosed = p2.equals(contour[0],tolerance);如果(!isClosed){轮廓.push(p2.clone());返回 getContour(p2, 点, 轮廓);} 别的 {轮廓.推(轮廓[0].克隆());返回轮廓;}}函数 getNearestPointIndex(point, points){让索引 = 0;for (let i = 0; i 

jsfiddle 示例 r87.

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 arrays) where the plane passes and connect them again. I tried to connect them by distance, but this does not give an effective result

//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. Ideas? Examples? Thank in advance for your replies!

解决方案

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.

这篇关于切平面三个js后的分组点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆