static void CreateBoneJointIfNeed( InsideEdgeLine insideEdge, GlyphTriangle first_p_tri, GlyphBoneJoint firstJoint, List <GlyphBone> newlyCreatedBones, List <GlyphBone> glyphBones) { if (insideEdge != null && insideEdge.inside_joint == null) { InsideEdgeLine mainEdge = insideEdge; EdgeLine nbEdge = null; if (FindSameCoordEdgeLine(first_p_tri.N0, mainEdge, out nbEdge) || FindSameCoordEdgeLine(first_p_tri.N1, mainEdge, out nbEdge) || FindSameCoordEdgeLine(first_p_tri.N2, mainEdge, out nbEdge)) { //confirm that nbEdge is INSIDE edge if (nbEdge.IsInside) { GlyphBoneJoint joint = new GlyphBoneJoint((InsideEdgeLine)nbEdge, mainEdge); GlyphBone bone = new GlyphBone(mainEdge.inside_joint, firstJoint); newlyCreatedBones.Add(bone); glyphBones.Add(bone); } else { //? } } else { //? } } }
static bool FindCommonInsideEdges(GlyphTriangle a, GlyphTriangle b, out InsideEdgeLine a_edge, out InsideEdgeLine b_edge) { //2 contact triangles share GlyphBoneJoint. EdgeLine find_b_edge = b.e0; InsideEdgeLine matching_inside_edge_of_a = null; if ((matching_inside_edge_of_a = FindCommonInsideEdge(a, find_b_edge)) != null) { //found a_edge = matching_inside_edge_of_a; b_edge = (InsideEdgeLine)find_b_edge; return(true); } //-------------- find_b_edge = b.e1; if ((matching_inside_edge_of_a = FindCommonInsideEdge(a, find_b_edge)) != null) { //found a_edge = matching_inside_edge_of_a; b_edge = (InsideEdgeLine)find_b_edge; return(true); } find_b_edge = b.e2; if ((matching_inside_edge_of_a = FindCommonInsideEdge(a, find_b_edge)) != null) { //found a_edge = matching_inside_edge_of_a; b_edge = (InsideEdgeLine)find_b_edge; return(true); } a_edge = b_edge = null; return(false); }
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); }
internal GlyphCentroidPair(GlyphTriangle p, GlyphTriangle q) { //each triangle has 1 centroid point //a centroid line connects between 2 adjacent triangles via centroid //p triangle=> (x0,y0) (centroid of p) //q triangle=> (x1,y1) (centroid of q) //a centroid line move from p to q this.p = p; this.q = q; }
static int FindLatestConnectedTri(List <GlyphTriangle> usedTriList, GlyphTriangle tri) { //search back *** for (int i = usedTriList.Count - 1; i >= 0; --i) { if (usedTriList[i].IsConnectedTo(tri)) { return(i); } } return(-1); }
public bool IsConnectedTo(GlyphTriangle anotherTri) { DelaunayTriangle t2 = anotherTri._tri; if (t2 == this._tri) { throw new NotSupportedException(); } //compare each neighbor return this._tri.N0 == t2 || this._tri.N1 == t2 || this._tri.N2 == t2; }
public void CreateBoneLinkBetweenCentroidLine(List <GlyphBone> newlyCreatedBones) { foreach (CentroidLine line in _lines.Values) { List <GlyphBone> glyphBones = line.bones; GlyphBoneJoint firstJoint = line._joints[0]; GlyphTriangle first_p_tri = firstJoint.P_Tri; // CreateBoneJointIfNeed(first_p_tri.e0 as InsideEdgeLine, first_p_tri, firstJoint, newlyCreatedBones, glyphBones); CreateBoneJointIfNeed(first_p_tri.e1 as InsideEdgeLine, first_p_tri, firstJoint, newlyCreatedBones, glyphBones); CreateBoneJointIfNeed(first_p_tri.e2 as InsideEdgeLine, first_p_tri, firstJoint, newlyCreatedBones, glyphBones); } }
/// <summary> /// find nearest joint that contains tri /// </summary> /// <param name="tri"></param> /// <returns></returns> public GlyphBoneJoint FindNearestJoint(GlyphTriangle tri) { for (int i = _joints.Count - 1; i >= 0; --i) { GlyphBoneJoint joint = _joints[i]; //each pair has 1 bone joint //once we have 1 candidate if (joint.ComposeOf(tri)) { //found another joint return(joint); } } return(null); }
public bool FindBoneJoint(GlyphTriangle tri, out CentroidLine foundOnBranch, out GlyphBoneJoint foundOnJoint) { foreach (CentroidLine line in _lines.Values) { if ((foundOnJoint = line.FindNearestJoint(tri)) != null) { foundOnBranch = line; return(true); } } foundOnBranch = null; foundOnJoint = null; return(false); }
static EdgeLine FindAnotherOutsideEdge(GlyphTriangle tri, EdgeLine knownOutsideEdge) { if (tri.e0.IsOutside && tri.e0 != knownOutsideEdge) { return(tri.e0); } if (tri.e1.IsOutside && tri.e1 != knownOutsideEdge) { return(tri.e1); } if (tri.e2.IsOutside && tri.e2 != knownOutsideEdge) { return(tri.e2); } return(null); }
/// <summary> /// find nb triangle that has the same edgeLine /// </summary> /// <param name="tri"></param> /// <returns></returns> static bool FindSameCoordEdgeLine(GlyphTriangle tri, EdgeLine edgeLine, out EdgeLine foundEdge) { foundEdge = null; if (tri == null) { return(false); } if (SameCoord(foundEdge = tri.e0, edgeLine) || SameCoord(foundEdge = tri.e1, edgeLine) || SameCoord(foundEdge = tri.e2, edgeLine)) { return(true); } foundEdge = null; //not found return(false); }
/// <summary> /// set current centroid line to a centroid line that starts with triangle of centroid-line-head /// </summary> /// <param name="triOfCentroidLineHead"></param> public void SetCurrentCentroidLine(GlyphTriangle triOfCentroidLineHead) { //this method is used during centroid line hub creation if (currentBranchTri != triOfCentroidLineHead) { //check if we have already create it if (!_lines.TryGetValue(triOfCentroidLineHead, out currentLine)) { //if not found then create new currentLine = new CentroidLine(); #if DEBUG currentLine.dbugStartTri = triOfCentroidLineHead; #endif _lines.Add(triOfCentroidLineHead, currentLine); } currentBranchTri = triOfCentroidLineHead; } }
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> /// add information about each edge of a triangle, compare to the contactEdge of a ownerEdgeJoint /// </summary> /// <param name="triangle"></param> /// <param name="boneJoint"></param> /// <param name="knownInsideEdge"></param> static EdgeLine CreateTipEdgeIfNeed( double cent_slopAngle, GlyphTriangle triangle, EdgeLine knownInsideEdge) { int outsideCount; EdgeLine outside0, outside1, outside2, anotherInsideEdge; ClassifyTriangleEdges( triangle, knownInsideEdge, out anotherInsideEdge, out outside0, out outside1, out outside2, out outsideCount); switch (outsideCount) { default: throw new NotSupportedException(); case 0: case 1: break; case 3: throw new NotImplementedException(); //TODO: implement this case 2: //tip end //find which edge should be 'tip edge' //in this version we compare each edge slope to centroid line slope. //the most diff angle should be opposite edge (to the centroid) => tip edge //------------------------------------------------------------------------- EdgeLine tipEdge, notTipEdge; SelectMostProperTipEdge(cent_slopAngle, outside0, outside1, out tipEdge, out notTipEdge); return(tipEdge); } return(null); }
static InsideEdgeLine FindCommonInsideEdge(GlyphTriangle a, EdgeLine b_edge) { //2 contact triangles share GlyphBoneJoint. //compare 3 side of a's edge to b_edge if (b_edge.IsOutside) { return(null); } // if (IsMatchingEdge(a.e0, b_edge)) { return((InsideEdgeLine)a.e0); } if (IsMatchingEdge(a.e1, b_edge)) { return((InsideEdgeLine)a.e1); } if (IsMatchingEdge(a.e2, b_edge)) { return((InsideEdgeLine)a.e2); } return(null); }
/// <summary> /// find all outside edge a /// </summary> /// <param name="bone"></param> /// <param name="outsideEdges"></param> /// <returns></returns> public static void CollectOutsideEdge(this GlyphBone bone, System.Collections.Generic.List <EdgeLine> outsideEdges) { if (bone.JointB != null) { GlyphTriangle commonTri = FindCommonTriangle(bone.JointA, bone.JointB); if (commonTri != null) { if (commonTri.e0.IsOutside) { outsideEdges.Add(commonTri.e0); } if (commonTri.e1.IsOutside) { outsideEdges.Add(commonTri.e1); } if (commonTri.e2.IsOutside) { outsideEdges.Add(commonTri.e2); } } } else if (bone.TipEdge != null) { outsideEdges.Add(bone.TipEdge); EdgeLine found; if (ContainsEdge(bone.JointA.P_Tri, bone.TipEdge) && (found = FindAnotherOutsideEdge(bone.JointA.P_Tri, bone.TipEdge)) != null) { outsideEdges.Add(found); } else if (ContainsEdge(bone.JointA.Q_Tri, bone.TipEdge) && (found = FindAnotherOutsideEdge(bone.JointA.Q_Tri, bone.TipEdge)) != null) { outsideEdges.Add(found); } } }
internal bool ComposeOf(GlyphTriangle tri) { return(this.P_Tri == tri || this.Q_Tri == tri); }
static void CreateCentroidLineHubs(Polygon polygon, List <GlyphTriangle> triangles, List <CentroidLineHub> outputLineHubs) { //create triangle list from given DelaunayTriangle polygon. // Generate GlyphTriangle triangle from DelaunayTriangle foreach (DelaunayTriangle delnTri in polygon.Triangles) { delnTri.MarkAsActualTriangle(); triangles.Add(new GlyphTriangle(delnTri)); //all triangles are created from Triangulation process } //---------------------------- //create centroid line hub //---------------------------- //1. var centroidLineHubs = new Dictionary <GlyphTriangle, CentroidLineHub>(); CentroidLineHub currentCentroidLineHub = null; //2. temporary list of used triangles List <GlyphTriangle> usedTriList = new List <GlyphTriangle>(); GlyphTriangle latestTri = null; //we may walk forward and backward on each tri //so we record the used triangle into a usedTriList. int triCount = triangles.Count; for (int i = 0; i < triCount; ++i) { GlyphTriangle tri = triangles[i]; if (i == 0) { centroidLineHubs[tri] = currentCentroidLineHub = new CentroidLineHub(tri); usedTriList.Add(latestTri = tri); } else { //at a branch //one tri may connect with 3 NB triangle int foundIndex = FindLatestConnectedTri(usedTriList, tri); if (foundIndex < 0) { //? throw new NotSupportedException(); } else { //record used triangle usedTriList.Add(tri); GlyphTriangle connectWithPrevTri = usedTriList[foundIndex]; if (connectWithPrevTri != latestTri) { //branch CentroidLineHub lineHub; if (!centroidLineHubs.TryGetValue(connectWithPrevTri, out lineHub)) { //if not found then=> //start new CentroidLineHub centroidLineHubs[connectWithPrevTri] = lineHub = new CentroidLineHub(connectWithPrevTri); //create linehub to line hub connection //TODO: review here //create centroid pair at link point } else { //this is multiple facets triangle for CentroidLineHub } currentCentroidLineHub = lineHub; //ensure start triangle of the branch lineHub.SetCurrentCentroidLine(tri); //create centroid line and add to currrent hub currentCentroidLineHub.AddCentroidPair(new GlyphCentroidPair(connectWithPrevTri, tri)); } else { //add centroid line to current multifacet joint if (currentCentroidLineHub.LineCount == 0) { //ensure start triangle of the branch currentCentroidLineHub.SetCurrentCentroidLine(tri); } //create centroid line and add to currrent hub currentCentroidLineHub.AddCentroidPair(new GlyphCentroidPair(connectWithPrevTri, tri)); } latestTri = tri; } } } //-------------------------------------------------------------- //copy to list, we not use the centroidLineHubs anymore outputLineHubs.AddRange(centroidLineHubs.Values); }
static bool ContainsEdge(GlyphTriangle tri, EdgeLine edge) { return(tri.e0 == edge || tri.e1 == edge || tri.e2 == edge); }
public CentroidLineHub(GlyphTriangle startTriangle) { this.startTriangle = startTriangle; }
internal InsideEdgeLine(GlyphTriangle ownerTriangle, GlyphPoint p, GlyphPoint q) : base(ownerTriangle, p, q) { }
static void ClassifyTriangleEdges( GlyphTriangle triangle, EdgeLine knownInsideEdge, out EdgeLine anotherInsideEdge, out EdgeLine outside0, out EdgeLine outside1, out EdgeLine outside2, out int outsideCount) { outsideCount = 0; outside0 = outside1 = outside2 = anotherInsideEdge = null; if (triangle.e0.IsOutside) { switch (outsideCount) { case 0: outside0 = triangle.e0; break; case 1: outside1 = triangle.e0; break; case 2: outside2 = triangle.e0; break; } outsideCount++; } else { //e0 is not known inside edge if (triangle.e0 != knownInsideEdge) { anotherInsideEdge = triangle.e0; } } // if (triangle.e1.IsOutside) { switch (outsideCount) { case 0: outside0 = triangle.e1; break; case 1: outside1 = triangle.e1; break; case 2: outside2 = triangle.e1; break; } outsideCount++; } else { if (triangle.e1 != knownInsideEdge) { anotherInsideEdge = triangle.e1; } } // if (triangle.e2.IsOutside) { switch (outsideCount) { case 0: outside0 = triangle.e2; break; case 1: outside1 = triangle.e2; break; case 2: outside2 = triangle.e2; break; } outsideCount++; } else { if (triangle.e2 != knownInsideEdge) { anotherInsideEdge = triangle.e2; } } }
internal static bool ContainsTriangle(this EdgeLine edge, GlyphTriangle p) { return(p.e0 == edge || p.e1 == edge || p.e2 == edge); }
/// <summary> /// create a set of GlyphBone /// </summary> /// <param name="newlyCreatedBones"></param> public void CreateBones(List <GlyphBone> newlyCreatedBones) { foreach (CentroidLine line in _lines.Values) { List <GlyphBoneJoint> jointlist = line._joints; //start with empty bone list List <GlyphBone> glyphBones = line.bones; int j = jointlist.Count; if (j == 0) { continue; } // GlyphBoneJoint joint = jointlist[0]; //first { GlyphTriangle firstTri = joint.P_Tri; //test 3 edges, find edge that is inside //and the joint is not the same as first_pair.BoneJoint CreateTipBoneIfNeed(firstTri.e0 as InsideEdgeLine, joint, newlyCreatedBones, glyphBones); CreateTipBoneIfNeed(firstTri.e1 as InsideEdgeLine, joint, newlyCreatedBones, glyphBones); CreateTipBoneIfNeed(firstTri.e2 as InsideEdgeLine, joint, newlyCreatedBones, glyphBones); } for (int i = 0; i < j; ++i) { //for each GlyphCentroidPair //create bone that link the GlyphBoneJoint of the pair joint = jointlist[i]; //if (joint.dbugId > 20) //{ //} if (joint.TipEdgeP != null) { GlyphBone tipBone = new GlyphBone(joint, joint.TipEdgeP); newlyCreatedBones.Add(tipBone); glyphBones.Add(tipBone); } //----------------------------------------------------- if (i < j - 1) { //not the last one GlyphBoneJoint nextJoint = jointlist[i + 1]; GlyphBone bone = new GlyphBone(joint, nextJoint); newlyCreatedBones.Add(bone); glyphBones.Add(bone); } if (joint.TipEdgeQ != null) { GlyphBone tipBone = new GlyphBone(joint, joint.TipEdgeQ); newlyCreatedBones.Add(tipBone); glyphBones.Add(tipBone); } } //for (int i = 1; i < j; ++i) //{ // joint = jointlist[i]; //first // { // GlyphTriangle tri = joint.P_Tri; // //test 3 edges, find edge that is inside // //and the joint is not the same as first_pair.BoneJoint // CreateTipBoneIfNeed(tri.e0 as InsideEdgeLine, joint, newlyCreatedBones, glyphBones); // CreateTipBoneIfNeed(tri.e1 as InsideEdgeLine, joint, newlyCreatedBones, glyphBones); // CreateTipBoneIfNeed(tri.e2 as InsideEdgeLine, joint, newlyCreatedBones, glyphBones); // } //} } }