示例#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;
            var   p1 = ed1.v1;
            var   p2 = ed1.v2;
            var   q1 = ed2.v1;
            var   q2 = ed2.v2;

            var pn = new Point();

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

            var pn1 = VectorTools.Plus(pn, p1);
            var pn2 = VectorTools.Plus(pn, p2);

            var i1 = new Point();
            var i2 = new Point();

            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);
            }

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

            var qm = ed2.middle;

            var i = VectorTools.Distance(i1, i2);
            var 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)
        {
            var avg = (ed1.length + ed2.length) / 2;
            var 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 (var ed in groupsToStraighten.Values)
     {
         for (var i = 0; i < subdivisionPoints; i++)
         {
             //STRONG CHANGE
             var p = ed.controlPoints[i];
             p = VectorTools.Plus(VectorTools.Multiply(p, 1 - s),
                                  VectorTools.Multiply(VectorTools.Plus(ed.v1,
                                                                        VectorTools.Multiply(VectorTools.Minus(ed.v2, 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(Point p1, Point p2, Point q1, Point q2, ref Point intersection, ref float rp)
        {
            var q = (p1.Y - q1.Y) * (q2.X - q1.X) - (p1.X - q1.X) * (q2.Y - q1.Y);
            var d = (p2.X - p1.X) * (q2.Y - q1.Y) - (p2.Y - p1.Y) * (q2.X - q1.X);

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

            var r = q / d;

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

            intersection = VectorTools.Plus(p1, VectorTools.Multiply(VectorTools.Minus(p2, 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 Point[1];
                ed.newControlPoints = new Point[1];
                ed.controlPoints[0] = ed.middle;

                return;
            }

            var sPoints        = ed.controlPoints;
            var sPointsDoubled = new Point[subdivisionPoints * 2 + 1];

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


            for (var 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(TEdge e)
        {
            EdgeGroupData ed;
            var           key = new KeyPair(e.Source.ID, e.Target.ID);

            edgeGroupData.TryGetValue(key, out ed);

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

                ed.controlPoints = e.RoutingPoints; //e.GetValue(ReservedMetadataKeys.PerEdgeIntermediateCurvePoints);

                if (subdivisionPoints == 0)
                {
                    subdivisionPoints = ed.controlPoints.Length;
                }
                ed.newControlPoints = new Point[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>
        /// 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)
        {
            var ed = (EdgeGroupData)o;

            for (var i = 0; i < subdivisionPoints; i++)
            {
                var   p = ed.controlPoints[i];
                Point 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);
                var f = VectorTools.Multiply(VectorTools.Plus(VectorTools.Minus(p1, p), VectorTools.Minus(p2, p)), ed.k);
                var r = new Point(0, 0);
                foreach (var epd in ed.compatibleGroups.Values)
                {
                    Point         q;
                    var           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;
                        }
                    }
                    var fs = VectorTools.Minus(q, p);
                    //PointF fs = new PointF(q.X - p.X, q.Y - p.Y);

                    var 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);
                    }
                }

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

                var move  = new Point(f.X + r.X, f.Y + r.Y);
                var 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] = VectorTools.Plus(move, p);

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

                if (ed.newControlPoints[i].Y < AreaRectangle.Top)
                {
                    ed.newControlPoints[i].Y = AreaRectangle.Top;
                }
                else
                if (ed.newControlPoints[i].Y > AreaRectangle.Bottom)
                {
                    ed.newControlPoints[i].Y = AreaRectangle.Bottom;
                }
            }
            if (useThreading)
            {
                sem.Release();
            }
        }
示例#9
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)
        {
            var a = VectorTools.Angle(ed1.v1, ed1.v2, ed2.v1, ed2.v2);

            return((float)Math.Abs(Math.Cos(a)));
        }
示例#10
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(TGraph graph, float s)
 {
     foreach (var e in graph.Edges)
     {
         if (e.IsSelfLoop)
         {
             continue;
         }
         var controlPoints    = e.RoutingPoints;//(PointF[])e.GetValue(ReservedMetadataKeys.PerEdgeIntermediateCurvePoints);
         var newControlPoints = new Point[controlPoints.Length];
         for (var i = 0; i < controlPoints.Length; i++)
         {
             //STRONG CHANGE
             var p = controlPoints[i];
             p = VectorTools.Plus(VectorTools.Multiply(p, 1 - s),
                                  VectorTools.Multiply(VectorTools.Plus(VertexPositions[e.Source],
                                                                        VectorTools.Multiply(VectorTools.Minus(VertexPositions[e.Target], VertexPositions[e.Source]),
                                                                                             1.0f * (i + 1) / (controlPoints.Length + 1))), s));
             newControlPoints[i].X = p.X;
             newControlPoints[i].Y = p.Y;
         }
         //e.SetValue(ReservedMetadataKeys.PerEdgeIntermediateCurvePoints, newControlPoints);
         e.RoutingPoints = newControlPoints;
     }
 }