예제 #1
0
 static bool SameCoord(EdgeLine a, EdgeLine b)
 {
     //TODO: review this again
     return((a.P == b.P ||
             a.P == b.Q) &&
            (a.Q == b.P ||
             a.Q == b.Q));
 }
예제 #2
0
 public static void dbugGetScaledXY(this EdgeLine edge, out double px, out double py, out double qx, out double qy, float scale)
 {
     px = edge.PX * scale;
     py = edge.PY * scale;
     //
     qx = edge.QX * scale;
     qy = edge.QY * scale;
 }
예제 #3
0
        /// <summary>
        /// which one is min,max
        /// </summary>
        /// <param name="min"></param>
        /// <param name="max"></param>
        static void GetMinMax(EdgeLine edge, out Vector2 min, out Vector2 max)
        {
            Vector2 a_pos = new Vector2((float)edge.PX, (float)edge.PY);
            Vector2 b_pos = new Vector2((float)edge.QX, (float)edge.QY);

            min = Vector2.Min(a_pos, b_pos);
            max = Vector2.Max(a_pos, b_pos);
        }
예제 #4
0
        public GlyphBone(GlyphBoneJoint a, EdgeLine tipEdge)
        {
            JointA  = a;
            TipEdge = tipEdge;
            Vector2 midPoint = tipEdge.GetMidPoint();

            _len = Math.Sqrt(a.CalculateSqrDistance(midPoint));
            EvaluateSlope();
        }
        internal void SetTipEdge_P(EdgeLine e)
        {
#if DEBUG
            if (_tipEdge_p != null)
            {
                throw new System.NotSupportedException();
            }
#endif
            e.IsTip         = true;
            this._tipEdge_p = e;
        }
예제 #6
0
        internal void SetControlEdge(EdgeLine controlEdge)
        {
            //check if edge is connect to p or q

#if DEBUG
            if (!controlEdge.IsInside)
            {
            }
#endif
            //----------------
            if (_glyphPoint_P == controlEdge._glyphPoint_P)
            {
#if DEBUG
                if (_ctrlEdge_P != null && _ctrlEdge_P != controlEdge)
                {
                }
#endif
                //map this p to p of the control edge
                _ctrlEdge_P = controlEdge;
            }
            else if (_glyphPoint_P == controlEdge.Q)
            {
#if DEBUG
                if (_ctrlEdge_P != null && _ctrlEdge_P != controlEdge)
                {
                }
#endif
                _ctrlEdge_P = controlEdge;
            }
            else if (_glyphPoint_Q == controlEdge._glyphPoint_P)
            {
#if DEBUG
                if (_ctrlEdge_Q != null && _ctrlEdge_Q != controlEdge)
                {
                }
#endif
                _ctrlEdge_Q = controlEdge;
            }
            else if (_glyphPoint_Q == controlEdge.Q)
            {
#if DEBUG
                if (_ctrlEdge_Q != null && _ctrlEdge_Q != controlEdge)
                {
                }
#endif
                _ctrlEdge_Q = controlEdge;
            }
            else
            {
                //?
            }
        }
예제 #7
0
 static void FindPerpendicular(EdgeLine outsideEdge, EdgeLine inside)
 {
     System.Numerics.Vector2 m0 = inside.GetMidPoint();
     System.Numerics.Vector2 cut_fromM0;
     if (MyMath.FindPerpendicularCutPoint(outsideEdge, new System.Numerics.Vector2(m0.X, m0.Y), out cut_fromM0))
     {
         ((OutsideEdgeLine)outsideEdge).SetControlEdge(inside);
     }
     else
     {
     }
     outsideEdge._earlyInsideAnalysis = inside._earlyInsideAnalysis = true;
 }
예제 #8
0
        /// <summary>
        /// find cut point and check if the cut point is on the edge
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="p2"></param>
        /// <param name="cutResult"></param>
        /// <returns></returns>
        public static bool FindPerpendicularCutPoint(EdgeLine edge, Vector2 p2, out Vector2 cutResult)
        {
            cutResult = FindPerpendicularCutPoint(
                new Vector2((float)edge.PX, (float)edge.PY),
                new Vector2((float)edge.QX, (float)edge.QY),
                p2);
            //also check if result cutpoint is on current line segment or not

            Vector2 min, max;

            GetMinMax(edge, out min, out max);
            return(cutResult.X >= min.X && cutResult.X <= max.X && cutResult.Y >= min.Y && cutResult.Y <= max.Y);
        }
        public void CalculateBounds(ref float minX, ref float minY, ref float maxX, ref float maxY)
        {
            for (int e = edges.Length - 1; e >= 0; --e)
            {
                EdgeLine edge = edges[e];

                // x
                MyMath.FindMinMax(ref minX, ref maxX, (float)edge.PX);
                MyMath.FindMinMax(ref minX, ref maxX, (float)edge.QX);
                // y
                MyMath.FindMinMax(ref minY, ref maxY, (float)edge.PY);
                MyMath.FindMinMax(ref minY, ref maxY, (float)edge.QY);
            }
        }
예제 #10
0
        internal void SetTipEdge_Q(EdgeLine e)
        {
#if DEBUG
            if (_tipEdge_q != null)
            {
                throw new System.NotSupportedException();
            }
            if (_tipEdge_q != null && _tipEdge_q == _tipEdge_p)
            {
                throw new System.NotSupportedException();
            }
#endif
            e.IsTip    = true;
            _tipEdge_q = e;
        }
예제 #11
0
 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);
        }
예제 #13
0
        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
            }
        }
예제 #14
0
 /// <summary>
 /// check if the 2 triangle is matching or not
 /// </summary>
 /// <param name="a"></param>
 /// <param name="b"></param>
 /// <returns></returns>
 static bool IsMatchingEdge(EdgeLine a, EdgeLine b)
 {
     //x-axis
     if ((a.PX == b.PX && a.QX == b.QX) ||
         (a.PX == b.QX && a.QX == b.PX))
     {
         //pass x-axis
         //
         //y_axis
         if ((a.PY == b.PY && a.QY == b.QY) ||
             (a.PY == b.QY && a.QY == b.PY))
         {
             return(true);
         }
     }
     //otherwise...
     return(false);
 }
예제 #15
0
        /// <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);
        }
예제 #16
0
 void AnalyzeInsideEdge(EdgeLine d0, EdgeLine d1, EdgeLine d2)
 {
     if (d0._earlyInsideAnalysis)
     {
         return;
     }
     if (!d0.IsInside)
     {
         return;
     }
     //-------------------------------------------------
     //maybeInsideEdge is Inside ***
     //check another
     if (d1.IsInside)
     {
         if (d2.IsInside)
         {
             //3 inside edges
         }
         else
         {
             //1 outside edge (d2)
             //2 inside edges (d0,d1)
             //find a perpendicular line
             FindPerpendicular(d2, d0);
             FindPerpendicular(d2, d1);
         }
     }
     else if (d2.IsInside)
     {
         if (d1.IsInside)
         {
             //3 inside edges
         }
         else
         {
             //1 outside edge (d1)
             //2 inside edges (d0,d2)
             FindPerpendicular(d1, d0);
             FindPerpendicular(d1, d2);
         }
     }
 }
        void AnalyzeOutsideEdge(EdgeLine d, float centroidX, float centroidY)
        {
            //check if edge slope
            if (!d.IsOutside) return;
            //---------------------------
            switch (d.SlopeKind)
            {
                case LineSlopeKind.Horizontal:

                    //check if upper or lower
                    //compare mid point with the centroid  
                    d.IsUpper = d.GetMidPoint().Y > centroidY;
                    break;
                case LineSlopeKind.Vertical:
                    d.IsLeftSide = d.GetMidPoint().X < centroidX;
                    break;
            }

        }
예제 #18
0
        public GlyphTriangle(DelaunayTriangle tri)
        {
            this._tri = tri;
            //---------------------------------------------
            TriangulationPoint p0 = _tri.P0;
            TriangulationPoint p1 = _tri.P1;
            TriangulationPoint p2 = _tri.P2;

            //we do not store triangulation points (p0,p1,02)
            //an EdgeLine is created after we create GlyphTriangles.

            //triangulate point p0->p1->p2 is CCW ***
            e0 = NewEdgeLine(p0, p1, tri.EdgeIsConstrained(tri.FindEdgeIndex(p0, p1)));
            e1 = NewEdgeLine(p1, p2, tri.EdgeIsConstrained(tri.FindEdgeIndex(p1, p2)));
            e2 = NewEdgeLine(p2, p0, tri.EdgeIsConstrained(tri.FindEdgeIndex(p2, p0)));

            //if the order of original glyph point is CW
            //we may want to reverse the order of edge creation :
            //p2->p1->p0

            //link back
            tri.userData = this;
            //----------------

            //early analyze
            AnalyzeInsideEdge(e0, e1, e2);
            AnalyzeInsideEdge(e1, e0, e2);
            AnalyzeInsideEdge(e2, e0, e1);
            //at this point,
            //we should know the direction of this triangle
            //then we known that if this triangle is left/right/upper/lower of the 'stroke' line

            float cent_x, cent_y;

            this.CalculateCentroid(out cent_x, out cent_y);
            AnalyzeOutsideEdge(e0, cent_x, cent_y);
            AnalyzeOutsideEdge(e1, cent_x, cent_y);
            AnalyzeOutsideEdge(e2, cent_x, cent_y);
        }
예제 #19
0
        /// <summary>
        /// add information about edges to each triangle and create BoneJoint and Tip
        /// </summary>
        public GlyphBoneJoint AnalyzeEdgesAndCreateBoneJoint()
        {
#if DEBUG
            if (p == q)
            {
                throw new NotSupportedException();
            }
#endif

            //2 contact triangles share GlyphBoneJoint.
            //--------------------------------------
            //[C]
            //Find relation between edges of 2 triangle p and q
            //....
            //pick up a edge of p and compare to all edge of q
            //do until complete
            GlyphBoneJoint boneJoint = null;
            InsideEdgeLine p_edge, q_edge;
            if (FindCommonInsideEdges(p, q, out p_edge, out q_edge))
            {
                //create joint
                boneJoint = new GlyphBoneJoint(p_edge, q_edge);
                double slopeAngle = CalculateCentroidPairSlopeNoDirection(this);
                //
                EdgeLine foundTipEdge = null;
                if ((foundTipEdge = CreateTipEdgeIfNeed(slopeAngle, p, p_edge)) != null)
                {
                    //P
                    boneJoint.SetTipEdge_P(foundTipEdge);
                }
                if ((foundTipEdge = CreateTipEdgeIfNeed(slopeAngle, q, q_edge)) != null)
                {
                    //Q
                    boneJoint.SetTipEdge_Q(foundTipEdge);
                }
            }
            return(boneJoint);
        }
        internal GlyphBoneJoint(
            InsideEdgeLine p_contact_edge,
            InsideEdgeLine q_contact_edge)
        {
            //both p and q is INSIDE, contact edge
            this._p_contact_edge = p_contact_edge;
            this._q_contact_edge = q_contact_edge;
            //this is original x,y
            Vector2 midpos = p_contact_edge.GetMidPoint();

            this._fitX = midpos.X;
            this._fitY = midpos.Y;

#if DEBUG
            if (p_contact_edge.inside_joint != null ||
                q_contact_edge.inside_joint != null)
            {
                throw new System.NotSupportedException();
            }
#endif
            p_contact_edge.inside_joint = this;
            q_contact_edge.inside_joint = this;
        }
예제 #21
0
 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);
 }
예제 #22
0
        static void SelectMostProperTipEdge(
            double slopeAngle,
            EdgeLine outside0,
            EdgeLine outside1,
            out EdgeLine tipEdge,
            out EdgeLine notTipEdge)
        {
            //slop angle in rad

            double diff0 = Math.Abs(outside0.GetSlopeAngleNoDirection() - slopeAngle);
            double diff1 = Math.Abs(outside1.GetSlopeAngleNoDirection() - slopeAngle);

            if (diff0 > diff1)
            {
                tipEdge    = outside0;
                notTipEdge = outside1;
            }
            else
            {
                tipEdge    = outside1;
                notTipEdge = outside0;
            }
        }
예제 #23
0
 internal static bool ContainsTriangle(this EdgeLine edge, GlyphTriangle p)
 {
     return(p.e0 == edge ||
            p.e1 == edge ||
            p.e2 == edge);
 }
예제 #24
0
 internal static double GetSlopeAngleNoDirection(this EdgeLine line)
 {
     return(Math.Abs(Math.Atan2(Math.Abs(line.QY - line.PY), Math.Abs(line.QX - line.PX))));
 }
예제 #25
0
 public static Vector2 GetMidPoint(this EdgeLine line)
 {
     return(new Vector2((float)((line.PX + line.QX) / 2), (float)((line.PY + line.QY) / 2)));
 }
예제 #26
0
        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;
                }
            }
        }
예제 #27
0
        /// <summary>
        /// adjust vertical fitting value
        /// </summary>
        void ReCalculateFittingValues()
        {
            //(1)
            //clear all prev adjust value
            for (int i = _contours.Count - 1; i >= 0; --i)
            {
                List <GlyphPoint> pnts = _contours[i].flattenPoints;
                for (int m = pnts.Count - 1; m >= 0; --m)
                {
                    pnts[m].ResetFitAdjustValues();
                }
            }

            //adjust the value when we move to new pixel scale (pxscale)
            //if we known adjust values for that pxscale before( and cache it)
            //we can use that without recalculation

            //--------------------
            //(2)
            //select Horizontal BoneGroups for Vertical fitting:
            //for veritical fitting, we apply fitting value to each group.
            //each group may not need the same value.
            //--------------------
            List <BoneGroup> selectedHBoneGroups = _groupingHelper.SelectedHorizontalBoneGroups;

            for (int i = selectedHBoneGroups.Count - 1; i >= 0; --i)
            {
                BoneGroup boneGroup = selectedHBoneGroups[i];
                if (boneGroup._lengKind == BoneGroupSumLengthKind.Short)
                {
                    continue;
                }
                EdgeLine[] h_edges = boneGroup.edges;
                if (h_edges == null)
                {
                    continue;
                }
                //
                int edgeCount = h_edges.Length;
                //we need to calculate the avg of the glyph point
                //and add a total summary to this
                FitDiffCollector y_fitDiffCollector = new FitDiffCollector();
                float            groupLen           = boneGroup.approxLength;
                //
                for (int e = edgeCount - 1; e >= 0; --e)
                {
                    EdgeLine ee = h_edges[e];
                    //p
                    y_fitDiffCollector.Collect(MyMath.CalculateDiffToFit(ee.P.Y * _pxScale), groupLen);
                    //q
                    y_fitDiffCollector.Collect(MyMath.CalculateDiffToFit(ee.Q.Y * _pxScale), groupLen);
                }

                float avg_ydiff = y_fitDiffCollector.CalculateProperDiff();

                for (int e = edgeCount - 1; e >= 0; --e)
                {
                    //TODO: review here again
                    EdgeLine ee = h_edges[e];
                    ee.P.FitAdjustY = avg_ydiff; //assign px scale specific fit value
                    ee.Q.FitAdjustY = avg_ydiff; //assign px scale specific fit value
                }
            }
            //---------------------------------------------------------
            //(3)
            //vertical group for horizontal fit:
            //this different from the vertical fitting.
            //we calculate the value as a whole.
            //and apply it as a whole in later state
            List <BoneGroup> verticalGroups     = _groupingHelper.SelectedVerticalBoneGroups;
            FitDiffCollector x_fitDiffCollector = new FitDiffCollector();

            int j = verticalGroups.Count;

            for (int i = 0; i < j; ++i)
            {
                //1. the verticalGroup list is sorted, left to right
                //2. analyze in order left-> right

                BoneGroup boneGroup = verticalGroups[i];
                if (boneGroup._lengKind != BoneGroupSumLengthKind.Long)
                {
                    //in this case we focus on long-length bone group only
                    continue;
                }
                EdgeLine[] v_edges = boneGroup.edges;
                if (v_edges == null)
                {
                    continue;
                }

                int edgeCount = v_edges.Length;
                //we need to calculate the avg of the glyph point
                //and add a total summary to this
                float groupLen = boneGroup.approxLength;
                for (int e = 0; e < edgeCount; ++e)
                {
                    EdgeLine ee = v_edges[e];
                    //TODO: review this
                    //if (ee.IsLeftSide)
                    //{
                    //focus on leftside edge
                    //p
                    x_fitDiffCollector.Collect(MyMath.CalculateDiffToFit(ee.P.X * _pxScale), groupLen);
                    //q
                    x_fitDiffCollector.Collect(MyMath.CalculateDiffToFit(ee.Q.X * _pxScale), groupLen);
                    //}
                }
                //TODO: review here ***
                break; //only left most first long group ?
            }
            //(4)
            _avg_x_fitOffset = x_fitDiffCollector.CalculateProperDiff();
        }
예제 #28
0
 protected abstract void OnTriangle(int triAngleId, EdgeLine e0, EdgeLine e1, EdgeLine e2, double centroidX, double centroidY);
예제 #29
0
 static bool ContainsEdge(GlyphTriangle tri, EdgeLine edge)
 {
     return(tri.e0 == edge || tri.e1 == edge || tri.e2 == edge);
 }
예제 #30
0
 protected abstract void OnGlyphEdgeN(EdgeLine edge);