예제 #1
0
        public void DrawCurvedLine(Graphics g, PointF[] points, int radius)
        {
            using (GraphicsPath path = new GraphicsPath())
            {
                PointF lastQ     = new PointF(0, 0);
                PointF nextStart = new PointF(points[0].X, points[0].Y);
                for (int i = 0; i < points.Length - 2; i++)
                {
                    PointF Q = GetQ(points[i], points[i + 1], points[i + 2], radius);
                    PointF A = points[i + 1].Take(points[i]).Normalised();
                    PointF B = points[i + 2].Take(points[i + 1]).Normalised();

                    float  toLeave = Math.Abs(Q.Dot(A));
                    PointF toDraw  = A.ScaleBy(points[i].DistanceTo(points[i + 1]) - toLeave);

                    path.AddLine(nextStart.X, nextStart.Y, toDraw.X + points[i].X, toDraw.Y + points[i].Y);

                    nextStart = B.ScaleBy(Math.Abs(Q.Dot(B))).Plus(points[i + 1]);

                    //path.AddBezier(toDraw.X + points[i].X, toDraw.Y + points[i].Y, points[i + 1].X, points[i + 1].Y, points[i + 1].X, points[i + 1].Y, nextStart.X, nextStart.Y);

                    var arcLocation = Q.Plus(points[i + 1]).Plus(-radius, -radius);

                    float a1 = (float)(Math.Atan2(A.Y, A.X) * 180 / Math.PI);
                    float a2 = (float)(Math.Atan2(B.Y, B.X) * 180 / Math.PI);

                    float dif21 = a2 - a1; if (dif21 < 0)
                    {
                        dif21 += 360;
                    }
                    float dif12 = a1 - a2; if (dif12 < 0)
                    {
                        dif12 += 360;
                    }

                    path.AddArc(arcLocation.X, arcLocation.Y, radius * 2.0f, radius * 2.0f, a1 + dif12, Math.Abs(-dif12) < Math.Abs(dif21) ? -dif12 : dif21);
                    //path.AddArc(arcLocation.X, arcLocation.Y, radius, radius, a1, dif12);

                    lastQ = Q;
                }
                path.AddLine(path.GetLastPoint(), new PointF(points[points.Length - 1].X, points[points.Length - 1].Y));
                //g.DrawLines(Outline, points);
                //for (int i = 1; i < points.Length - 1; i++)
                //DrawArc(g, points[i - 1], points[i], points[i + 1], radius);

                g.DrawPath(Outline, path);
            }
        }
예제 #2
0
        internal void MouseMove(MouseEventArgs e)
        {
            MousePosition       = new PointF(e.X, e.Y);
            StickyMousePosition = Snap(MousePosition);

            Hover      = simulation.Vertices.Where(v => MousePosition.Sub(v.Position).Mag() < v.Radius);
            HoverEdges = simulation.Edges.Where(edge =>
            {
                // hledání úseček v dané (či menší) vzdálenosti od bodu
                // https://en.wikipedia.org/wiki/Vector_projection
                // vektor od V do U
                PointF delta = edge.U.Position.Sub(edge.V.Position);
                float length = delta.Mag();
                PointF unit  = delta.MultiplyScalar(1f / length);
                // vektor od V do pozice myši
                PointF deltaMouse = MousePosition.Sub(edge.V.Position);
                // skalární projekce - musí být > 0 && < délka úsečky UV
                // jinak je projekce bodu myši mimo tuto úsečku a tedy
                // myš není u úsečky ale někde před ní nebo za ní
                float scalarProjection = unit.Dot(deltaMouse);
                if (scalarProjection < edge.U.Radius || scalarProjection > length - edge.V.Radius)
                {
                    return(false);
                }

                // vektorová projekce
                PointF a1 = unit.MultiplyScalar(scalarProjection);
                // rozdíl, tedy kolmý vektor na UV ukazující od úsečky k bodu myši
                PointF a2 = deltaMouse.Sub(a1);
                // "kolmá" vzdálenost úsečky a myši
                float mouseDistance = a2.Mag();
                float maxDistance   = Math.Max(edge.U.Radius, edge.V.Radius);
                return(mouseDistance < maxDistance);
            });

            foreach (Vertex v in Dragging)
            {
                if (simulation.Pause)
                {
                    // přesouvání bodu probíhá při vypnuté simulaci
                    // přímým nastavením pozice bodu
                    v.Position = StickyMousePosition;
                    v.PrevPos  = StickyMousePosition;
                    IEnumerable <Edge> affectedEdges = simulation.GetEdges(v);
                    foreach (Edge edge in affectedEdges)
                    {
                        edge.ResetLength();
                    }
                }
                else
                {
                    // přesouvání bodu probíhá při běžící simulaci
                    // pomocí aplikací síly
                    v.SetTarget(MousePosition);
                }
            }
        }
예제 #3
0
        private static PointF GetQ(PointF p1, PointF p2, PointF p3, int radius)
        {
            PointF A     = p1.Take(p2).Normalised();
            PointF B     = p3.Take(p2).Normalised();
            PointF ApB   = A.Plus(B);
            float  apbls = ApB.LengthSquared();
            float  hs    = apbls * radius * radius / (float)(apbls - (1 - A.Dot(B)));
            float  l     = (float)Math.Sqrt(hs / apbls);
            PointF Q     = new PointF(ApB.X * l, ApB.Y * l);

            return(Q);
        }