예제 #1
0
        //    *
        //	 * Determines whether the outside as defined by user equals "real" outside
        //

        //-----------------------------------------------------------------------

        //
        //ORIGINAL LINE: bool isOutsideRealOutside() const
        public bool isOutsideRealOutside()
        {
            float x          = float.MinValue;//std.numeric_limits<float>.min();
            int   index      = 0;
            int   shapeIndex = 0;

            for (int j = 0; j < mShapes.size(); j++)
            {
                Shape s = mShapes[j];
                std_vector <Vector2> points = s.getPointsReference();
                for (int i = 0; i < points.Count; i++)
                {
                    if (x < points[i].x)
                    {
                        x          = points[i].x;
                        index      = i;
                        shapeIndex = j;
                    }
                }
            }
            Radian alpha1 = Utils.angleTo(Vector2.UNIT_Y, mShapes[shapeIndex].getDirectionAfter((uint)index));
            Radian alpha2 = Utils.angleTo(Vector2.UNIT_Y, -mShapes[shapeIndex].getDirectionBefore((uint)index));
            Side   shapeSide;

            if (alpha1 < alpha2)
            {
                shapeSide = Side.SIDE_RIGHT;
            }
            else
            {
                shapeSide = Side.SIDE_LEFT;
            }
            return(shapeSide == mShapes[shapeIndex].getOutSide());
        }
예제 #2
0
        //-----------------------------------------------------------------------

        public static void _buildTriLookup(ref TriLookup lookup, TriangleBuffer newMesh)
        {
            std_vector <TriangleBuffer.Vertex> nvec = newMesh.getVertices();
            std_vector <int> nind = newMesh.getIndices();

            for (int i = 0; i < (int)nind.Count / 3; i++)
            {
                lookup.insert(new Segment3D(nvec[nind[i * 3]].mPosition, nvec[nind[i * 3 + 1]].mPosition).orderedCopy(), i);
                lookup.insert(new KeyValuePair <Segment3D, int>(new Segment3D(nvec[nind[i * 3]].mPosition, nvec[nind[i * 3 + 2]].mPosition).orderedCopy(), i));
                lookup.insert(new KeyValuePair <Segment3D, int>(new Segment3D(nvec[nind[i * 3 + 1]].mPosition, nvec[nind[i * 3 + 2]].mPosition).orderedCopy(), i));
            }
        }
예제 #3
0
        /// Builds an aggregated list of all points contained in all shapes
        //-----------------------------------------------------------------------

        //
        //ORIGINAL LINE: List<Vector2> getPoints() const
        public std_vector <Vector2> getPoints()
        {
            std_vector <Vector2> result = new std_vector <Vector2>();

            for (int i = 0; i < mShapes.Count; i++)
            {
                Vector2[] points = mShapes[i].getPoints();
                //
                //result.insert(result.end(), points.GetEnumerator(), points.end());
                result.AddRange(points);
            }
            return(result);
        }
        //-----------------------------------------------------------------------
        //
        //ORIGINAL LINE: MultiShape _booleanOperation(const Shape& STLAllocator<U, AllocPolicy>, BooleanOperationType opType) const
        private MultiShape _booleanOperation(Shape other, BooleanOperationType opType) {
            if (!mClosed || mPoints.size() < 2)
                OGRE_EXCEPT("Ogre::Exception::ERR_INVALID_STATE", "Current shapes must be closed and has to contain at least 2 points!", "Procedural::Shape::_booleanOperation(const Procedural::Shape&, Procedural::BooleanOperationType)");
            if (!other.mClosed || other.mPoints.size() < 2)
                OGRE_EXCEPT("Ogre::Exception::ERR_INVALIDPARAMS", "Other shapes must be closed and has to contain at least 2 points!", "Procedural::Shape::_booleanOperation(const Procedural::Shape&, Procedural::BooleanOperationType)");
            ;

            // Compute the intersection between the 2 shapes
            std_vector<IntersectionInShape> intersections = new std_vector<IntersectionInShape>();
            _findAllIntersections(other, ref intersections);

            // Build the resulting shape
            if (intersections.empty()) {
                if (isPointInside(other.getPoint(0))) {
                    // Shape B is completely inside shape A
                    if (opType == BooleanOperationType.BOT_UNION) {
                        MultiShape ms = new MultiShape();
                        ms.addShape(this);
                        return ms;
                    }
                    else if (opType == BooleanOperationType.BOT_INTERSECTION) {
                        MultiShape ms = new MultiShape();
                        ms.addShape(other);
                        return ms;
                    }
                    else if (opType == BooleanOperationType.BOT_DIFFERENCE) {
                        MultiShape ms = new MultiShape();
                        ms.addShape(this);
                        ms.addShape(other);
                        ms.getShape(1).switchSide();
                        return ms;
                    }

                }
                else if (other.isPointInside(getPoint(0))) {
                    // Shape A is completely inside shape B
                    if (opType == BooleanOperationType.BOT_UNION) {
                        MultiShape ms = new MultiShape();
                        ms.addShape(other);
                        return ms;
                    }
                    else if (opType == BooleanOperationType.BOT_INTERSECTION) {
                        MultiShape ms = new MultiShape();
                        ms.addShape(this);
                        return ms;
                    }
                    else if (opType == BooleanOperationType.BOT_DIFFERENCE) {
                        MultiShape ms = new MultiShape();
                        ms.addShape(this);
                        ms.addShape(other);
                        ms.getShape(0).switchSide();
                        return ms;
                    }
                }
                else {
                    if (opType == BooleanOperationType.BOT_UNION) {
                        MultiShape ms = new MultiShape();
                        ms.addShape(this);
                        ms.addShape(other);
                        return ms;
                    }
                    else if (opType == BooleanOperationType.BOT_INTERSECTION)
                        return new MultiShape(); //empty result
                    else if (opType == BooleanOperationType.BOT_DIFFERENCE)
                        return new MultiShape(); //empty result
                }
            }
            MultiShape outputMultiShape = new MultiShape();

            Shape[] inputShapes = new Shape[2];
            inputShapes[0] = this;
            inputShapes[1] = other;

            while (!intersections.empty()) {
                Shape outputShape = new Shape();
                byte shapeSelector = 0; // 0 : first shape, 1 : second shape

                Vector2 currentPosition = intersections[0].position;//intersections.GetEnumerator().position;
                IntersectionInShape firstIntersection = intersections[0];//*intersections.GetEnumerator();
                uint currentSegment = firstIntersection.index[shapeSelector];
                //C++ TO C# CONVERTER TODO TASK: There is no direct equivalent to the STL vector 'erase' method in C#:
                //intersections.erase(intersections.GetEnumerator());//ÒƳý
                intersections.erase(firstIntersection, true);
                outputShape.addPoint(currentPosition);

                sbyte isIncreasing = 0; // +1 if increasing, -1 if decreasing, 0 if undefined

                if (!_findWhereToGo(inputShapes, opType, firstIntersection, ref shapeSelector, ref isIncreasing, ref currentSegment)) {
                    // That intersection is located on a place where the resulting shape won't go => discard
                    continue;
                }

                while (true) {
                    // find the closest intersection on the same segment, in the correct direction
                    //List<IntersectionInShape>.Enumerator found_next_intersection = intersections.end();
                    IntersectionInShape found_next_intersection = intersections[intersections.Count - 1];
                    int found_next_intersection_pos = -1;
                    float distanceToNextIntersection = float.MaxValue;// std.numeric_limits<Real>.max();

                    uint nextPoint = currentSegment + (uint)(isIncreasing == 1 ? 1 : 0);
                    bool nextPointIsOnIntersection = false;

                    //for (List<IntersectionInShape>.Enumerator it = intersections.GetEnumerator(); it.MoveNext(); ++it)
                    for (int i = 0; i < intersections.Count; i++) {
                        IntersectionInShape it = intersections[i];
                        if (currentSegment == it.index[shapeSelector]) {
                            if (((it.position - currentPosition).DotProduct(it.position - inputShapes[shapeSelector].getPoint((int)nextPoint)) < 0f) || (it.onVertex[shapeSelector] && nextPoint == it.index[shapeSelector])) {
                                // found an intersection between the current one and the next segment point
                                float d = (it.position - currentPosition).Length;
                                if (d < distanceToNextIntersection) {
                                    // check if we have the nearest intersection
                                    found_next_intersection = it;
                                    found_next_intersection_pos = i;
                                    distanceToNextIntersection = d;
                                }
                            }
                        }
                        if (nextPoint == it.index[shapeSelector] && it.onVertex[shapeSelector])
                            nextPointIsOnIntersection = true;
                    }

                    // stop condition
                    if (currentSegment == firstIntersection.index[shapeSelector]) {
                        // we found ourselves on the same segment as the first intersection and no other
                        if ((firstIntersection.position - currentPosition).DotProduct(firstIntersection.position - inputShapes[shapeSelector].getPoint((int)nextPoint)) < 0f) {
                            float d = (firstIntersection.position - currentPosition).Length;
                            if (d > 0.0f && d < distanceToNextIntersection) {
                                outputShape.close();
                                break;
                            }
                        }
                    }

                    // We actually found the next intersection => change direction and add current intersection to the list
                    //if (found_next_intersection.MoveNext())
                    //if (intersections.Count > 1) {
                    if (found_next_intersection_pos != -1) {
                        //IntersectionInShape currentIntersection = found_next_intersection.Current;
                        IntersectionInShape currentIntersection = found_next_intersection;

                        intersections.erase(found_next_intersection, true);
                        //IntersectionInShape currentIntersection = intersections[intersections.Count - 1];
                        outputShape.addPoint(currentIntersection.position);
                        bool result = _findWhereToGo(inputShapes, opType, currentIntersection, ref shapeSelector, ref isIncreasing, ref currentSegment);
                        if (result == null) {
                            OGRE_EXCEPT("Ogre::Exception::ERR_INTERNAL_ERROR", "We should not be here!", "Procedural::Shape::_booleanOperation(const Procedural::Shape&, Procedural::BooleanOperationType)");
                            ;
                        }
                    }
                    else {
                        // no intersection found for the moment => just continue on the current segment
                        if (!nextPointIsOnIntersection) {
                            if (isIncreasing == 1)
                                currentPosition = inputShapes[shapeSelector].getPoint((int)currentSegment + 1);
                            else
                                currentPosition = inputShapes[shapeSelector].getPoint((int)currentSegment);

                            outputShape.addPoint(currentPosition);
                        }
                        currentSegment = (uint)Utils.modulo((int)currentSegment + isIncreasing, inputShapes[shapeSelector].getSegCount());
                    }
                }

                outputMultiShape.addShape(outputShape);
            }
            return outputMultiShape;
        }
 public Shape addPointRel(std_vector<Vector2> pointList) {
     if (mPoints.Count == 0) {
         mPoints.AddRange(pointList.ToArray());
     }
     else {
         Vector2 refVector = mPoints[mPoints.size() - 1];
         foreach (var it in pointList) {
             addPoint(it + refVector);
         }
     }
     return this;
 }
        //-----------------------------------------------------------------------
        //
        //ORIGINAL LINE: void _findAllIntersections(const Shape& STLAllocator<U, AllocPolicy>, List<IntersectionInShape>& intersections) const
        private void _findAllIntersections(Shape other, ref std_vector<IntersectionInShape> intersections) {
            for (ushort i = 0; i < getSegCount(); i++) {
                Segment2D seg1 = new Segment2D(getPoint(i), getPoint(i + 1));

                for (ushort j = 0; j < other.getSegCount(); j++) {
                    Segment2D seg2 = new Segment2D(other.getPoint(j), other.getPoint(j + 1));

                    Vector2 intersect = new Vector2();
                    if (seg1.findIntersect(seg2, ref intersect)) {
                        IntersectionInShape inter = new IntersectionInShape(i, j, intersect);
                        // check if intersection is "borderline" : too near to a vertex
                        if ((seg1.mA - intersect).SquaredLength < 1e-8) {
                            inter.onVertex[0] = true;
                        }
                        if ((seg1.mB - intersect).SquaredLength < 1e-8) {
                            inter.onVertex[0] = true;
                            inter.index[0]++;
                        }
                        if ((seg2.mA - intersect).SquaredLength < 1e-8) {
                            inter.onVertex[1] = true;
                        }
                        if ((seg2.mB - intersect).SquaredLength < 1e-8) {
                            inter.onVertex[1] = true;
                            inter.index[1]++;
                        }

                        intersections.push_back(inter);
                    }
                }
            }
        }
예제 #7
0
        //
        //ORIGINAL LINE: List<std::pair<uint, uint> > getNoIntersectionParts(uint pathIndex) const
        /// <summary>
        /// 获取非交集
        /// </summary>
        /// <param name="pathIndex"></param>
        /// <returns></returns>
        public std_vector<std_pair<uint, uint>> getNoIntersectionParts(uint pathIndex) {
            Path path = mPaths[(int)pathIndex];
            std_vector<std_pair<uint, uint>> result = new std_vector<std_pair<uint, uint>>();
            std_vector<int> intersections = new std_vector<int>();
            //for (std.map<PathCoordinate, List<PathCoordinate>>.Enumerator it = mIntersectionsMap.begin(); it != mIntersectionsMap.end(); ++it) {
            foreach (var it in mIntersectionsMap) {
                if (it.Key.pathIndex == pathIndex) {
                    intersections.push_back((int)it.Key.pointIndex);
                }
            }
            //std.sort(intersections.GetEnumerator(), intersections.end());
            intersections.Sort((x, y) => {
                return x - y;//正序排序(重写int比较器,|x|>|y|返回正数,|x|=|y|返回0,|x|<|y|返回负数)  
            });
            //Array.Sort(intersections.ToArray());

            int begin = 0;
            //for (std::vector<int>::iterator it = intersections.begin(); it!= intersections.end(); ++it)
            //{
            //    if (*it-1>begin)
            //        result.push_back(std::pair<unsigned int, unsigned int>(begin, *it-1));
            //    begin = *it+1;
            //}
            //if (path.getSegCount() > begin)
            //    result.push_back(std::pair<unsigned int, unsigned int>(begin, path.getSegCount()));

            //for (List<int>.Enumerator it = intersections.GetEnumerator(); it.MoveNext(); ++it)
            foreach (var it in intersections) {
                if (it - 1 > begin)
                    result.push_back(new std_pair<uint, uint>((uint)begin, (uint)it - 1));
                begin = it + 1;
            }
            if (path.getSegCount() > begin)
                result.push_back(new std_pair<uint, uint>((uint)begin, (uint)path.getSegCount()));
            return result;
        }
예제 #8
0
        //-----------------------------------------------------------------------
        /// <summary>
        /// 查找交集
        /// </summary>
        public void _calcIntersections() {
            mIntersectionsMap.Clear();
            mIntersections.Clear();
            //std::map<Ogre::Vector3, PathIntersection, Vector3Comparator> pointSet;        
            std_map<Vector3, std_vector<PathCoordinate>> pointSet = new std_map<Vector3, std_vector<PathCoordinate>>(new Vector3Comparator());
            //       for (std::vector<Path>::iterator it = mPaths.begin(); it!= mPaths.end(); ++it)
            uint it_index = 0;
            foreach (var it in mPaths) {

                uint it_point_index = 0;
                //for (std::vector<Ogre::Vector3>::const_iterator it2 = it->getPoints().begin(); it2 != it->getPoints().end(); ++it2)
                foreach (var it2 in it._getPoints()) {

                    //PathCoordinate pc(it-mPaths.begin(), it2-it->getPoints().begin());
                    PathCoordinate pc = new PathCoordinate(it_index, it_point_index);
                    //if (pointSet.find(*it2)==pointSet.end())
                    if (!pointSet.ContainsKey(it2)) {
                        std_vector<PathCoordinate> pi = new std_vector<PathCoordinate>();
                        pi.Add(pc);
                        //pointSet[it2] = pi;
                        pointSet.Add(it2, pi);
                    }
                    else {
                        pointSet[it2].push_back(pc);
                    }

                    it_point_index++;
                }
                it_index++;
            }
            //for (std::map<Ogre::Vector3, PathIntersection, Vector3Comparator>::iterator it = pointSet.begin(); it != pointSet.end(); ++it)
            foreach (var it_ps in pointSet) {
                if (it_ps.Value.size() > 1) {
                    foreach (var it2 in it_ps.Value) {
                        //mIntersectionsMap[*it2] = it->second;
                        if (mIntersectionsMap.ContainsKey(it2)) {
                            mIntersectionsMap[it2] = it_ps.Value;
                        }
                        else {
                            mIntersectionsMap.Add(it2, it_ps.Value);
                        }
                    }
                    mIntersections.push_back(it_ps.Value);
                }
            }
            //          
        }
예제 #9
0
 public void buildFromSegmentSoup(std_vector<Segment3D> segList, ref std_vector<Path> @out)
 {
     //typedef std::multimap<Vector3, Vector3, Vector3Comparator> Vec3MultiMap;
     //Vec3MultiMap segs;
    std_multimap<Vector3,Vector3>segs=new std_multimap<Vector3,Vector3>(new Vector3Comparator());
    // for (std::vector<Segment3D>::const_iterator it = segList.begin(); it != segList.end(); ++it)
    foreach(var it in segList)
    {
         //segs.insert(std::pair<Vector3, Vector3 > (it->mA, it->mB));
         //segs.insert(std::pair<Vector3, Vector3 > (it->mB, it->mA));
        segs.insert(it.mA,it.mB);
        segs.insert(it.mB,it.mA);
     }
     while (!segs.empty())
     {
        Vector3 headFirst = segs.get(0).first;//segs.begin()->first;
         Vector3 headSecond = segs.get(0).second[0];//segs.begin()->second;
         Path p=new Path();
         p.addPoint(headFirst).addPoint(headSecond);
         //Vec3MultiMap::iterator firstSeg = segs.begin();
         int firstSeg_pos=segs.begin();
         Vector3 firstSeg=segs.get(0).first;
         //std::pair<Vec3MultiMap::iterator, Vec3MultiMap::iterator> correspondants2 = segs.equal_range(headSecond);
        std_pair<std_pair<Vector3,List<Vector3>>,std_pair<Vector3,List<Vector3>>>  correspondants2 = segs.equal_range(headSecond);
         //for (Vec3MultiMap::iterator it = correspondants2.first; it != correspondants2.second;)
         for(int i=correspondants2.first.second.Count-1;i>=0;i--)
         {
            // Vec3MultiMap::iterator removeIt = it++;
             Vector3 removeIt=correspondants2.first.second[i];
             //if ((removeIt->second - firstSeg->first).squaredLength() < 1e-8)
             if((removeIt-firstSeg).SquaredLength<1e-8)
                 segs.erase(removeIt);
         }
         segs.erase(firstSeg);
         bool foundSomething = true;
         while (!segs.empty() && foundSomething)
         {
             foundSomething = false;
             //Vec3MultiMap::iterator next = segs.find(headSecond);
             int next_pos = segs.find(headSecond);
             //if (next != segs.end())
             if(next_pos!=-1)
             {
                 std_pair<Vector3,List<Vector3>>next=segs.get((uint)next_pos);
                 foundSomething = true;
                 headSecond = next.second[0];
                 p.addPoint(headSecond);
                 //std::pair<Vec3MultiMap::iterator, Vec3MultiMap::iterator> correspondants = segs.equal_range(headSecond);
                 std_pair<std_pair<Vector3,List<Vector3>>,std_pair<Vector3,List<Vector3>>>correspondants = segs.equal_range(headSecond);
                 //for (Vec3MultiMap::iterator it = correspondants.first; it != correspondants.second;)
                 for (int i = correspondants.first.second.Count - 1; i >= 0;i-- ) {
                     //Vec3MultiMap::iterator removeIt = it++;
                     Vector3 removeIt = correspondants.first.second[i];
                     //if ((removeIt->second - next->first).squaredLength() < 1e-8)
                     if ((removeIt - next.first).SquaredLength < 1e-8)
                         segs.erase(removeIt);
                 }
                 //segs.erase(next);
                 segs.erase(next.first);
             }
             //Vec3MultiMap::iterator previous = segs.find(headFirst);
             int previous_pos=segs.find(headFirst);
             //if (previous != segs.end())
             if(previous_pos!=-1)
             {
                 std_pair<Vector3, List<Vector3>> previous = segs.get((uint)previous_pos);
                 foundSomething = true;
                 //p.insertPoint(0, previous.second);
                 p.insertPoint(0, previous.second[0]);//???
                 headFirst = previous.second[0];
                 //std::pair<Vec3MultiMap::iterator, Vec3MultiMap::iterator> correspondants = segs.equal_range(headFirst);
                 std_pair<std_pair<Vector3,List<Vector3>>,std_pair<Vector3,List<Vector3>>>correspondants = segs.equal_range(headFirst);
                 //for (Vec3MultiMap::iterator it = correspondants.first; it != correspondants.second;)
                 for(int i=correspondants.first.second.Count-1;i>=0;i--)
                 {
                     //Vec3MultiMap::iterator removeIt = it++;
                     Vector3 removeIt=correspondants.first.second[i];
                     //if ((removeIt->second - previous->first).squaredLength() < 1e-8)
                     if((removeIt-previous.first).SquaredLength<1e-8) 
                     segs.erase(removeIt);
                 }
                 //segs.erase(previous);
                 segs.erase(previous.first);
             }
         }
         if ((p.getPoint(0)-p.getPoint(p.getSegCount() + 1)).SquaredLength < 1e-6)
         {
             p.getPointsReference().pop_back();
             p.close();
         }
         @out.push_back(p);
     }
 }
예제 #10
0
        //std_vector<std::string> split(const std::string& str, const std::string& delimiters, bool removeEmpty = true);
        std_vector<string> split(string str, string delimiters, bool removeEmpty) {
            std_vector<string> tokens = new std_vector<string>();
            //std::string::size_type delimPos = 0, tokenPos = 0, pos = 0;
            //int delimPos = 0, tokenPos = 0, pos = 0;
            //if (str.empty()) return tokens;
            if (string.IsNullOrEmpty(str)) return tokens;
            string[] strsplits = str.Split(delimiters.ToCharArray());
            foreach (var v in strsplits) {
                if (removeEmpty) {
                    if (!string.IsNullOrEmpty(v)) {
                        tokens.push_back(v);
                    }
                }
                else {
                    tokens.push_back(v);
                }
            }
            //while (true)
            //{
            //    delimPos = str.find_first_of(delimiters, pos);
            //    tokenPos = str.find_first_not_of(delimiters, pos);

            //    if (std::string::npos != delimPos)
            //    {
            //        if (std::string::npos != tokenPos)
            //        {
            //            if (tokenPos < delimPos)
            //                tokens.push_back(str.substr(pos,delimPos-pos));
            //            else
            //            {
            //                if (!removeEmpty) tokens.push_back("");
            //            }
            //        }
            //        else
            //        {
            //            if (!removeEmpty) tokens.push_back("");
            //        }
            //        pos = delimPos+1;
            //    }
            //    else
            //    {
            //        if (std::string::npos != tokenPos)
            //            tokens.push_back(str.substr(pos));
            //        else
            //        {
            //            if (!removeEmpty) tokens.push_back("");
            //        }
            //        break;
            //    }
            //}
            return tokens;
        }
예제 #11
0
            // SvgLoaderPath(std::vector<std::string> p, unsigned int ns);
            public SvgLoaderPath(std_vector<string> p, uint ns) {
                parts = p;
                mNumSeg = ns;
                px = 0.0f;
                py = 0.0f;
                index = 0;
                char lastCmd = (char)0;

                while (index < p.Count) {
                    try {
                        char newCmd = parts[index][0];
                        bool next = true;
                        if (lastCmd != newCmd && newCmd != '.' && newCmd != '-' && (newCmd < '0' || newCmd > '9') && curve.size() > 3 && ((lastCmd == 'c' || lastCmd == 'C') && (newCmd == 's' || newCmd == 'S') || (lastCmd == 'q' || lastCmd == 'Q') && (newCmd == 't' || newCmd == 'T'))) {
                            // finish curve
                            finishCurve(lastCmd);
                        }
                        switch (newCmd) {
                            case 'l':
                                parseLineTo(true, next);
                                break;
                            case 'L':
                                parseLineTo(false, next);
                                break;
                            case 'm':
                                parseMoveTo(true, next);
                                newCmd = 'l';
                                break;
                            case 'M':
                                parseMoveTo(false, next);
                                newCmd = 'L';
                                break;
                            case 'h':
                                parseHLineTo(true, next);
                                break;
                            case 'H':
                                parseHLineTo(false, next);
                                break;
                            case 'v':
                                parseVLineTo(true, next);
                                break;
                            case 'V':
                                parseVLineTo(false, next);
                                break;
                            case 'c':
                                curve.push_back(point);
                                parseCurveCTo(true, next);
                                break;
                            case 'C':
                                curve.push_back(point);
                                parseCurveCTo(false, next);
                                break;
                            case 's':
                                parseCurveSTo(true, next);
                                break;
                            case 'S':
                                parseCurveSTo(false, next);
                                break;
                            case 'q':
                                curve.push_back(point);
                                parseCurveQTo(true, next);
                                break;
                            case 'Q':
                                curve.push_back(point);
                                parseCurveQTo(false, next);
                                break;
                            case 't':
                                parseCurveTTo(true, next);
                                break;
                            case 'T':
                                parseCurveTTo(false, next);
                                break;
                            case 'a':
                                parseArcTo(true, next);
                                break;
                            case 'A':
                                parseArcTo(false, next);
                                break;
                            case 'z':
                            case 'Z':
                                shape.close();
                                index++;
                                break;
                            default:
                                newCmd = lastCmd;
                                next = false;
                                switch (lastCmd) {
                                    case 'l':
                                        parseLineTo(true, next);
                                        break;
                                    case 'L':
                                        parseLineTo(false, next);
                                        break;
                                    case 'm':
                                        parseMoveTo(true, next);
                                        break;
                                    case 'M':
                                        parseMoveTo(false, next);
                                        break;
                                    case 'h':
                                        parseHLineTo(true, next);
                                        break;
                                    case 'H':
                                        parseHLineTo(false, next);
                                        break;
                                    case 'v':
                                        parseVLineTo(true, next);
                                        break;
                                    case 'V':
                                        parseVLineTo(false, next);
                                        break;
                                    case 'c':
                                        parseCurveCTo(true, next);
                                        break;
                                    case 'C':
                                        parseCurveCTo(false, next);
                                        break;
                                    case 's':
                                        parseCurveSTo(true, next);
                                        break;
                                    case 'S':
                                        parseCurveSTo(false, next);
                                        break;
                                    case 'q':
                                        parseCurveQTo(true, next);
                                        break;
                                    case 'Q':
                                        parseCurveQTo(false, next);
                                        break;
                                    case 't':
                                        parseCurveTTo(true, next);
                                        break;
                                    case 'T':
                                        parseCurveTTo(false, next);
                                        break;
                                    case 'a':
                                        parseArcTo(true, next);
                                        break;
                                    case 'A':
                                        parseArcTo(false, next);
                                        break;

                                    default:
                                        break;
                                }
                                break;
                        }
                        lastCmd = newCmd;
                    }
                    catch {
                    }
                }
                if (curve.size() > 0)
                    finishCurve(lastCmd);
            }
 //--------------------------------------------------------------
 public void modify() {
     if (mInputTriangleBuffer == null)
         OGRE_EXCEPT("Exception::ERR_INVALID_STATE", "Input triangle buffer must be set", "__FUNCTION__");
     ;
     std_vector<TriangleBuffer.Vertex> newVertices = new std_vector<TriangleBuffer.Vertex>();
     std_vector<TriangleBuffer.Vertex> originVertices = mInputTriangleBuffer.getVertices();
     std_vector<int> originIndices = mInputTriangleBuffer.getIndices();
     for (int i = 0; i < originIndices.size(); i += 3) {
         newVertices.push_back(originVertices[originIndices[i]]);
         newVertices.push_back(originVertices[originIndices[i + 1]]);
         newVertices.push_back(originVertices[originIndices[i + 2]]);
     }
     mInputTriangleBuffer.getVertices().clear();
     mInputTriangleBuffer.getVertices().reserve(newVertices.size());
     //for (List<TriangleBuffer.Vertex>.Enumerator it = newVertices.GetEnumerator(); it.MoveNext(); ++it)
     //	mInputTriangleBuffer.getVertices().push_back(it.Current);
     foreach (var it in newVertices) {
         mInputTriangleBuffer.getVertices().push_back(it);
     }
     mInputTriangleBuffer.getIndices().clear();
     mInputTriangleBuffer.getIndices().reserve(newVertices.size());
     for (int i = 0; i < newVertices.size(); i++)
         mInputTriangleBuffer.getIndices().push_back(i);
 }
        //--------------------------------------------------------------
        public void modify() {
            if (mInputTriangleBuffer == null)
                OGRE_EXCEPT("Exception::ERR_INVALID_STATE", "Input triangle buffer must be set", "__FUNCTION__");
            ;

            if (mComputeMode == NormalComputeMode.NCM_TRIANGLE) {
                if (mMustWeldUnweldFirst)
                    new UnweldVerticesModifier().setInputTriangleBuffer(mInputTriangleBuffer).modify();

                std_vector<int> indices = mInputTriangleBuffer.getIndices();
                std_vector<TriangleBuffer.Vertex> vertices = mInputTriangleBuffer.getVertices();
                for (int i = 0; i < indices.size(); i += 3) {
                    Vector3 v1 = vertices[indices[i]].mPosition;
                    Vector3 v2 = vertices[indices[i + 1]].mPosition;
                    Vector3 v3 = vertices[indices[i + 2]].mPosition;
                    Vector3 n = (v2 - v1).CrossProduct(v3 - v1).NormalisedCopy;
                    //
                    //ORIGINAL LINE: vertices[indices[i]].mNormal = n;
                    vertices[indices[i]].mNormal = (n);
                    //
                    //ORIGINAL LINE: vertices[indices[i+1]].mNormal = n;
                    vertices[indices[i + 1]].mNormal = (n);
                    //
                    //ORIGINAL LINE: vertices[indices[i+2]].mNormal = n;
                    vertices[indices[i + 2]].mNormal = (n);
                }
            }
            else {
                if (mMustWeldUnweldFirst)
                    new WeldVerticesModifier().setInputTriangleBuffer(mInputTriangleBuffer).modify();
                std_vector<int> indices = mInputTriangleBuffer.getIndices();
                std_vector<TriangleBuffer.Vertex> vertices = mInputTriangleBuffer.getVertices();
                std_vector<std_vector<Vector3>> tmpNormals = new std_vector<std_vector<Vector3>>();
                tmpNormals.resize(vertices.size());
                for (int i = 0; i < indices.size(); i += 3) {
                    Vector3 v1 = vertices[indices[i]].mPosition;
                    Vector3 v2 = vertices[indices[i + 1]].mPosition;
                    Vector3 v3 = vertices[indices[i + 2]].mPosition;
                    Vector3 n = (v2 - v1).CrossProduct(v3 - v1);
                    tmpNormals[indices[i]].push_back(n);
                    tmpNormals[indices[i + 1]].push_back(n);
                    tmpNormals[indices[i + 2]].push_back(n);
                }
                for (int i = 0; i < vertices.size(); i++) {
                    Vector3 n = (Vector3.ZERO);
                    for (int j = 0; j < tmpNormals[i].size(); j++)
                        n += tmpNormals[i][j];
                    vertices[i].mNormal = n.NormalisedCopy;
                }
            }
        }