Used for vector calculations
示例#1
0
        /// <summary>
        /// Calculates visibility coefficient of the two edges.
        /// </summary>
        ///
        /// <param name="ed1">
        /// First edge to be used in calculation
        /// </param>
        ///
        /// <param name="ed2">
        /// Second edge to be used in calculation
        /// </param>
        ///
        /// <returns>
        /// Compatibility coefficient ranging from 0 to 1
        /// </returns>
        private float VisibilityCoefficient(EdgeGroupData ed1, EdgeGroupData ed2)
        {
            float  c;
            PointF p1 = ed1.v1;
            PointF p2 = ed1.v2;
            PointF q1 = ed2.v1;
            PointF q2 = ed2.v2;

            PointF pn = new PointF();

            pn.X = p1.Y - p2.Y;
            pn.Y = p2.X - p1.X;

            PointF pn1 = pn + new SizeF(p1);
            PointF pn2 = pn + new SizeF(p2);

            PointF i1 = new PointF();
            PointF i2 = new PointF();

            float r1 = 0, r2 = 0;

            if (!Intersects(q1, q2, p1, pn1, ref i1, ref r1))
            {
                return(0);
            }
            Intersects(q1, q2, p2, pn2, ref i2, ref r2);

            if ((r1 < 0 && r2 < 0) || (r1 > 1 && r2 > 1))
            {
                return(0);
            }

            PointF im = VectorTools.MidPoint(i1, i2);

            PointF qm = ed2.middle;

            float i = VectorTools.Distance(i1, i2);
            float m = VectorTools.Distance(qm, im);

            if (i == 0)
            {
                return(0);
            }

            c = 1f - 2f * m / i;

            if (c < 0)
            {
                return(0);
            }
            else
            {
                return(c);
            }
        }
示例#2
0
        /// <summary>
        /// Calculates position compatibility of the two edges
        /// </summary>
        ///
        /// <param name="ed1">
        /// First edge to be used in calculation
        /// </param>
        ///
        /// <param name="ed2">
        /// Second edge to be used in calculation
        /// </param>
        ///
        /// <returns>
        /// Position compatibility coefficient ranging from 0 to 1
        /// </returns>
        private float PositionCompatibility(EdgeGroupData ed1, EdgeGroupData ed2)
        {
            float avg = (ed1.length + ed2.length) / 2;
            float dis = VectorTools.Distance(ed1.middle, ed2.middle);

            if ((avg + dis) == 0)
            {
                return(0);
            }
            return(avg / (avg + dis));
        }
示例#3
0
 /// <summary>
 /// Calculates directedness of the two edges.
 /// </summary>
 ///
 /// <param name="ed1">
 /// First edge to be used in calculation
 /// </param>
 ///
 /// <param name="ed2">
 /// Second edge to be used in calculation
 /// </param>
 ///
 /// <returns>
 /// True if edges have roughly the same direction, false otherwise
 /// </returns>
 private bool CalculateDirectedness(EdgeGroupData ed1, EdgeGroupData ed2)
 {
     if ((VectorTools.Distance(ed1.v1, ed2.v1) + VectorTools.Distance(ed1.v2, ed2.v2)) <
         (VectorTools.Distance(ed1.v1, ed2.v2) + VectorTools.Distance(ed1.v2, ed2.v1)))
     {
         return(true);
     }
     else
     {
         return(false);
     }
 }
示例#4
0
 /// <summary>
 /// Straightens the edges using internal data sturctures
 /// </summary>
 ///
 /// <param name="groupsToStraighten">
 /// Groups of edges that should be straightened
 /// </param>
 ///
 /// <param name="s">
 /// Specifies the amount of straightening, from 0 to 1
 /// </param>
 private void StraightenEdgesInternally(Dictionary <KeyPair, EdgeGroupData> groupsToStraighten, float s)
 {
     foreach (EdgeGroupData ed in groupsToStraighten.Values)
     {
         for (int i = 0; i < subdivisionPoints; i++)
         {
             PointF p = ed.controlPoints[i];
             p = VectorTools.Multiply(p, 1 - s) +
                 new SizeF(VectorTools.Multiply(ed.v1 +
                                                new SizeF(VectorTools.Multiply(ed.v2 -
                                                                               new SizeF(ed.v1), 1.0f * (i + 1) / (subdivisionPoints + 1))), s));
             ed.controlPoints[i].X = p.X;
             ed.controlPoints[i].Y = p.Y;
         }
     }
 }
示例#5
0
        /// <summary>
        /// Finds an intersection point of the two lines
        /// </summary>
        ///
        /// <param name="p1">
        /// First point of the first line
        /// </param>
        ///
        /// <param name="p2">
        /// Second point of the first line
        /// </param>
        ///
        /// <param name="q1">
        /// First point of the second line
        /// </param>
        ///
        /// <param name="q2">
        /// Second point of the second line
        /// </param>
        ///
        /// <param name="intersection">
        /// Point of intersection
        /// </param>
        ///
        /// <param name="rp">
        /// Parameter used for determining on which segment the intersection point lies
        /// </param>
        ///
        /// <returns>
        /// True if lines are not parallel, false otherwise
        /// </returns>
        private bool Intersects(PointF p1, PointF p2, PointF q1, PointF q2, ref PointF intersection, ref float rp)
        {
            float q = (p1.Y - q1.Y) * (q2.X - q1.X) - (p1.X - q1.X) * (q2.Y - q1.Y);
            float d = (p2.X - p1.X) * (q2.Y - q1.Y) - (p2.Y - p1.Y) * (q2.X - q1.X);

            if (d == 0) // parallel lines
            {
                return(false);
            }

            float r = q / d;

            q = (p1.Y - q1.Y) * (p2.X - p1.X) - (p1.X - q1.X) * (p2.Y - p1.Y);
            float s = q / d;

            intersection = p1 + new SizeF(VectorTools.Multiply(p2 - new SizeF(p1), r));

            return(true);
        }
示例#6
0
        /// <summary>
        /// Doubles subdivision points for an edge by adding one new subdivision point between each two
        /// </summary>
        ///
        /// <param name="ed">
        /// Edge data that contains subdivision points to be doubled
        /// </param>
        private void DoubleSubdivisionPoints(EdgeGroupData ed)
        {
            if (subdivisionPoints == 0) //make one subdivision point
            {
                ed.k = springConstant * 2 / ed.length;
                if (ed.k > 0.5f)
                {
                    ed.k = 0.5f;
                }
                ed.controlPoints    = new PointF[1];
                ed.newControlPoints = new PointF[1];
                ed.controlPoints[0] = ed.middle;

                return;
            }

            PointF[] sPoints        = ed.controlPoints;
            PointF[] sPointsDoubled = new PointF[subdivisionPoints * 2 + 1];
            ed.newControlPoints = new PointF[subdivisionPoints * 2 + 1];
            for (int i = 0; i < subdivisionPoints; i++)
            {
                sPointsDoubled[i * 2 + 1] = sPoints[i];
            }


            for (int i = 0; i < subdivisionPoints - 1; i++)
            {
                sPointsDoubled[i * 2 + 2] = VectorTools.MidPoint(sPoints[i], sPoints[i + 1]);
            }


            sPointsDoubled[0] = VectorTools.MidPoint(ed.v1, sPoints[0]);
            sPointsDoubled[subdivisionPoints * 2] = VectorTools.MidPoint(sPoints[subdivisionPoints - 1], ed.v2);
            //ed.K = springConstant * (subdivisionPoints * 2 + 2) / ed.Length;
            ed.k *= 2f;
            if (ed.k > 0.5f)
            {
                ed.k = 0.5f;
            }
            ed.controlPoints = sPointsDoubled;
        }
示例#7
0
        /// <summary>
        /// Collects data from the specified edge.
        /// Used for edges that already have control points metadata.
        /// </summary>
        ///
        /// <param name="e">
        /// Edge to collect data from
        /// </param>
        private void AddExistingData(IEdge e)
        {
            EdgeGroupData ed;
            KeyPair       key = new KeyPair(e.Vertices[0].ID, e.Vertices[1].ID);

            edgeGroupData.TryGetValue(key, out ed);

            if (ed == null)
            {
                PointF p1 = e.Vertices[0].Location;
                PointF p2 = e.Vertices[1].Location;
                ed    = new EdgeGroupData();
                ed.v1 = p1;
                ed.v2 = p2;
                ed.id = key;
                PointF mid = VectorTools.MidPoint(p1, p2);
                ed.middle = mid;
                ed.length = VectorTools.Distance(p1, p2);

                ed.controlPoints = (PointF[])e.GetValue(ReservedMetadataKeys.PerEdgeIntermediateCurvePoints);

                if (subdivisionPoints == 0)
                {
                    subdivisionPoints = ed.controlPoints.Length;
                }
                ed.newControlPoints = new PointF[subdivisionPoints];
                ed.k = springConstant * (subdivisionPoints + 1) / ed.length;
                if (ed.k > 0.5f)
                {
                    ed.k = 0.5f;
                }
                //ed.edges = new HashSet<int>();
                ed.edgeCount        = 0;
                ed.compatibleGroups = new Dictionary <KeyPair, GroupPairData>();
                edgeGroupData.Add(key, ed);
            }
            //ed.edges.Add(e.ID);
            ed.edgeCount++;
        }
示例#8
0
 /// <summary>
 /// Moves the control points of all the edges of the graph closer to their original position on the straight edge
 /// </summary>
 ///
 /// <param name="graph">
 /// Graph whose edges should be straightened
 /// </param>
 ///
 /// <param name="s">
 /// Specifies the amount of straightening, from 0 to 1
 /// </param>
 public void StraightenEdges(IGraph graph, float s)
 {
     foreach (IEdge e in graph.Edges)
     {
         if (e.IsSelfLoop)
         {
             continue;
         }
         PointF[] controlPoints    = (PointF[])e.GetValue(ReservedMetadataKeys.PerEdgeIntermediateCurvePoints);
         PointF[] newControlPoints = new PointF[controlPoints.Length];
         for (int i = 0; i < controlPoints.Length; i++)
         {
             PointF p = controlPoints[i];
             p = VectorTools.Multiply(p, 1 - s) +
                 new SizeF(VectorTools.Multiply(e.Vertices[0].Location +
                                                new SizeF(VectorTools.Multiply(e.Vertices[1].Location -
                                                                               new SizeF(e.Vertices[0].Location), 1.0f * (i + 1) / (controlPoints.Length + 1))), s));
             newControlPoints[i].X = p.X;
             newControlPoints[i].Y = p.Y;
         }
         e.SetValue(ReservedMetadataKeys.PerEdgeIntermediateCurvePoints, newControlPoints);
     }
 }
示例#9
0
        /// <summary>
        /// Calculates new positions for the control points of an edge by applying elastic and electrostatic forces to them
        /// </summary>
        ///
        /// <param name="o">
        /// Edge data that contains subdivision points to be moved
        /// </param>
        private void CalculateNewControlPoints(Object o)
        {
            EdgeGroupData ed = (EdgeGroupData)o;

            for (int i = 0; i < subdivisionPoints; i++)
            {
                PointF p = ed.controlPoints[i];
                PointF p1, p2;
                if (i == 0)
                {
                    p1 = ed.v1;
                }
                else
                {
                    p1 = ed.controlPoints[i - 1];
                }
                if (i == (subdivisionPoints - 1))
                {
                    p2 = ed.v2;
                }
                else
                {
                    p2 = ed.controlPoints[i + 1];
                }
                SizeF  sp = new SizeF(p);
                PointF f  = VectorTools.Multiply((p1 - sp) + new SizeF((p2 - sp)), ed.k);
                PointF r  = new PointF(0, 0);
                foreach (GroupPairData epd in ed.compatibleGroups.Values)
                {
                    PointF        q;
                    float         j = 1f;
                    EdgeGroupData ed2;
                    if ((epd.ed1.id.k1 == ed.id.k1) && (epd.ed1.id.k2 == ed.id.k2))
                    {
                        ed2 = epd.ed2;
                    }
                    else
                    {
                        ed2 = epd.ed1;
                    }

                    if (epd.d)
                    {
                        q = ed2.controlPoints[i];
                    }
                    else
                    {
                        q = ed2.controlPoints[subdivisionPoints - i - 1];
                        if (directed && repulseOpposite)
                        {
                            j = repulsionCoefficient;
                        }
                    }
                    PointF fs = q - sp;
                    //PointF fs = new PointF(q.X - p.X, q.Y - p.Y);

                    float l = VectorTools.Length(fs);
                    if (l > 0)//???
                    {
                        fs = VectorTools.Multiply(fs, epd.c / (l));

                        //fs = VectorTools.Multiply(fs, VectorTools.Length(fs) * ed2.edges.Count);
                        fs = VectorTools.Multiply(fs, VectorTools.Length(fs) * ed2.edgeCount);

                        r.X += (j * fs.X);
                        r.Y += (j * fs.Y);
                    }
                }

                float rl = VectorTools.Length(r);
                if (rl > 0)
                {
                    r = VectorTools.Multiply(r, (float)(1.0 / Math.Sqrt(rl)));
                }

                PointF move  = new PointF(f.X + r.X, f.Y + r.Y);
                float  moveL = VectorTools.Length(move);

                //float len = ed.Length / (subdivisionPoints + 1);
                //if (moveL > (len)) move = VectorTools.Multiply(move, len*cooldown / moveL);
                //if (moveL != 0) move = VectorTools.Multiply(move, cooldown / moveL);
                move = VectorTools.Multiply(move, cooldown * 0.5f);
                ed.newControlPoints[i] = move + sp;

                if (ed.newControlPoints[i].X < rectangle.Left)
                {
                    ed.newControlPoints[i].X = rectangle.Left;
                }
                else
                if (ed.newControlPoints[i].X > rectangle.Right)
                {
                    ed.newControlPoints[i].X = rectangle.Right;
                }

                if (ed.newControlPoints[i].Y < rectangle.Top)
                {
                    ed.newControlPoints[i].Y = rectangle.Top;
                }
                else
                if (ed.newControlPoints[i].Y > rectangle.Bottom)
                {
                    ed.newControlPoints[i].Y = rectangle.Bottom;
                }
            }
            if (useThreading)
            {
                sem.Release();
            }
        }
示例#10
0
        /// <summary>
        /// Calculates angle compatibility of the two edges
        /// </summary>
        ///
        /// <param name="ed1">
        /// First edge to be used in calculation
        /// </param>
        ///
        /// <param name="ed2">
        /// Second edge to be used in calculation
        /// </param>
        ///
        /// <returns>
        /// Angle compatibility coefficient ranging from 0 to 1
        /// </returns>
        private float AngleCompatibility(EdgeGroupData ed1, EdgeGroupData ed2)
        {
            float a = VectorTools.Angle(ed1.v1, ed1.v2, ed2.v1, ed2.v2);

            return((float)Math.Abs(Math.Cos(a)));
        }