So yes, this answer is based on this and extends it. The solution is crude and can be optimized.
I used the modified .equals() method THREE.Vector3() (I hope that it (or something like that) will become part of the kernel one day, as this is a very useful function), taken from here :
THREE.Vector3.prototype.equals = function(v, tolerance) { if (tolerance === undefined) { return ((vx === this.x) && (vy === this.y) && (vz === this.z)); } else { return ((Math.abs(vx - this.x) < tolerance) && (Math.abs(vy - this.y) < tolerance) && (Math.abs(vz - this.z) < tolerance)); } }

Idea:
When we get the intersection points, we add information to each point about which face the point belongs to. This means that there are always pairs of points with the same face index.
Then we recursively find all the contours that form our points.
In addition, all points are marked as unchecked ( .checked = false ).
Find the first unverified point. Add it to the array of the current path.
Find your pair (with the same facial index). Add it to the array of the current path.
Find the unverified point closest to the last point found. Makr is as noted .checked = true .
Find your pair (with the same facial index). Mark it as checked .checked = true .
Check if the last found point is (with some tolerance) the first found point (beginning of the contour)
5.1. If not, just add the last found point to the array of the current path and go to step 3 .
5.2. If yes, then clone the first point of the current path and add it to the array of the current path, add the path to the path array.
Check if we have all the points marked as marked.
6.1. If not, go to step 1 .
6.2. If yes, we are done. Returns an array of paths.
Modified Intersection Point Function:
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 r87 example.