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 { //? } } }
/// <summary> /// find a perpendicular cut-point from p to bone /// </summary> /// <param name="bone"></param> /// <param name="p"></param> /// <param name="cutPoint"></param> /// <returns></returns> public static bool FindPerpendicularCutPoint(GlyphBone bone, Vector2 p, out Vector2 cutPoint) { if (bone.JointB != null) { cutPoint = FindPerpendicularCutPoint( bone.JointA.OriginalJointPos, bone.JointB.OriginalJointPos, p); //find min /max Vector2 min, max; GetMinMax(bone, out min, out max); return(cutPoint.X >= min.X && cutPoint.X <= max.X && cutPoint.Y >= min.Y && cutPoint.Y <= max.Y); } else { //to tip if (bone.TipEdge != null) { cutPoint = FindPerpendicularCutPoint( bone.JointA.OriginalJointPos, bone.TipEdge.GetMidPoint(), p); Vector2 min, max; GetMinMax(bone, out min, out max); return(cutPoint.X >= min.X && cutPoint.X <= max.X && cutPoint.Y >= min.Y && cutPoint.Y <= max.Y); } else { throw new System.NotSupportedException(); } } }
static void CreateTipBoneIfNeed( InsideEdgeLine insideEdge, GlyphBoneJoint joint, List <GlyphBone> newlyCreatedBones, List <GlyphBone> glyphBones) { if (insideEdge != null && insideEdge.inside_joint != null && insideEdge.inside_joint != joint) { //create connection GlyphBone tipBone = new GlyphBone(insideEdge.inside_joint, joint); newlyCreatedBones.Add(tipBone); glyphBones.Add(tipBone); } }
//utils for glyph bones public static Vector2 GetMidPoint(this GlyphBone bone) { if (bone.JointB != null) { return((bone.JointA.OriginalJointPos + bone.JointB.OriginalJointPos) / 2); } else if (bone.TipEdge != null) { Vector2 edge = bone.TipEdge.GetMidPoint(); return((edge + bone.JointA.OriginalJointPos) / 2); } else { return(Vector2.Zero); } }
internal void CollectOutsideEdges(List <EdgeLine> tmpEdges) { tmpEdges.Clear(); int index = this.startIndex; for (int n = this.count - 1; n >= 0; --n) { GlyphBone bone = ownerCentroidLine.bones[index]; //collect all outside edge around glyph bone bone.CollectOutsideEdge(tmpEdges); index++; } // if (tmpEdges.Count == 0) { return; } this.edges = tmpEdges.ToArray(); }
static void GetMinMax(GlyphBone bone, out Vector2 min, out Vector2 max) { if (bone.JointB != null) { var a_pos = bone.JointA.OriginalJointPos; var b_pos = bone.JointB.OriginalJointPos; min = Vector2.Min(a_pos, b_pos); max = Vector2.Max(a_pos, b_pos); } else if (bone.TipEdge != null) { var a_pos = bone.JointA.OriginalJointPos; var tip_pos = bone.TipEdge.GetMidPoint(); min = Vector2.Min(a_pos, tip_pos); max = Vector2.Max(a_pos, tip_pos); } else { throw new System.NotSupportedException(); } }
/// <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); } } }
/// <summary> /// apply grid box to all bones in this line /// </summary> /// <param name="gridW"></param> /// <param name="gridH"></param> public void ApplyGridBox(List <BoneGroup> boneGroups, int gridW, int gridH) { //1. apply grid box to each joint for (int i = _joints.Count - 1; i >= 0; --i) { _joints[i].AdjustFitXY(gridW, gridH); } //2. (re) calculate slope for all bones. for (int i = bones.Count - 1; i >= 0; --i) { bones[i].EvaluateSlope(); } //3. re-grouping int j = bones.Count; BoneGroup boneGroup = new BoneGroup(this); //new group boneGroup.slopeKind = LineSlopeKind.Other; // float approxLen = 0; float ypos_sum = 0; float xpos_sum = 0; for (int i = 0; i < j; ++i) { GlyphBone bone = bones[i]; LineSlopeKind slope = bone.SlopeKind; Vector2 mid_pos = bone.GetMidPoint(); if (slope != boneGroup.slopeKind) { //add existing to list and create a new group if (boneGroup.count > 0) { //add existing bone group to bone-group list boneGroup.approxLength = approxLen; boneGroup.avg_x = xpos_sum / boneGroup.count; boneGroup.avg_y = ypos_sum / boneGroup.count; // boneGroups.Add(boneGroup); } // boneGroup = new BoneGroup(this); boneGroup.startIndex = i; boneGroup.slopeKind = slope; // boneGroup.count++; approxLen = bone.EvaluateFitLength(); //reset // xpos_sum = mid_pos.X; ypos_sum = mid_pos.Y; } else { boneGroup.count++; approxLen += bone.EvaluateFitLength(); //append // xpos_sum += mid_pos.X; ypos_sum += mid_pos.Y; } } // if (boneGroup.count > 0) { boneGroup.approxLength = approxLen; boneGroup.avg_x = xpos_sum / boneGroup.count; boneGroup.avg_y = ypos_sum / boneGroup.count; boneGroups.Add(boneGroup); } }
/// <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); // } //} } }
protected abstract void OnDrawBone(GlyphBone bone, int boneIndex);