public Intersect(Segment3D seg, int tri1, int tri2) { //mSeg = new Segment3D(seg); mSeg.mA = seg.mA; mSeg.mB = seg.mB; mTri1 = tri1; mTri2 = tri2; }
// //ORIGINAL LINE: bool findIntersect(const Triangle3D& STLAllocator<U, AllocPolicy>, Segment3D& intersection) const public bool findIntersect(Triangle3D triangle3d, ref Segment3D intersection) { // Compute plane equation of first triangle Vector3 e1 = mPoints[1] - mPoints[0]; Vector3 e2 = mPoints[2] - mPoints[0]; Vector3 n1 = e1.CrossProduct(e2); float d1 = -n1.DotProduct(mPoints[0]); // Put second triangle in first plane equation to compute distances to the plane float[] du = new float[3]; for (short i = 0; i < 3; i++) { du[i] = n1.DotProduct(triangle3d.mPoints[i]) + d1; if (Math.Abs(du[i]) < 1e-6) { du[i] = 0.0f; } } float du0du1 = du[0] * du[1]; float du0du2 = du[0] * du[2]; if (du0du1 > 0.0f && du0du2 > 0.0f) // same sign on all of them + not equal 0 ? { return(false); // no intersection occurs } // Compute plane equation of first triangle e1 = triangle3d.mPoints[1] - triangle3d.mPoints[0]; e2 = triangle3d.mPoints[2] - triangle3d.mPoints[0]; Vector3 n2 = e1.CrossProduct(e2); float d2 = -n2.DotProduct(triangle3d.mPoints[0]); // Put first triangle in second plane equation to compute distances to the plane float[] dv = new float[3]; for (short i = 0; i < 3; i++) { dv[i] = n2.DotProduct(mPoints[i]) + d2; if (Math.Abs(dv[i]) < 1e-6) { dv[i] = 0.0f; } } float dv0dv1 = dv[0] * dv[1]; float dv0dv2 = dv[0] * dv[2]; if (dv0dv1 > 0.0f && dv0dv2 > 0.0f) // same sign on all of them + not equal 0 ? { return(false); // no intersection occurs } //Compute the direction of intersection line Vector3 d = n1.CrossProduct(n2); // We don't do coplanar triangles if (d.SquaredLength < 1e-6) { return(false); } // Project triangle points onto the intersection line // compute and index to the largest component of D float max = Math.Abs(d[0]); int index = 0; float b = Math.Abs(d[1]); float c = Math.Abs(d[2]); if (b > max) { max = b; index = 1; } if (c > max) { max = c; index = 2; } // this is the simplified projection onto L float vp0 = mPoints[0][index]; float vp1 = mPoints[1][index]; float vp2 = mPoints[2][index]; float up0 = triangle3d.mPoints[0][index]; float up1 = triangle3d.mPoints[1][index]; float up2 = triangle3d.mPoints[2][index]; float[] isect1 = new float[2]; float[] isect2 = new float[2]; // compute interval for triangle 1 GlobalMembers.computeIntervals(vp0, vp1, vp2, dv[0], dv[1], dv[2], dv0dv1, dv0dv2, ref isect1[0], ref isect1[1]); // compute interval for triangle 2 GlobalMembers.computeIntervals(up0, up1, up2, du[0], du[1], du[2], du0du1, du0du2, ref isect2[0], ref isect2[1]); if (isect1[0] > isect1[1]) { std_array_swap <float>(isect1, 0, 1); } if (isect2[0] > isect2[1]) { std_array_swap <float>(isect2, 0, 1); } if (isect1[1] < isect2[0] || isect2[1] < isect1[0]) { return(false); } // Deproject segment onto line float r1 = System.Math.Max(isect1[0], isect2[0]); float r2 = System.Math.Min(isect1[1], isect2[1]); Plane pl1 = new Plane(n1.x, n1.y, n1.z, d1); Plane pl2 = new Plane(n2.x, n2.y, n2.z, d2); Line interLine = new Line(); pl1.intersect(pl2, ref interLine); Vector3 p = interLine.mPoint; //d.Normalise(); d = d.NormalisedCopy; Vector3 v1 = p + (r1 - p[index]) / d[index] * d; Vector3 v2 = p + (r2 - p[index]) / d[index] * d; intersection.mA = v1; intersection.mB = v2; return(true); }
// //ORIGINAL LINE: bool epsilonEquivalent(const Segment3D& STLAllocator<U, AllocPolicy>) const public bool epsilonEquivalent(Segment3D segment3D) { return(((mA - segment3D.mA).SquaredLength < 1e-8 && (mB - segment3D.mB).SquaredLength < 1e-8) || ((mA - segment3D.mB).SquaredLength < 1e-8 && (mB - segment3D.mA).SquaredLength < 1e-8)); }
//----------------------------------------------------------------------- // //ORIGINAL LINE: void addToTriangleBuffer(TriangleBuffer& buffer) const public override void addToTriangleBuffer(ref TriangleBuffer buffer) { std_vector <TriangleBuffer.Vertex> vec1 = mMesh1.getVertices(); std_vector <int> ind1 = mMesh1.getIndices(); std_vector <TriangleBuffer.Vertex> vec2 = mMesh2.getVertices(); std_vector <int> ind2 = mMesh2.getIndices(); Segment3D intersectionResult = new Segment3D(); std_vector <Intersect> intersectionList = new std_vector <Intersect>(); // Find all intersections between mMesh1 and mMesh2 int idx1 = 0; //for (std::vector<int>::const_iterator it = ind1.begin(); it != ind1.end(); idx1++) for (int i = 0; i < ind1.Count; i += 3, idx1++) { int it = ind1[i]; //Triangle3D t1(vec1[*it++].mPosition, vec1[*it++].mPosition, vec1[*it++].mPosition); Triangle3D t1 = new Triangle3D(vec1[it].mPosition, vec1[it + 1].mPosition, vec1[it + 2].mPosition); int idx2 = 0; //for (std::vector<int>::const_iterator it2 = ind2.begin(); it2 != ind2.end(); idx2++) for (int j = 0; j < ind2.Count; j += 3, idx2++) { int it2 = ind2[j]; //Triangle3D t2(vec2[*it2++].mPosition, vec2[*it2++].mPosition, vec2[*it2++].mPosition); Triangle3D t2 = new Triangle3D(vec2[it2].mPosition, vec2[it2 + 1].mPosition, vec2[it2 + 2].mPosition); if (t1.findIntersect(t2, ref intersectionResult)) { Intersect intersect = new Intersect(intersectionResult, idx1, idx2); intersectionList.push_back(intersect); } } } // Remove all intersection segments too small to be relevant //for (std::vector<Intersect>::iterator it = intersectionList.begin(); it != intersectionList.end();) // if ((it.mSeg.mB - it.mSeg.mA).squaredLength() < 1e-8) // it = intersectionList.erase(it); // else // ++it; for (int i = intersectionList.Count - 1; i >= 0; i--) { Intersect it = intersectionList[i]; if ((it.mSeg.mB - it.mSeg.mA).SquaredLength < 1e-8) { intersectionList.erase((uint)i); } } // Retriangulate TriangleBuffer newMesh1 = new TriangleBuffer(); TriangleBuffer newMesh2 = new TriangleBuffer(); GlobalMembersProceduralBoolean._retriangulate(ref newMesh1, mMesh1, intersectionList, true); GlobalMembersProceduralBoolean._retriangulate(ref newMesh2, mMesh2, intersectionList, false); //buffer.append(newMesh1); //buffer.append(newMesh2); //return; // Trace contours std_vector <Path> contours = new std_vector <Path>(); std_vector <Segment3D> segmentSoup = new std_vector <Segment3D>(); //for (std::vector<Intersect>::iterator it = intersectionList.begin(); it != intersectionList.end(); ++it) foreach (var it in intersectionList) { segmentSoup.push_back(it.mSeg); } new Path().buildFromSegmentSoup(segmentSoup, ref contours); // Build a lookup from segment to triangle TriLookup triLookup1 = new std_multimap <Segment3D, int>(new Seg3Comparator()), triLookup2 = new std_multimap <Segment3D, int>(new Seg3Comparator()); GlobalMembersProceduralBoolean._buildTriLookup(ref triLookup1, newMesh1); GlobalMembersProceduralBoolean._buildTriLookup(ref triLookup2, newMesh2); std_set <Segment3D> limits = new std_set <Segment3D>(new Seg3Comparator()); //for (std::vector<Segment3D>::iterator it = segmentSoup.begin(); it != segmentSoup.end(); ++it) foreach (var it in segmentSoup) { limits.insert(it.orderedCopy()); } // Build resulting mesh //for (std::vector<Path>::iterator it = contours.begin(); it != contours.end(); ++it) foreach (var it in contours) { // Find 2 seed triangles for each contour Segment3D firstSeg = new Segment3D(it.getPoint(0), it.getPoint(1)); //std_pair<TriLookup::iterator, TriLookup::iterator> it2mesh1 = triLookup1.equal_range(firstSeg.orderedCopy()); //std_pair<TriLookup::iterator, TriLookup::iterator> it2mesh2 = triLookup2.equal_range(firstSeg.orderedCopy()); std_pair <std_pair <Segment3D, List <int> >, std_pair <Segment3D, List <int> > > it2mesh1 = triLookup1.equal_range(firstSeg.orderedCopy()); std_pair <std_pair <Segment3D, List <int> >, std_pair <Segment3D, List <int> > > it2mesh2 = triLookup2.equal_range(firstSeg.orderedCopy()); int mesh1seed1 = 0, mesh1seed2 = 0, mesh2seed1 = 0, mesh2seed2 = 0; //if (it2mesh1.first != triLookup1.end() && it2mesh2.first != triLookup2.end()) if (it2mesh1.first != null && it2mesh2.first != null) { // check which of seed1 and seed2 must be included (it can be 0, 1 or both) //mesh1seed1 = it2mesh1.first.second; //mesh1seed2 = (--it2mesh1.second).second; //mesh2seed1 = it2mesh2.first.second; //mesh2seed2 = (--it2mesh2.second).second; mesh1seed1 = it2mesh1.first.second[0]; mesh1seed2 = it2mesh1.first.second[it2mesh1.first.second.Count - 1]; //(--it2mesh1.second).second[0]; mesh2seed1 = it2mesh2.first.second[0]; mesh2seed2 = it2mesh2.first.second[it2mesh2.first.second.Count - 1]; //(--it2mesh2.second).second[0]; if (mesh1seed1 == mesh1seed2) { mesh1seed2 = -1; } if (mesh2seed1 == mesh2seed2) { mesh2seed2 = -1; } Vector3 vMesh1 = new Vector3(0f, 0f, 0f), nMesh1 = new Vector3(0f, 0f, 0f), vMesh2 = new Vector3(0f, 0f, 0f), nMesh2 = new Vector3(0f, 0f, 0f); for (int i = 0; i < 3; i++) { Vector3 pos = newMesh1.getVertices()[newMesh1.getIndices()[mesh1seed1 * 3 + i]].mPosition; if ((pos - firstSeg.mA).SquaredLength > 1e-6 && (pos - firstSeg.mB).SquaredLength > 1e-6) { vMesh1 = pos; nMesh1 = newMesh1.getVertices()[newMesh1.getIndices()[mesh1seed1 * 3 + i]].mNormal; break; } } for (int i = 0; i < 3; i++) { Vector3 pos = newMesh2.getVertices()[newMesh2.getIndices()[mesh2seed1 * 3 + i]].mPosition; if ((pos - firstSeg.mA).SquaredLength > 1e-6 && (pos - firstSeg.mB).SquaredLength > 1e-6) { vMesh2 = pos; nMesh2 = newMesh2.getVertices()[newMesh2.getIndices()[mesh2seed1 * 3 + i]].mNormal; break; } } bool M2S1InsideM1 = (nMesh1.DotProduct(vMesh2 - firstSeg.mA) < 0f); bool M1S1InsideM2 = (nMesh2.DotProduct(vMesh1 - firstSeg.mA) < 0f); GlobalMembersProceduralBoolean._removeFromTriLookup(mesh1seed1, ref triLookup1); GlobalMembersProceduralBoolean._removeFromTriLookup(mesh2seed1, ref triLookup2); GlobalMembersProceduralBoolean._removeFromTriLookup(mesh1seed2, ref triLookup1); GlobalMembersProceduralBoolean._removeFromTriLookup(mesh2seed2, ref triLookup2); // Recursively add all neighbours of these triangles // Stop when a contour is touched switch (mBooleanOperation) { case BooleanOperation.BT_UNION: if (M1S1InsideM2) { GlobalMembersProceduralBoolean._recursiveAddNeighbour(ref buffer, newMesh1, mesh1seed2, ref triLookup1, limits, false); } else { GlobalMembersProceduralBoolean._recursiveAddNeighbour(ref buffer, newMesh1, mesh1seed1, ref triLookup1, limits, false); } if (M2S1InsideM1) { GlobalMembersProceduralBoolean._recursiveAddNeighbour(ref buffer, newMesh2, mesh2seed2, ref triLookup2, limits, false); } else { GlobalMembersProceduralBoolean._recursiveAddNeighbour(ref buffer, newMesh2, mesh2seed1, ref triLookup2, limits, false); } break; case BooleanOperation.BT_INTERSECTION: if (M1S1InsideM2) { GlobalMembersProceduralBoolean._recursiveAddNeighbour(ref buffer, newMesh1, mesh1seed1, ref triLookup1, limits, false); } else { GlobalMembersProceduralBoolean._recursiveAddNeighbour(ref buffer, newMesh1, mesh1seed2, ref triLookup1, limits, false); } if (M2S1InsideM1) { GlobalMembersProceduralBoolean._recursiveAddNeighbour(ref buffer, newMesh2, mesh2seed1, ref triLookup2, limits, false); } else { GlobalMembersProceduralBoolean._recursiveAddNeighbour(ref buffer, newMesh2, mesh2seed2, ref triLookup2, limits, false); } break; case BooleanOperation.BT_DIFFERENCE: if (M1S1InsideM2) { GlobalMembersProceduralBoolean._recursiveAddNeighbour(ref buffer, newMesh1, mesh1seed2, ref triLookup1, limits, false); } else { GlobalMembersProceduralBoolean._recursiveAddNeighbour(ref buffer, newMesh1, mesh1seed1, ref triLookup1, limits, false); } if (M2S1InsideM1) { GlobalMembersProceduralBoolean._recursiveAddNeighbour(ref buffer, newMesh2, mesh2seed1, ref triLookup2, limits, true); } else { GlobalMembersProceduralBoolean._recursiveAddNeighbour(ref buffer, newMesh2, mesh2seed2, ref triLookup2, limits, true); } break; } } } }
//----------------------------------------------------------------------- public static Segment2D projectOnAxis(Segment3D input, Vector3 origin, Vector3 axis1, Vector3 axis2) { return(new Segment2D(projectOnAxis(input.mA, origin, axis1, axis2), projectOnAxis(input.mB, origin, axis1, axis2))); }