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