Пример #1
0
        public override async Task Apply(CADDocument doc, params string[] args)
        {
            Editor ed = doc.Editor;

            ed.PickedSelection.Clear();

            var p1 = await ed.GetPoint("Start point: ");

            if (p1.Result != ResultMode.OK)
            {
                return;
            }
            var p2 = await ed.GetPoint("End point: ", p1.Value);

            if (p2.Result != ResultMode.OK)
            {
                return;
            }
            QuadraticBezier cons = new QuadraticBezier(p1.Value, Point2D.Average(p1.Value, p2.Value), p2.Value);

            doc.Jigged.Add(cons);
            var p3 = await ed.GetPoint("Control point: ", (p) => cons.P1 = p);

            doc.Jigged.Remove(cons);
            if (p3.Result != ResultMode.OK)
            {
                return;
            }

            Drawable newItem = new QuadraticBezier(p1.Value, p3.Value, p2.Value);

            doc.Model.Add(newItem);
        }
Пример #2
0
        private void AddParabola(Point2D site)
        {
            if (m_root == null)
            {
                m_root = new VParabolaNode(site);
            }
            else if (m_root.EnumerateLeaves().All((leaf) => leaf.Site.Y == site.Y))
            {
                // Degenerate case - all parabola sites on the same y-value.
                // If this happens, then our edge starts between us and our nearest point, and we need
                // to force affected edges (left and right) to recalculate their edge starts.
                var cutParabola = m_root.GetParabolaByX(site.X, site.Y);
                var newParabola = new VParabolaNode(site);
                var middle      = Point2D.Average(cutParabola.Site, newParabola.Site);

                // store old parabola parent so we can append junction node there
                var cutParent = cutParabola.Parent;

                // note: edge ctor appends child parabolas to itself.
                VEdgeNode edge;
                if (cutParabola.Site.X < newParabola.Site.X)
                {
                    edge = new VEdgeNode(middle, Vector2D.UnitXPlus, cutParabola, newParabola);
                }
                else
                {
                    edge = new VEdgeNode(middle, Vector2D.UnitXPlus, newParabola, cutParabola);
                }

                // append edge node to old cutparabola parent
                if (cutParent != null)
                {
                    if (cutParent.Left == null)
                    {
                        cutParent.Left = edge;
                    }
                    else
                    {
                        cutParent.Right = edge;
                    }
                }
            }
            else
            {
                var cutParabola = m_root.GetParabolaByX(site.X, site.Y);

                // store old parabola parent so we can append junction node there
                var cutParent = cutParabola.Parent;

                // :: determine the parabolas left and right of the cut parabola. This is important
                // :: for the "Swallowing" of parabolas by circle events.
                var cutParabolaLeft  = (VParabolaNode)cutParabola.GetLeftLeaf();
                var cutParabolaRight = (VParabolaNode)cutParabola.GetRightLeaf();

                // :: determine the left, middle, and right parabolas formed by this cut.
                var left   = cutParabola;
                var middle = new VParabolaNode(site);
                var right  = cutParabola.Clone();

                // :: determine where the new "middle" parabola meets the "cut" parabola
                var intersection = cutParabola.CalculatePointAtX(site.X, site.Y);

                // create the left and right edges...
                var vCutMiddle     = middle.Site - cutParabola.Site;
                var rightDirection = vCutMiddle.Perp(); // performs 90deg counterclockwise rotation in euclidean space
                var leftDirection  = rightDirection.Flip();
                var leftEdge       = new VEdgeNode(intersection, leftDirection, left, middle);
                var rightEdge      = new VEdgeNode(intersection, leftDirection, leftEdge, right);

                if (cutParent.Left == null)
                {
                    cutParent.Left = rightEdge;
                }
                else
                {
                    cutParent.Right = rightEdge;
                }

                // :: Manage Circle Events
                // Unregister the cut parabola node's event, which is now invalidated.
                if (cutParabola.CircleEvent != null)
                {
                    m_queue.Remove(cutParabola.CircleEvent);
                    cutParabola.CircleEvent = null;
                }

                // Register the left, right, and middle circle events
                if (cutParabolaLeft != null)
                {
                    RegisterCircleEvent(cutParabolaLeft, left, middle);
                }
                if (cutParabolaRight != null)
                {
                    RegisterCircleEvent(middle, right, cutParabolaRight);
                }
                if (cutParabolaLeft != null && cutParabolaRight != null)
                {
                    RegisterCircleEvent(left, middle, right); // wtf? Shouldn't be necessary, right?
                }
            }
        }