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