Beispiel #1
0
        //    *
        //	 * Executes the Constrained Delaunay Triangulation algorithm
        //	 * @param output A vector of index where is outputed the resulting triangle indexes
        //	 * @param outputVertices A vector of vertices where is outputed the resulting triangle vertices
        //	 * @exception Ogre::InvalidStateException Either shape or multishape or segment list must be defined
        //
        //void triangulate(ref List<int>& output, ref List<Vector2>& outputVertices) const;
        public void triangulate(std_vector <int> output, PointList outputVertices)
        {
            if (mShapeToTriangulate == null && mMultiShapeToTriangulate == null && mSegmentListToTriangulate == null)
            {
                throw new NullReferenceException("Ogre::Exception::ERR_INVALID_STATE," + "Either shape or multishape or segment list must be defined!" + ",  Procedural::Triangulator::triangulate(std::vector<int>&, PointList&)");
            }
            //Ogre::Timer mTimer;
            //Mogre.Timer mTimer = new Timer();
            //mTimer.Reset();
            DelaunayTriangleBuffer dtb = new std_list <Triangle>();
            // Do the Delaunay triangulation
            std_vector <int> segmentListIndices = new std_vector <int>();

            if (mShapeToTriangulate != null)
            {
                outputVertices = new std_vector <Vector2>(mShapeToTriangulate.getPoints());
                for (int i = 0; i < mShapeToTriangulate.getSegCount(); ++i)
                {
                    segmentListIndices.push_back(i);
                    segmentListIndices.push_back(mShapeToTriangulate.getBoundedIndex(i + 1));
                }
            }
            else if (mMultiShapeToTriangulate != null)
            {
                outputVertices = new std_vector <Vector2>(mMultiShapeToTriangulate.getPoints());
                int index = 0;
                for (int i = 0; i < mMultiShapeToTriangulate.getShapeCount(); ++i)
                {
                    Shape shape = mMultiShapeToTriangulate.getShape((uint)i);
                    for (int j = 0; j < shape.getSegCount(); j++)
                    {
                        segmentListIndices.push_back(index + j);
                        segmentListIndices.push_back(index + shape.getBoundedIndex(j + 1));
                    }
                    index += shape.getSegCount();
                }
            }
            else if (mSegmentListToTriangulate != null)
            {
                //std_map<Vector2, int, Vector2Comparator> backMap;
                std_map <Vector2, int> backMap = new std_map <Vector2, int>(new Vector2Comparator());
                //for (std::vector<Segment2D>::iterator it = mSegmentListToTriangulate->begin(); it!= mSegmentListToTriangulate->end(); it++)
                foreach (var it in mSegmentListToTriangulate)
                {
                    if ((it.mA - it.mB).SquaredLength < 1e-6)
                    {
                        continue;
                    }

                    //std::map<Vector2, int, Vector2Comparator>::iterator it2 = backMap.find(it->mA);
                    int it2_pos = backMap.find(it.mA);
                    //if (it2 != backMap.end())
                    if (it2_pos != -1)
                    {
                        //segmentListIndices.push_back(it2->second);
                        segmentListIndices.push_back(backMap[it.mA]);
                    }
                    else
                    {
                        //backMap[it->mA] = outputVertices.size();
                        backMap.insert(it.mA, outputVertices.size());
                        segmentListIndices.push_back(outputVertices.size());
                        outputVertices.push_back(it.mA);
                    }

                    //it2 = backMap.find(it.mB);
                    it2_pos = backMap.find(it.mB);
                    //if (it2 != backMap.end())
                    if (it2_pos != -1)
                    {
                        //segmentListIndices.push_back(it2.second);
                        segmentListIndices.push_back(backMap[it.mB]);
                    }
                    else
                    {
                        //backMap[it->mB] = outputVertices.size();
                        backMap.insert(it.mB, outputVertices.size());
                        segmentListIndices.push_back(outputVertices.size());
                        outputVertices.push_back(it.mB);
                    }
                }

                if (mManualSuperTriangle != null)
                {
                    Triangle superTriangle = new Triangle(outputVertices);
                    for (int i = 0; i < 3; i++)
                    {
                        //std::map<Vector2, int, Vector2Comparator>::iterator it = backMap.find(mManualSuperTriangle->mPoints[i]);
                        int it_pos = backMap.find(mManualSuperTriangle.mPoints[i]);
                        //if (it != backMap.end())
                        if (it_pos != -1)
                        {
                            //segmentListIndices.push_back(it->second);
                            //superTriangle.i[i] = it->second;
                            superTriangle.i[i] = backMap[mManualSuperTriangle.mPoints[i]];
                        }
                        else
                        {
                            //backMap[mManualSuperTriangle->mPoints[i]] = outputVertices.size();
                            backMap.insert(mManualSuperTriangle.mPoints[i], outputVertices.size());
                            //segmentListIndices.push_back(outputVertices.size());
                            superTriangle.i[i] = outputVertices.size();
                            outputVertices.push_back(mManualSuperTriangle.mPoints[i]);
                        }
                    }

                    dtb.push_back(superTriangle);
                }
            }
            //Utils::log("Triangulator preparation : " + StringConverter::toString(mTimer.getMicroseconds() / 1000.0f) + " ms");
            delaunay(outputVertices, ref dtb);
            //Utils::log("Triangulator delaunay : " + StringConverter::toString(mTimer.getMicroseconds() / 1000.0f) + " ms");
            // Add contraints
            _addConstraints(ref dtb, outputVertices, segmentListIndices);
            //Utils::log("Triangulator constraints : " + StringConverter::toString(mTimer.getMicroseconds() / 1000.0f) + " ms");
            //Outputs index buffer
            //for (DelaunayTriangleBuffer::iterator it = dtb.begin(); it!=dtb.end(); ++it)
            foreach (var it in dtb)
            {
                if (!it.isDegenerate())
                {
                    output.push_back(it.i[0]);
                    output.push_back(it.i[1]);
                    output.push_back(it.i[2]);
                }
            }
            // Remove super triangle
            if (mRemoveOutside)
            {
                outputVertices.pop_back();
                outputVertices.pop_back();
                outputVertices.pop_back();
            }
            //Utils::log("Triangulator output : " + StringConverter::toString(mTimer.getMicroseconds() / 1000.0f) + " ms");
        }
Beispiel #2
0
        //
        //ORIGINAL LINE: void delaunay(List<Ogre::Vector2>& pointList, LinkedList<Triangle>& tbuffer) const
        void delaunay(PointList pointList, ref DelaunayTriangleBuffer tbuffer)
        {
            // Compute super triangle or insert manual super triangle
            if (mManualSuperTriangle != null)
            {
                float maxTriangleSize = 0.0f;
                //for (PointList::iterator it = pointList.begin(); it!=pointList.end(); ++it)
                foreach (Vector2 it in pointList)
                {
                    maxTriangleSize = max(maxTriangleSize, Math.Abs(it.x));
                    maxTriangleSize = max(maxTriangleSize, Math.Abs(it.y));
                }
                pointList.push_back(new Vector2(-3f * maxTriangleSize, -3f * maxTriangleSize));
                pointList.push_back(new Vector2(3f * maxTriangleSize, -3f * maxTriangleSize));
                pointList.push_back(new Vector2(0.0f, 3 * maxTriangleSize));

                int      maxTriangleIndex = pointList.size() - 3;
                Triangle superTriangle    = new Triangle(pointList);
                superTriangle.i[0] = maxTriangleIndex;
                superTriangle.i[1] = maxTriangleIndex + 1;
                superTriangle.i[2] = maxTriangleIndex + 2;
                tbuffer.push_back(superTriangle);
            }

            // Point insertion loop
            for (int i = 0; i < pointList.size() - 3; i++)
            {
                //Utils::log("insert point " + StringConverter::toString(i));
                //std::list<std::list<Triangle>::iterator> borderlineTriangles;
                std_list <Triangle> borderlineTriangles = new std_list <Triangle>();
                // Insert 1 point, find all triangles for which the point is in circumcircle
                Vector2 p = pointList[i];
                //std::set<DelaunaySegment> segments;
                std_set <DelaunaySegment> segments = new std_set <DelaunaySegment>();
                IEnumerator <Triangle>    et       = tbuffer.GetEnumerator();
                //for (DelaunayTriangleBuffer::iterator it = tbuffer.begin(); it!=tbuffer.end();)
                List <Triangle> need_erase = new List <Triangle>();
                while (et.MoveNext())
                {
                    Triangle            it       = et.Current;
                    Triangle.InsideType isInside = it.isPointInsideCircumcircle(p);
                    if (isInside == Triangle.InsideType.IT_INSIDE)
                    {
                        if (!it.isDegenerate())
                        {
                            //Utils::log("tri insie" + it->debugDescription());
                            for (int k = 0; k < 3; k++)
                            {
                                DelaunaySegment d1 = new DelaunaySegment(it.i[k], it.i[(k + 1) % 3]);
                                if (segments.find(d1) != segments.end())
                                {
                                    segments.erase(d1);
                                }
                                else if (segments.find(d1.inverse()) != segments.end())
                                {
                                    segments.erase(d1.inverse());
                                }
                                else
                                {
                                    segments.insert(d1);
                                }
                            }
                        }
                        //it=tbuffer.erase(it);
                        need_erase.Add(it);
                    }
                    else if (isInside == Triangle.InsideType.IT_BORDERLINEOUTSIDE)
                    {
                        //Utils::log("tri borer " + it->debugDescription());
                        borderlineTriangles.push_back(it);
                        //++it;
                    }
                    else
                    {
                        //++it;
                    }
                }
                //do delete
                foreach (var v in need_erase)
                {
                    tbuffer.Remove(v);
                }

                // Robustification of the standard algorithm : if one triangle's circumcircle was borderline against the new point,
                // test whether that triangle is intersected by new segments or not (normal situation : it should not)
                // If intersected, the triangle is considered having the new point in its circumc
                std_set <DelaunaySegment> copySegment = segments;
                IEnumerator <Triangle>    be          = borderlineTriangles.GetEnumerator();
                //for (std::list<std::list<Triangle>::iterator>::iterator itpTri = borderlineTriangles.begin(); itpTri!=borderlineTriangles.end(); itpTri++ )
                while (be.MoveNext())
                {
                    Triangle itpTri = be.Current;
                    //DelaunayTriangleBuffer::iterator itTri = *itpTri;
                    Triangle itTri      = itpTri;
                    bool     triRemoved = false;
                    //for (std::set<DelaunaySegment>::iterator it = copySegment.begin(); it!=copySegment.end() && !triRemoved; ++it)
                    IEnumerator <DelaunaySegment> cse = copySegment.GetEnumerator();
                    while (cse.MoveNext() && !triRemoved)
                    {
                        DelaunaySegment it = cse.Current;
                        bool            isTriangleIntersected = false;
                        for (int k = 0; k < 2; k++)
                        {
                            int i1 = (k == 0) ? it.i1 : it.i2;
                            int i2 = i;
                            for (int l = 0; l < 3; l++)
                            {
                                //Early out if 2 points are in fact the same
                                if (itTri.i[l] == i1 || itTri.i[l] == i2 || itTri.i[(l + 1) % 3] == i1 || itTri.i[(l + 1) % 3] == i2)
                                {
                                    continue;
                                }
                                Segment2D seg2 = new Segment2D(itTri.p(l), itTri.p((l + 1) % 3));
                                Segment2D seg1 = new Segment2D(pointList[i1], pointList[i2]);
                                if (seg1.intersects(seg2))
                                {
                                    isTriangleIntersected = true;
                                    break;
                                }
                            }
                        }
                        if (isTriangleIntersected)
                        {
                            if (!itTri.isDegenerate())
                            {
                                //Utils::log("tri inside" + itTri->debugDescription());
                                for (int m = 0; m < 3; m++)
                                {
                                    DelaunaySegment d1 = new DelaunaySegment(itTri.i[m], itTri.i[(m + 1) % 3]);
                                    if (segments.find(d1) != segments.end())
                                    {
                                        segments.erase(d1);
                                    }
                                    else if (segments.find(d1.inverse()) != segments.end())
                                    {
                                        segments.erase(d1.inverse());
                                    }
                                    else
                                    {
                                        segments.insert(d1);
                                    }
                                }
                            }
                            //tbuffer.erase(itTri);
                            need_erase.Clear();
                            need_erase.Add(itTri);
                            triRemoved = true;
                        }
                    }
                }
                //do delete
                foreach (var v in need_erase)
                {
                    tbuffer.Remove(v);
                }
                // Find all the non-interior edges
                IEnumerator <DelaunaySegment> seg_ie = segments.GetEnumerator();
                //for (std::set<DelaunaySegment>::iterator it = segments.begin(); it!=segments.end(); ++it)
                while (seg_ie.MoveNext())
                {
                    DelaunaySegment it = seg_ie.Current;
                    //Triangle dt(&pointList);
                    Triangle dt = new Triangle(pointList);
                    dt.setVertices(it.i1, it.i2, i);
                    dt.makeDirectIfNeeded();
                    //Utils::log("Add tri " + dt.debugDescription());
                    tbuffer.push_back(dt);
                }
            }

            // NB : Don't remove super triangle here, because all outer triangles are already removed in the addconstraints method.
            //      Uncomment that code if delaunay triangulation ever has to be unconstrained...

            /*TouchSuperTriangle touchSuperTriangle(maxTriangleIndex, maxTriangleIndex+1,maxTriangleIndex+2);
             * tbuffer.remove_if(touchSuperTriangle);
             * pointList.pop_back();
             * pointList.pop_back();
             * pointList.pop_back();*/
        }