コード例 #1
0
        //-----------------------------------------------------------------------
        //
        //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;
        }
コード例 #2
0
        /// Creates a shape with the keys of this shape and extra keys coming from a track
        /// @param track the track to merge keys with
        /// @return a new Shape coming from the merge between original shape and the track
        //-----------------------------------------------------------------------
        //
        //ORIGINAL LINE: Shape mergeKeysWithTrack(const Track& track) const
        public Shape mergeKeysWithTrack(Track track) {
            if (!track.isInsertPoint() || track.getAddressingMode() == Track.AddressingMode.AM_POINT)
                return this;
            float totalLength = getTotalLength();

            float lineicPos = 0;
            float shapeLineicPos = 0;
            Shape outputShape = new Shape();
            if (mClosed)
                outputShape.close();
            outputShape.addPoint(getPoint(0));
            for (int i = 1; i < mPoints.Count; ) {
                float nextLineicPos = shapeLineicPos + (mPoints[i] - mPoints[i - 1]).Length;

                //std.map<Real,Real>.Enumerator it = track._getKeyValueAfter(lineicPos, lineicPos/totalLength, i-1);
                std_pair<float, float> it = track._getKeyValueAfter(lineicPos, lineicPos / totalLength, ((uint)i - 1));
                float nextTrackPos = it.first;
                if (track.getAddressingMode() == Track.AddressingMode.AM_RELATIVE_LINEIC)
                    nextTrackPos *= totalLength;

                // Adds the closest point to the curve, being either from the shape or the track
                if (nextLineicPos <= nextTrackPos || lineicPos >= nextTrackPos) {
                    outputShape.addPoint(mPoints[i]);
                    i++;
                    lineicPos = nextLineicPos;
                    shapeLineicPos = nextLineicPos;
                }
                else {
                    outputShape.addPoint(getPosition((uint)i - 1, (nextTrackPos - shapeLineicPos) / (nextLineicPos - shapeLineicPos)));
                    lineicPos = nextTrackPos;
                }
            }
            return outputShape;
        }
コード例 #3
0
 //    *
 //	 * Applies a "thickness" to a shape, ie a bit like the extruder, but in 2D
 //	 * <table border="0" width="100%"><tr><td>\image html shape_thick1.png "Start shape (before thicken)"</td><td>\image html shape_thick2.png "Result (after thicken)"</td></tr></table>
 //	 
 //-----------------------------------------------------------------------
 public MultiShape thicken(float amount) {
     if (!mClosed) {
         Shape s = new Shape();
         s.setOutSide(mOutSide);
         for (int i = 0; i < mPoints.Count; i++)
             s.addPoint(mPoints[i] + amount * getAvgNormal((uint)i));
         for (int i = mPoints.Count - 1; i >= 0; i--)
             s.addPoint(mPoints[i] - amount * getAvgNormal((uint)i));
         s.close();
         return new MultiShape().addShape(s);
     }
     else {
         MultiShape ms = new MultiShape();
         Shape s1 = new Shape();
         for (int i = 0; i < mPoints.Count; i++)
             s1.addPoint(mPoints[i] + amount * getAvgNormal((uint)i));
         s1.close();
         s1.setOutSide(mOutSide);
         ms.addShape(s1);
         Shape s2 = new Shape();
         for (int i = 0; i < mPoints.Count; i++)
             s2.addPoint(mPoints[i] - amount * getAvgNormal((uint)i));
         s2.close();
         s2.setOutSide(mOutSide == Side.SIDE_LEFT ? Side.SIDE_RIGHT : Side.SIDE_LEFT);
         ms.addShape(s2);
         return ms;
     }
 }
コード例 #4
0
 //    *
 //	 * Computes the union between this shape and another one.
 //	 * Both shapes must be closed.
 //	 * <table border="0" width="100%"><tr><td>\image html shape_booleansetup.png "Start shapes"</td><td>\image html shape_booleanunion.png "Union of the two shapes"</td></tr></table>
 //	 * @param other The shape against which the union is computed
 //	 * @return The union of two shapes, as a new shape
 //	 * @exception Ogre::InvalidStateException Current shapes must be closed and has to contain at least 2 points!
 //	 * @exception Ogre::InvalidParametersException Other shapes must be closed and has to contain at least 2 points!
 //	 
 //-----------------------------------------------------------------------
 //
 //ORIGINAL LINE: MultiShape booleanUnion(const Shape& STLAllocator<U, AllocPolicy>) const
 public MultiShape booleanUnion(Shape other) {
     return _booleanOperation(other, BooleanOperationType.BOT_UNION);
 }
コード例 #5
0
 //    *
 //	 * Computes the difference between this shape and another one.
 //	 * Both shapes must be closed.
 //	 * <table border="0" width="100%"><tr><td>\image html shape_booleansetup.png "Start shapes"</td><td>\image html shape_booleandifference.png "Difference of the two shapes"</td></tr></table>
 //	 * @param other The shape against which the diffenrence is computed
 //	 * @return The difference of two shapes, as a new shape
 //	 * @exception Ogre::InvalidStateException Current shapes must be closed and has to contain at least 2 points!
 //	 * @exception Ogre::InvalidParametersException Other shapes must be closed and has to contain at least 2 points!
 //	 
 //-----------------------------------------------------------------------
 //
 //ORIGINAL LINE: MultiShape booleanDifference(const Shape& STLAllocator<U, AllocPolicy>) const
 public MultiShape booleanDifference(Shape other) {
     return _booleanOperation(other, BooleanOperationType.BOT_DIFFERENCE);
 }
コード例 #6
0
 /// Extracts a part of the shape as a new shape
 /// @param first first index to be in the new shape
 /// @param last last index to be in the new shape
 public Shape extractSubShape(uint first, uint last) {
     Shape s = new Shape();
     for (int i = (int)first; i <= last; i++)
         s.addPoint(mPoints[i]);
     s.setOutSide(mOutSide);
     if (mClosed)
         s.close();
     return s;
 }
コード例 #7
0
        //    *
        //	 * Computes the intersection between this shape and another one.
        //	 * Both shapes must be closed.
        //	 * <table border="0" width="100%"><tr><td>\image html shape_booleansetup.png "Start shapes"</td><td>\image html shape_booleanintersection.png "Intersection of the two shapes"</td></tr></table>
        //	 * @param other The shape against which the intersection is computed
        //	 * @return The intersection of two shapes, as a new shape
        //	 * @exception Ogre::InvalidStateException Current shapes must be closed and has to contain at least 2 points!
        //	 * @exception Ogre::InvalidParametersException Other shapes must be closed and has to contain at least 2 points!
        //	 
        //-----------------------------------------------------------------------


        //-----------------------------------------------------------------------
        //
        //ORIGINAL LINE: MultiShape booleanIntersect(const Shape& STLAllocator<U, AllocPolicy>) const
        public MultiShape booleanIntersect(Shape other) {
            return _booleanOperation(other, BooleanOperationType.BOT_INTERSECTION);
        }
コード例 #8
0
 /// Appends another shape at the end of this one
 public Shape appendShape(Shape other) {
     //
     //mPoints.insert(mPoints.end(), STLAllocator<U, AllocPolicy>.mPoints.GetEnumerator(), STLAllocator<U, AllocPolicy>.mPoints.end());
     mPoints.AddRange(other.mPoints.ToArray());
     return this;
 }
コード例 #9
0
 /// Appends another shape at the end of this one, relative to the last point of this shape
 public Shape appendShapeRel(Shape other) {
     return addPointRel(other.mPoints);
     //if (mPoints.Count == 0)
     //    appendShape(other);
     //else {
     //    Vector2 refVector = mPoints[mPoints.Count - 1];// *(mPoints.end()-1);
     //    List<Vector2> pointList = other.mPoints;//new List<Vector2>(STLAllocator<U, AllocPolicy>.mPoints.GetEnumerator(), STLAllocator<U, AllocPolicy>.mPoints.end());
     //    //            for (List<Vector2>.Enumerator it = pointList.GetEnumerator(); it.MoveNext(); ++it)
     //    //                it.Current +=refVector;
     //    ////
     //    //            mPoints.insert(mPoints.end(), pointList.GetEnumerator(), pointList.end());
     //    foreach (var it in pointList) {
     //        addPoint(it + refVector);
     //    }
     //}
     //return this;
 }
コード例 #10
0
        //-----------------------------------------------------------------------
        //
        //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);
                    }
                }
            }
        }
コード例 #11
0
        //-----------------------------------------------------------------------
        //
        //ORIGINAL LINE: bool _findWhereToGo(const Shape* inputShapes[], BooleanOperationType opType, IntersectionInShape intersection, byte& shapeSelector, sbyte& isIncreasing, uint& currentSegment) const
        private bool _findWhereToGo(Shape[] inputShapes, BooleanOperationType opType, IntersectionInShape intersection, ref byte shapeSelector, ref sbyte isIncreasing, ref uint currentSegment) {
            if (intersection.onVertex[0] || intersection.onVertex[1]) {
                // determine 4 directions with normal info
                // if 2 normals "face each other" then you have the couple of outside directions
                Vector2[] directions = new Vector2[4];
                //string sides = new string(new char[4]);
                byte[] sides = new byte[4];
                byte incomingDirection;

                // fill-in the incoming arrays
                if (isIncreasing == 0) {
                    incomingDirection = 255;
                }
                else {
                    incomingDirection = (byte)(shapeSelector + (isIncreasing == 1 ? 2 : 0));
                }
                for (byte i = 0; i < 2; i++)
                    if (intersection.onVertex[i]) {
                        directions[i] = inputShapes[i].getDirectionBefore(intersection.index[i]);
                        directions[2 + i] = -inputShapes[i].getDirectionAfter(intersection.index[i]);
                    }
                    else {
                        directions[2 + i] = -inputShapes[i].getDirectionAfter(intersection.index[i]);
                        directions[i] = -directions[2 + i];
                    }
                for (byte i = 0; i < 4; i++) {
                    sides[i] = (byte)((i / 2 == 0 ? -1 : 1) * (inputShapes[i % 2].mOutSide == Side.SIDE_RIGHT ? -1 : 1));
                }

                bool[] isOutside = new bool[4];
                //std.pair<Radian, byte>[] sortedDirections = new std.pair[4];
                KeyValuePair<Radian, byte>[] sortedDirections = new KeyValuePair<Radian, byte>[4];
                // sort by angle
                for (byte i = 0; i < 4; i++) {
                    if (i == 0) {
                        //sortedDirections[i].first = 0;
                        sortedDirections[i] = new KeyValuePair<Radian, byte>(0, i);
                    }
                    else {
                        Radian first = sides[0] * Utils.angleTo(directions[0], directions[i]);
                        sortedDirections[i] = new KeyValuePair<Radian, byte>(first, i);
                    }
                    //sortedDirections[i].second=i;
                }

                //std.sort(sortedDirections, sortedDirections+4, GlobalMembersProceduralShape._sortAngles);
                //ToDo:sortedDirectionsÅÅÐò
                List<KeyValuePair<Radian, byte>> sort_sortedDirections = new List<KeyValuePair<Radian, byte>>();
                sort_sortedDirections.AddRange(sortedDirections);
                sort_sortedDirections.Sort((X, Y) => {
                    return _sortAngles(X, Y) ? -1 : 1;
                });
                sortedDirections = sort_sortedDirections.ToArray();
                //Array.Sort(sortedDirections);
                //find which segments are outside
                if (sides[0] != sides[sortedDirections[1].Value]) {
                    isOutside[0] = isOutside[sortedDirections[1].Value] = true;
                    isOutside[sortedDirections[2].Value] = isOutside[sortedDirections[3].Value] = false;
                }
                else {
                    isOutside[sortedDirections[1].Value] = isOutside[sortedDirections[2].Value] = true;
                    isOutside[sortedDirections[3].Value] = isOutside[sortedDirections[0].Value] = false;
                }

                //find first eligible segment that is not the current segment
                for (ushort i = 0; i < 4; i++)
                    if ((isOutside[i] == _isLookingForOutside(opType, (sbyte)(i % 2))) && (i != incomingDirection)) {
                        shapeSelector = (byte)(i % 2);
                        isIncreasing = (sbyte)(i / 2 == 0 ? 1 : -1);
                        currentSegment = intersection.index[shapeSelector];
                        return true;
                    }
                // if we reach here, it means that no segment is eligible! (it should only happen with difference opereation
                return false;
            }
            else {
                // determine which way to go
                int nextShapeSelector = (shapeSelector + 1) % 2;

                float d = inputShapes[nextShapeSelector].getDirectionAfter(intersection.index[nextShapeSelector]).DotProduct(inputShapes[shapeSelector].getNormalAfter(currentSegment));
                isIncreasing = _isIncreasing(d, opType, (sbyte)nextShapeSelector);

                shapeSelector = (byte)nextShapeSelector;

                currentSegment = intersection.index[shapeSelector];
                return true;
            }
        }
コード例 #12
0
        /// Converts the path to a shape, with Y=0

        //-----------------------------------------------------------------------
        //
        //ORIGINAL LINE: Shape convertToShape() const
        public Shape convertToShape() {
            Shape s = new Shape();
            //for (List<Vector3>.Enumerator it = mPoints.GetEnumerator(); it.MoveNext(); ++it)
            foreach (var it in mPoints) {
                s.addPoint(it.x, it.y);
            }
            if (mClosed)
                s.close();

            return s;
        }
コード例 #13
0
 //-----------------------------------------------------------------------
 void parsePolygon(ref MultiShape @out, XmlNode pPolygonNode) {
     //if (pPolygonNode->first_attribute("points"))
     if (pPolygonNode.Attributes["points"] != null) {
         //if (pPolygonNode->first_attribute("points")->value_size() < 3) return;
         if (string.IsNullOrEmpty(pPolygonNode.Attributes["points"].Value)) return;
         if (pPolygonNode.Attributes["points"].Value.Length < 3) return;
         string temp = xtrim(pPolygonNode.Attributes["points"].Value);
         std_vector<string> pts = split(temp, " ");
         if (pts.size() == 0) return;
         Shape s = new Shape();
         for (int i = 0; i < pts.size() - 1; i += 2)
             s.addPoint(parseReal(pts[i + 0]), parseReal(pts[i + 1]));
         if (s.getPointsReference().size() == 0) return;
         s.close();
         //		if(pPolygonNode->first_attribute("id"))
         //		ss.id = pPolygonNode->first_attribute("id")->value();
         s.translate(getAttribTranslate(pPolygonNode));
         @out.addShape(s);
     }
 }
コード例 #14
0
//    *
//	 * Build a MultiShape from chars (one Shape per character)
//	 * \exception Ogre::InternalErrorException Freetype error
//	 * \todo Need to split shapes of multi region chars. For example the letter \c O
//	 * has two shapes, but they are connected to one shape.
//	 
	public MultiShape realizeShapes()
	{
		MultiShape retVal = new MultiShape();
	
		FT_Library ftlib = new FT_Library();
		FT_Face face = new FT_Face();
		FT_GlyphSlot slot = new FT_GlyphSlot();
	
		FT_Error error = FT_Init_FreeType(ftlib);
		if (error == 0)
		{
			error = FT_New_Face(ftlib, getFontFileByName().c_str(), 0, face);
			if (error == FT_Err_Unknown_File_Format)
			{
	//C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __LINE__ macro:
	//C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __FILE__ macro:
				throw ExceptionFactory.create(Mogre.ExceptionCodeType<Mogre.Exception.ExceptionCodes.ERR_INTERNAL_ERROR>(), "FreeType ERROR: FT_Err_Unknown_File_Format", "Procedural::TextShape::realizeShapes()", __FILE__, __LINE__);
				;
			}
			else if (error != null)
			{
	//C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __LINE__ macro:
	//C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __FILE__ macro:
				throw ExceptionFactory.create(Mogre.ExceptionCodeType<Mogre.Exception.ExceptionCodes.ERR_INTERNAL_ERROR>(), "FreeType ERROR: FT_New_Face - " + StringConverter.toString(error), "Procedural::TextShape::realizeShapes()", __FILE__, __LINE__);
				;
			}
			else
			{
				FT_Set_Pixel_Sizes(face, 0, mFontSize);
	
				int px = 0;
				int py = 0;
				slot = face.glyph;
	
				for (int n = 0; n < mText.length(); n++)
				{
					error = FT_Load_Char(face, mText[n], FT_LOAD_NO_BITMAP);
					if (error != null)
						continue;
	
					Shape s = new Shape();
	
					int nContours = face.glyph.outline.n_contours;
					int startPos = 0;
					string tags = face.glyph.outline.tags;
					FT_Vector[] vec = face.glyph.outline.points;
	
					for (int k = 0; k < nContours; k++)
					{
						if (k > 0)
							startPos = face.glyph.outline.contours[k-1]+1;
						int endPos = face.glyph.outline.contours[k]+1;
	
						Vector2 lastPoint = Vector2.ZERO;
						for (int j = startPos; j < endPos; j++)
						{
							if (FT_CURVE_TAG(tags[j]) == FT_CURVE_TAG_ON)
							{
								lastPoint = Vector2((float)vec[j].x, (float)vec[j].y);
								s.addPoint(lastPoint / 64.0f);
							}
							else
							{
								if (FT_CURVE_TAG(tags[j]) == FT_CURVE_TAG_CUBIC)
								{
									int prevPoint = j - 1;
									if (j == 0)
										prevPoint = endPos - 1;
									int nextIndex = j + 1;
									if (nextIndex >= endPos)
										nextIndex = startPos;
									Vector2[] nextPoint = new Vector2[nextIndex]((float)vec.x, (float)vec[nextIndex].y);
									if ((FT_CURVE_TAG(tags[prevPoint]) != FT_CURVE_TAG_ON) && (FT_CURVE_TAG(tags[prevPoint]) == FT_CURVE_TAG_CUBIC))
									{
										BezierCurve2 bc = new BezierCurve2();
										bc.addPoint(Vector2((float)vec[prevPoint].x, (float)vec[prevPoint].y) / 64.0f);
										bc.addPoint(Vector2((float)vec[j].x, (float)vec[j].y) / 64.0f);
										bc.addPoint(Vector2((float)vec[nextIndex].x, (float)vec[nextIndex].y) / 64.0f);
										s.appendShape(bc.realizeShape());
									}
								}
								else
								{
									Vector2[] conicPoint = new Vector2[j]((float)vec.x, (float)vec[j].y);
									if (j == startPos)
									{
										if ((FT_CURVE_TAG(tags[endPos-1]) != FT_CURVE_TAG_ON) && (FT_CURVE_TAG(tags[endPos-1]) != FT_CURVE_TAG_CUBIC))
										{
											Vector2[] lastConnic = new Vector2[endPos - 1]((float)vec.x, (float)vec[endPos - 1].y);
											lastPoint = (conicPoint + lastConnic) / 2;
										}
									}
	
									int nextIndex = j + 1;
									if (nextIndex >= endPos)
										nextIndex = startPos;
	
									Vector2[] nextPoint = new Vector2[nextIndex]((float)vec.x, (float)vec[nextIndex].y);
	
									bool nextIsConnic = (FT_CURVE_TAG(tags[nextIndex]) != FT_CURVE_TAG_ON) && (FT_CURVE_TAG(tags[nextIndex]) != FT_CURVE_TAG_CUBIC);
									if (nextIsConnic)
										nextPoint = (conicPoint + nextPoint) / 2;
	
									int pc = s.getPointCount();
									BezierCurve2 bc = new BezierCurve2();
									if (pc == 0)
										bc.addPoint(Vector2.ZERO);
									else
										bc.addPoint(s.getPoint(pc - 1));
									bc.addPoint(lastPoint / 64.0f);
									bc.addPoint(conicPoint / 64.0f);
									bc.addPoint(nextPoint / 64.0f);
									if (pc == 0)
										s.appendShape(bc.realizeShape());
									else
									{
										List<Vector2> subShape = bc.realizeShape().getPoints();
										for (List<Vector2>.Enumerator iter = subShape.GetEnumerator(); iter.MoveNext(); iter++)
										{
											if (iter != subShape.GetEnumerator())
												s.addPoint(iter.Current);
										}
									}
	
									if (nextIsConnic)
//
//ORIGINAL LINE: lastPoint = nextPoint;
										lastPoint=(nextPoint);
								}
							}
						}
					}
	
					s.close();
					s.translate((float)px, (float)py);
					retVal.addShape(s);
	
					px += slot.advance.x >> 6;
					py += slot.advance.y >> 6;
				}
				FT_Done_Face(face);
			}
			FT_Done_FreeType(ftlib);
		}
		else
		{
	//C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __LINE__ macro:
	//C++ TO C# CONVERTER TODO TASK: There is no direct equivalent in C# to the C++ __FILE__ macro:
			throw ExceptionFactory.create(Mogre.ExceptionCodeType<Mogre.Exception.ExceptionCodes.ERR_INTERNAL_ERROR>(), "FreeType ERROR: FT_Init_FreeTyp", "Procedural::TextShape::realizeShapes()", __FILE__, __LINE__);
			;
		}
	
		return retVal;
	}