///<summary>
 /// Appends another path at the end of this one, relative to the last point of this path
 ///</summary>
 public Path appendPathRel(Path other)
 {
     if (mPoints.empty())
     {
         appendPath(other);
     }
     else
     {
         Vector3   refVector = mPoints[mPoints.Count - 1]; //*(mPoints.end()-1);
         Vector3[] pointList = (other.mPoints.ToArray());
         //for (List<Vector3>.Enumerator it = pointList.GetEnumerator(); it.MoveNext(); ++it)
         //	it.Current += refVector;
         for (int i = 0; i < pointList.Length; i++)
         {
             pointList[i] += refVector;
         }
         //mPoints.insert(mPoints.end(), pointList.begin(), pointList.end());
         mPoints.AddRange(pointList);
     }
     return(this);
 }
        //-----------------------------------------------------------------------
        //
        //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;
        }
        //    *
        //	 * Builds a shape from control points
        //	 * \exception Ogre::InvalidStateException The path contains no points
        //
        //-----------------------------------------------------------------------
        public Shape realizeShape()
        {
            if (mPoints.empty())
            {
                OGRE_EXCEPT("Ogre::Exception::ERR_INVALID_STATE", "The shape contains no points", "Procedural::RoundedCornerSpline2::realizePath()");
            }
            ;

            Shape shape     = new Shape();
            int   numPoints = mClosed ? mPoints.Count : (mPoints.Count - 2);

            if (!mClosed)
            {
                shape.addPoint(mPoints[0]);
            }

            for (uint i = 0; i < numPoints; ++i)
            {
                Vector2 p0 = safeGetPoint(i);
                Vector2 p1 = safeGetPoint(i + 1);
                Vector2 p2 = safeGetPoint(i + 2);

                Vector2 vBegin = p1 - p0;
                Vector2 vEnd   = p2 - p1;

                // We're capping the radius if it's too big compared to segment length
                float radius            = mRadius;
                float smallestSegLength = System.Math.Min(vBegin.Length, vEnd.Length);
                if (smallestSegLength < 2 * mRadius)
                {
                    radius = smallestSegLength / 2.0f;
                }

                Vector2 pBegin = p1 - vBegin.NormalisedCopy * radius;
                Vector2 pEnd   = p1 + vEnd.NormalisedCopy * radius;
                Line2D  line1  = new Line2D(pBegin, vBegin.Perpendicular);
                Line2D  line2  = new Line2D(pEnd, vEnd.Perpendicular);
                Vector2 center = new Vector2();
                line1.findIntersect(line2, ref center);
                Vector2 vradBegin  = pBegin - center;
                Vector2 vradEnd    = pEnd - center;
                Radian  angleTotal = Utils.angleBetween(vradBegin, vradEnd);
                if (vradBegin.CrossProduct(vradEnd) < 0f)
                {
                    angleTotal = -angleTotal;
                }

                for (uint j = 0; j <= mNumSeg; j++)
                {
                    Vector2 deltaVector = Utils.rotateVector2(vradBegin, (float)j * angleTotal / (float)mNumSeg);
                    shape.addPoint(center + deltaVector);
                }
            }

            if (!mClosed)
            {
                shape.addPoint(mPoints[mPoints.size() - 1]);
            }

            if (mClosed)
            {
                shape.close();
            }
            shape.setOutSide(mOutSide);

            return(shape);
        }
Exemple #4
0
        //void Triangulator::_recursiveTriangulatePolygon(const DelaunaySegment& cuttingSeg, std::vector<int> inputPoints, DelaunayTriangleBuffer& tbuffer, const PointList&  pointList) const
        void _recursiveTriangulatePolygon(DelaunaySegment cuttingSeg, std_vector <int> inputPoints, DelaunayTriangleBuffer tbuffer, PointList pointList)
        {
            if (inputPoints.size() == 0)
            {
                return;
            }
            if (inputPoints.size() == 1)
            {
                Triangle t2 = new Triangle(pointList);
                //t.setVertices(cuttingSeg.i1, cuttingSeg.i2, inputPoints.begin());
                t2.setVertices(cuttingSeg.i1, cuttingSeg.i2, inputPoints.front());
                t2.makeDirectIfNeeded();
                tbuffer.push_back(t2);
                return;
            }
            // Find a point which, when associated with seg.i1 and seg.i2, builds a Delaunay triangle
            //std::vector<int>::iterator currentPoint = inputPoints.begin();
            int  currentPoint_pos = inputPoints.begin();
            int  currentPoint     = inputPoints.front();
            bool found            = false;

            while (!found)
            {
                bool isDelaunay = true;
                //Circle c=new Circle(pointList[*currentPoint], pointList[cuttingSeg.i1], pointList[cuttingSeg.i2]);
                Circle c = new Circle(pointList[currentPoint], pointList[cuttingSeg.i1], pointList[cuttingSeg.i2]);
                //for (std::vector<int>::iterator it = inputPoints.begin(); it!=inputPoints.end(); ++it)
                int idx = -1;
                foreach (var it in inputPoints)
                {
                    idx++;
                    //if (c.isPointInside(pointList[*it]) && (*it != *currentPoint))
                    if (c.isPointInside(pointList[it]) && (it != currentPoint))
                    {
                        isDelaunay       = false;
                        currentPoint     = it;
                        currentPoint_pos = idx;
                        break;
                    }
                }
                if (isDelaunay)
                {
                    found = true;
                }
            }

            // Insert current triangle
            Triangle t = new Triangle(pointList);

            //t.setVertices(*currentPoint, cuttingSeg.i1, cuttingSeg.i2);
            t.setVertices(currentPoint, cuttingSeg.i1, cuttingSeg.i2);
            t.makeDirectIfNeeded();
            tbuffer.push_back(t);

            // Recurse
            //DelaunaySegment newCut1=new DelaunaySegment(cuttingSeg.i1, *currentPoint);
            //DelaunaySegment newCut2=new DelaunaySegment(cuttingSeg.i2, *currentPoint);
            DelaunaySegment newCut1 = new DelaunaySegment(cuttingSeg.i1, currentPoint);
            DelaunaySegment newCut2 = new DelaunaySegment(cuttingSeg.i2, currentPoint);
            //std_vector<int> set1=new std_vector<int>(inputPoints.begin(), currentPoint);
            //std_vector<int> set2=new std_vector<int>(currentPoint+1, inputPoints.end());
            std_vector <int> set1 = new std_vector <int>();

            set1.assign(inputPoints.ToArray(), inputPoints.begin(), currentPoint_pos);
            std_vector <int> set2 = new std_vector <int>();

            set2.assign(inputPoints.ToArray(), currentPoint_pos + 1, inputPoints.end());

            if (!set1.empty())
            {
                _recursiveTriangulatePolygon(newCut1, set1, tbuffer, pointList);
            }
            if (!set2.empty())
            {
                _recursiveTriangulatePolygon(newCut2, set2, tbuffer, pointList);
            }
        }
        //    *
        //	 * Builds a shape from control points
        //	 * \exception Ogre::InvalidStateException The path contains no points
        //

        //-----------------------------------------------------------------------
        public Path realizePath()
        {
            if (mPoints.empty())
            {
                OGRE_EXCEPT("Ogre::Exception::ERR_INVALID_STATE", "The path contains no points", "Procedural::RoundedCornerSpline3::realizePath()");
            }
            ;

            Path path      = new Path();
            int  numPoints = mClosed ? mPoints.Count : (mPoints.Count - 2);

            if (!mClosed)
            {
                path.addPoint(mPoints[0]);
            }

            for (uint i = 0; i < numPoints; ++i)
            {
                Vector3 p0 = safeGetPoint(i);
                Vector3 p1 = safeGetPoint(i + 1);
                Vector3 p2 = safeGetPoint(i + 2);

                Vector3 vBegin = p1 - p0;
                Vector3 vEnd   = p2 - p1;

                // We're capping the radius if it's too big compared to segment length
                float radius            = mRadius;
                float smallestSegLength = System.Math.Min(vBegin.Length, vEnd.Length);
                if (smallestSegLength < 2 * mRadius)
                {
                    radius = smallestSegLength / 2.0f;
                }

                Vector3 pBegin = p1 - vBegin.NormalisedCopy * radius;
                Vector3 pEnd   = p1 + vEnd.NormalisedCopy * radius;
                Mogre_Procedural.Plane plane1 = new Plane(vBegin, pBegin);
                Mogre_Procedural.Plane plane2 = new Plane(vEnd, pEnd);
                Line axis = new Line();
                plane1.intersect(plane2, ref axis);

                Vector3    vradBegin  = axis.shortestPathToPoint(pBegin);
                Vector3    vradEnd    = axis.shortestPathToPoint(pEnd);
                Quaternion q          = vradBegin.GetRotationTo(vradEnd);
                Vector3    center     = pBegin - vradBegin;
                Radian     angleTotal = new Radian();
                Vector3    vAxis      = new Vector3();
                q.ToAngleAxis(out angleTotal, out vAxis);

                for (uint j = 0; j <= mNumSeg; j++)
                {
                    q.FromAngleAxis(angleTotal * (float)j / (float)mNumSeg, vAxis);
                    path.addPoint(center + q * vradBegin);
                }
            }

            if (!mClosed)
            {
                path.addPoint(mPoints[mPoints.size() - 1]);
            }

            if (mClosed)
            {
                path.close();
            }

            return(path);
        }