internal OutsideEdgeLine(GlyphTriangle ownerTriangle, GlyphPoint p, GlyphPoint q) : base(ownerTriangle, p, q) { //set back p.SetOutsideEdgeUnconfirmEdgeDirection(this); q.SetOutsideEdgeUnconfirmEdgeDirection(this); _newDynamicMidPoint = new Vector2((p.OX + q.OX) / 2, (p.OY + q.OY) / 2); }
void AddPoint(float x, float y, PointKind kind) { var p = new GlyphPoint(x, y, kind); #if DEBUG p.dbugOwnerPart = dbug_ownerPart; #endif points.Add(p); }
/// <summary> /// find bounds of new fit glyph /// </summary> /// <param name="minX"></param> /// <param name="minY"></param> /// <param name="maxX"></param> /// <param name="maxY"></param> internal void FindBounds(ref float minX, ref float minY, ref float maxX, ref float maxY) { for (int i = flattenPoints.Count - 1; i >= 0; --i) { GlyphPoint p = flattenPoints[i]; MyMath.FindMinMax(ref minX, ref maxX, p.X); MyMath.FindMinMax(ref minY, ref maxY, p.Y); } }
public bool IsClockwise() { //after flatten if (_analyzedClockDirection) { return(_isClockwise); } List <GlyphPoint> f_points = this.flattenPoints; if (f_points == null) { throw new NotSupportedException(); } _analyzedClockDirection = true; //TODO: review here again*** //--------------- //http://stackoverflow.com/questions/1165647/how-to-determine-if-a-list-of-polygon-points-are-in-clockwise-order //check if hole or not //clockwise or counter-clockwise { //Some of the suggested methods will fail in the case of a non-convex polygon, such as a crescent. //Here's a simple one that will work with non-convex polygons (it'll even work with a self-intersecting polygon like a figure-eight, telling you whether it's mostly clockwise). //Sum over the edges, (x2 − x1)(y2 + y1). //If the result is positive the curve is clockwise, //if it's negative the curve is counter-clockwise. (The result is twice the enclosed area, with a +/- convention.) int j = flattenPoints.Count; double total = 0; for (int i = 1; i < j; ++i) { GlyphPoint p0 = f_points[i - 1]; GlyphPoint p1 = f_points[i]; total += (p1.OX - p0.OX) * (p1.OY + p0.OY); } //the last one { GlyphPoint p0 = f_points[j - 1]; GlyphPoint p1 = f_points[0]; total += (p1.OX - p0.OX) * (p1.OY + p0.OY); } _isClockwise = total >= 0; } return(_isClockwise); }
/// <summary> /// find common edge of 2 glyph points /// </summary> /// <param name="p"></param> /// <param name="q"></param> /// <returns></returns> internal static OutsideEdgeLine FindCommonOutsideEdge(GlyphPoint p, GlyphPoint q) { if (p.E0 == q.E0 || p.E0 == q.E1) { return(p.E0); } else if (p.E1 == q.E0 || p.E1 == q.E1) { return(p.E1); } else { return(null); } }
internal void CreateGlyphEdges() { int lim = flattenPoints.Count - 1; GlyphPoint p = null, q = null; OutsideEdgeLine edgeLine = null; _edges = new List <OutsideEdgeLine>(); // for (int i = 0; i < lim; ++i) { //in order ... p = flattenPoints[i]; q = flattenPoints[i + 1]; if ((edgeLine = EdgeLine.FindCommonOutsideEdge(p, q)) != null) { //from p point to q //so ... //edgeLine is outwardEdge for p. //edgeLine is inwardEdge for q. //p.OutwardEdge = q.InwardEdge = edgeLine; _edges.Add(edgeLine); } else { //? } } //close p = flattenPoints[lim]; q = flattenPoints[0]; if ((edgeLine = EdgeLine.FindCommonOutsideEdge(p, q)) != null) { //from p point to q //so ... //edgeLine is outwardEdge for p. //edgeLine is inwardEdge for q. //p.OutwardEdge = q.InwardEdge = edgeLine; _edges.Add(edgeLine); } else { //not found } }
internal EdgeLine(GlyphTriangle ownerTriangle, GlyphPoint p, GlyphPoint q) { //this canbe inside edge or outside edge this._ownerTriangle = ownerTriangle; //------------------------------------ //an edge line connects 2 glyph points. //it is created from triangulation process. // //some edge line is either 'INSIDE' edge OR 'OUTSIDE'. // //------------------------------------ this._glyphPoint_P = p; this._glyphPoint_Q = q; //new dynamic mid point is calculate from original X,Y //------------------------------- //analyze angle and slope kind //------------------------------- //slope kind is evaluated SlopeAngleNoDirection = this.GetSlopeAngleNoDirection(); if (QX == PX) { this.SlopeKind = LineSlopeKind.Vertical; } else { if (SlopeAngleNoDirection > _85degreeToRad) { SlopeKind = LineSlopeKind.Vertical; } else if (SlopeAngleNoDirection < _01degreeToRad) { SlopeKind = LineSlopeKind.Horizontal; p.IsPartOfHorizontalEdge = q.IsPartOfHorizontalEdge = true; } else { SlopeKind = LineSlopeKind.Other; } } }
/// <summary> /// create polygon from GlyphContour /// </summary> /// <param name="cnt"></param> /// <returns></returns> static Poly2Tri.Polygon CreatePolygon(List <GlyphPoint> flattenPoints) { List <Poly2Tri.TriangulationPoint> points = new List <Poly2Tri.TriangulationPoint>(); //limitation: poly tri not accept duplicated points! *** double prevX = 0; double prevY = 0; #if DEBUG //dbug check if all point is unique dbugCheckAllGlyphsAreUnique(flattenPoints); #endif int j = flattenPoints.Count; //pass for (int i = 0; i < j; ++i) { GlyphPoint p = flattenPoints[i]; double x = p.OX; //start from original X*** double y = p.OY; //start from original Y*** if (x == prevX && y == prevY) { if (i > 0) { throw new NotSupportedException(); } } else { var triPoint = new Poly2Tri.TriangulationPoint(prevX = x, prevY = y) { userData = p }; #if DEBUG p.dbugTriangulationPoint = triPoint; #endif points.Add(triPoint); } } return(new Poly2Tri.Polygon(points.ToArray())); }
/// <summary> /// update dynamic cutpoint of 2 adjacent edges /// </summary> /// <param name="p"></param> static void UpdateNewEdgeCut(GlyphPoint p) { OutsideEdgeLine e0 = p.E0; OutsideEdgeLine e1 = p.E1; Vector2 tmp_e0_q = e0._newDynamicMidPoint + e0.GetOriginalEdgeVector(); Vector2 tmp_e1_p = e1._newDynamicMidPoint - e1.GetOriginalEdgeVector(); Vector2 cutpoint; if (MyMath.FindCutPoint(e0._newDynamicMidPoint, tmp_e0_q, e1._newDynamicMidPoint, tmp_e1_p, out cutpoint)) { p.SetNewXY(cutpoint.X, cutpoint.Y); } else { //pararell edges } }
internal void Flatten(GlyphPartFlattener flattener) { //flatten once if (_analyzed) { return; } //flatten each part ... //------------------------------- int j = parts.Count; //--------------- List <GlyphPoint> prevResult = flattener.Result; List <GlyphPoint> tmpFlattenPoints = flattenPoints = flattener.Result = new List <GlyphPoint>(); //start ... for (int i = 0; i < j; ++i) { //flatten each part parts[i].Flatten(flattener); } //check duplicated the first point and last point int pointCount = tmpFlattenPoints.Count; if (GlyphPoint.SameCoordAs(tmpFlattenPoints[pointCount - 1], tmpFlattenPoints[0])) { //check if the last point is the same value as the first //if yes => remove the last one tmpFlattenPoints.RemoveAt(pointCount - 1); pointCount--; } //assign number for all glyph point in this contour for (int i = 0; i < pointCount; ++i) { tmpFlattenPoints[i].SeqNo = i; } flattener.Result = prevResult; _analyzed = true; }
static void dbugCheckAllGlyphsAreUnique(List <GlyphPoint> flattenPoints) { double prevX = 0; double prevY = 0; s_debugTmpPoints = new Dictionary <dbugTmpPoint, bool>(); int lim = flattenPoints.Count - 1; for (int i = 0; i < lim; ++i) { GlyphPoint p = flattenPoints[i]; double x = p.OX; //start from original X*** double y = p.OY; //start from original Y*** if (x == prevX && y == prevY) { if (i > 0) { throw new NotSupportedException(); } } else { dbugTmpPoint tmp_point = new dbugTmpPoint(x, y); if (!s_debugTmpPoints.ContainsKey(tmp_point)) { //ensure no duplicated point s_debugTmpPoints.Add(tmp_point, true); } else { throw new NotSupportedException(); } prevX = x; prevY = y; } } }
internal InsideEdgeLine(GlyphTriangle ownerTriangle, GlyphPoint p, GlyphPoint q) : base(ownerTriangle, p, q) { }
internal bool ContainsGlyphPoint(GlyphPoint p) { return(this._glyphPoint_P == p || this._glyphPoint_Q == p); }