//
        //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);
        }
Beispiel #2
0
        //-----------------------------------------------------------------------

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