Esempio n. 1
0
 protected internal override void DoGrabMove(GrabMovement move)
 {
     if (move.GrabType == GrabTypes.SingleVertex || move.GrabType == GrabTypes.Radius)             // not sure how I want to display them graphically yet, but the functionality will be the same
     {
         int    index    = move.ShapeIndex;
         int    previous = (index + 3) % 4;
         int    next     = (index + 1) % 4;
         int    opposite = (index + 2) % 4;
         PointF target   = Geometry.ClosestPointOnLine(Vertices[opposite], Vertices[index], move.Current.Exact);
         if (target.ApproxEqual(Vertices[opposite]))
         {
             return;
         }
         Vertices[index] = target;
         SizeF  vector = Vertices[opposite].VectorTo(Vertices[index]).MultiplyBy(0.5f);
         PointF centre = Vertices[opposite] + vector;
         vector             = new SizeF(-vector.Height, vector.Width);
         Vertices[previous] = centre + vector;
         Vertices[next]     = centre - vector;
         DiscardPath();
     }
     else
     {
         base.DoGrabMove(move);
     }
 }
Esempio n. 2
0
        protected internal override void DoGrabMove(GrabMovement move)
        {
            switch (move.GrabType)
            {
            case GrabTypes.SingleVertex:
                PointF ptNew = Vertices[1];
                move.Transform.TransformPoint(ref ptNew);
                if (ptNew.ApproxEqual(Vertices[0]))
                {
                    return;
                }
                if (HasCaret)
                {
                    CaretRealculateCoordinates(false);
                }
                Vertices[1] = ptNew;
                ClearTextCache();
                m_Bounds = CalculateBounds();
                break;

            default:
                base.DoGrabMove(move);
                break;
            }
        }
Esempio n. 3
0
        // let the base class take care of positioning the first line
        // however after choosing the end of that line becomes point 2 and point 1 is then moved (and point 3 is automatic)

        public override VerbResult Choose(EditableView.ClickPosition position)
        {
            PointF pt = position.Snapped;

            if (pt.ApproxEqual(LastDefined))
            {
                return(VerbResult.Rejected);
            }
            DiscardPath();

            switch (m_DefinedVertices)
            {
            case 1:
                SetLength(4);
                Vertices[2]       = pt;
                Vertices[1]       = Geometry.MidPoint(Vertices[0], Vertices[2]);
                m_DefinedVertices = 2;
                Float(position);
                return(VerbResult.Continuing);

            case 2:
                Float(position);
                if (Geometry.PointApproxOnLine(Vertices[0], Vertices[2], Vertices[1]))
                {
                    return(VerbResult.Rejected);
                }
                return(VerbResult.Completed);

            default: throw new InvalidOperationException();
            }
        }
Esempio n. 4
0
        /// <summary>like AngleSnap, but can use two origins, trying to find an intersection 15 degrees from each
        /// first origin has priority.  If bolSecondOnlyIfClose then second only used if quite close to snapping angle - ignored if angle needs a lot of adjusting</summary>
        internal static PointF AngleSnapFromTwoPoints(PointF pt, PointF origin, PointF secondOrigin, bool secondOnlyIfClose)
        {
            Debug.Assert(!origin.IsEmpty);             // usually means dont want snap
            if (pt.ApproxEqual(origin))
            {
                return(origin);                // usually happens as shape is being drawn - floated point starts on top of previous
            }
            float angle = VectorAngle(origin, pt);

            angle = (float)(Math.Round(angle / AngleStep()) * AngleStep());
            float angle2        = VectorAngle(secondOrigin, pt);
            float angle2Rounded = (float)(Math.Round(angle2 / AngleStep()) * AngleStep());

            // check if we need to ignore second - happens if both angles are the same (because we are v distant from 2 origins near each other
            // in which case there is no target 15deg from both), or if bolSecondOnlyIfClose
            if (Math.Abs(angle - angle2Rounded) < 0.05 || secondOnlyIfClose && Math.Abs(angle2 - angle2Rounded) > AngleStep() / 6)
            {
                // just return snapping to first origin
                return(origin + ScalarToVector(DistanceBetween(pt, origin), angle));
            }
            // try to solve for both - generate two lines of arbitrary length in right directions and let intersection logic return the intersection
            PointF intersection = Intersection.Line_LineIntersection(origin, origin + ScalarToVector(100, angle), false, secondOrigin, secondOrigin + ScalarToVector(100, angle2Rounded), false, true, true, out _, out _);

            // can return Empty if failed.  Ignore last Byref - only used if parallel which these aren't
            if (!intersection.IsEmpty)
            {
                return(intersection);
            }
            Debug.WriteLine("AngleSnapFromTwoPoint2 failed to resolve both angles");
            // just use first origin
            return(origin + ScalarToVector(DistanceBetween(pt, origin), angle));
        }
Esempio n. 5
0
        public override VerbResult Float(EditableView.ClickPosition position)
        {
            // let the base class take care of positioning the first line
            if (m_DefinedVertices < 2)
            {
                return(base.Float(position));
            }
            // need to calculate the coordinates of the fourth point.  We can add the 1>2 vector onto point 0
            Debug.Assert(Vertices.Count == 4);
            PointF newPoint = Geometry.PerpendicularPoint(Vertices[0], Vertices[1], position.Snapped);

            if (newPoint.Equals(Vertices[2]))
            {
                return(VerbResult.Unchanged);
            }
            if (newPoint.ApproxEqual(Vertices[1]))
            {
                return(VerbResult.Rejected);
            }
            Vertices[2] = newPoint;
            SizeF vector = Vertices[1].VectorTo(Vertices[2]);

            Vertices[3]  = PointF.Add(Vertices[0], vector);
            m_Bounds     = CalculateBounds();
            m_Acceptable = !VerticesFormLine(0);
            DiscardPath();
            return(VerbResult.Continuing);
        }
Esempio n. 6
0
        public override VerbResult Choose(EditableView.ClickPosition position)
        {
            PointF point = position.Snapped;

            if (point.ApproxEqual(LastDefined))
            {
                return(VerbResult.Rejected);
            }
            Vertices[Vertices.Count - 1] = point;
            FixVertex();
            return(VerbResult.Continuing);
        }
Esempio n. 7
0
        /// <summary>as AngleSnap, but doesn't make angle a multiple of 15;  instead difference between current vector and vector ptOrigin->ptRelative
        /// must be a multiple of 15</summary>
        internal static PointF AngleSnapPointRelative(PointF pt, PointF origin, PointF relative)
        {
            Debug.Assert(!origin.IsEmpty);             // usually means dont want snap
            if (pt.ApproxEqual(origin))
            {
                return(origin);                // usually happens as shape is being drawn - floated point starts on top of previous
            }
            float angle         = VectorAngle(origin, pt);
            float relativeAngle = VectorAngle(origin, relative);

            angle = (float)(Math.Round((angle - relativeAngle) / AngleStep()) * AngleStep() + relativeAngle);
            return(origin + ScalarToVector(DistanceBetween(pt, origin), angle));
        }
Esempio n. 8
0
        internal static PointF AngleSnapPoint(PointF pt, PointF origin, float stepAngle = -1)
        {
            if (stepAngle <= 0)
            {
                stepAngle = AngleStep();
            }
            Debug.Assert(!origin.IsEmpty);             // usually means dont want snap
            if (pt.ApproxEqual(origin))
            {
                return(origin);                // usually happens as shape is being drawn - floated point starts on top of previous
            }
            float angle = VectorAngle(origin, pt);

            angle = (float)(Math.Round(angle / stepAngle) * stepAngle);
            return(origin + ScalarToVector(DistanceBetween(pt, origin), angle));
        }
Esempio n. 9
0
 /// <summary>checks whether ptTest is within line A-B *ASSUMING* that we have already tested it lies on the line,
 /// *OR* we can assume it must.  (Eg intersection on given Segment).  Used especially for Ant/Segment where rounding</summary>
 internal static bool PointWithinLineExtent(PointF lineA, PointF lineB, PointF test)
 {
     // errors can actually put the point slightly off the official line, so we can't strictly check that test is within Rectangle(ptA, ptB)
     // just check in X or Y direction - wherever line is most distinct
     Debug.Assert(!lineA.ApproxEqual(lineB), "PointWithinLineExtent doesn\'t work correctly if points equal");
     // not sure about the assert - why not???  And I was getting some errors on scissors, which might be due to this pausing the code in an invalid state
     if (Math.Abs(lineA.X - lineB.X) > Math.Abs(lineA.Y - lineB.Y))
     {
         // X more useful
         return((test.X > lineA.X - NEGLIGIBLE || test.X > lineB.X - NEGLIGIBLE) && (test.X < lineA.X + NEGLIGIBLE || test.X < lineB.X + NEGLIGIBLE));
     }
     else
     {
         return((test.Y > lineA.Y - NEGLIGIBLE || test.Y > lineB.Y - NEGLIGIBLE) && (test.Y < lineA.Y + NEGLIGIBLE || test.Y < lineB.Y + NEGLIGIBLE));
     }
 }
Esempio n. 10
0
        public override VerbResult Float(EditableView.ClickPosition position)
        {
            PointF pt = position.Snapped;

            if (!m_BaseLineFixed)
            {
                if (pt.ApproxEqual(Vertices[0]))
                {
                    return(VerbResult.Rejected);
                }
                Vertices[1] = pt;
                m_Bounds    = CalculateBounds();
                // otherwise we are still typing text, nothing actually moves
                ClearTextCache();
            }
            return(VerbResult.Continuing);
        }
Esempio n. 11
0
 protected internal override void DoGrabMove(GrabMovement move)
 {
     if (move.GrabType == GrabTypes.Radius)
     {
         PointF centre = Centre;                 // because Centre function may not be all that fast
         if (centre.ApproxEqual(move.Current.Snapped))
         {
             return;
         }
         // update the radius, changing all points
         float radius = Geometry.DistanceBetween(centre, move.Current.Snapped);
         for (int vertex = 0; vertex <= Vertices.Count - 1; vertex++)
         {
             Vertices[vertex] = centre + centre.VectorTo(Vertices[vertex]).ChangeLength(radius);
         }
         DiscardPath();
         m_Bounds = RectangleF.Empty;
     }
     else
     {
         base.DoGrabMove(move);
     }
 }
Esempio n. 12
0
        public override VerbResult Choose(EditableView.ClickPosition position)
        {
            PointF pt = position.Snapped;

            if (pt.ApproxEqual(LastDefined))
            {
                return(VerbResult.Rejected);
            }
            DiscardPath();
            if (!UseBaseline())
            {
                Debug.Assert(Vertices.Count == m_DefinedVertices + 1, "Sequential.Choose is only applicable when there is a single floating vertex  if not UseBaseline - this function should have been overridden");
                FixVertex();
                return(VerbResult.Continuing);
            }

            // once we have two points forming a baseline, generate a complete set of points and float to set their initial positions
            if (m_DefinedVertices == 1)
            {
                // baseline now formed
                Vertices[1] = pt;
                SetLength(FixedVerticesLength());
                m_DefinedVertices = 2;
                Float(position);                 // will set some sort of default position for all of the remaining vertices
                return(VerbResult.Continuing);
            }

            // presumably the shape is complete - however reject if trying to place pt2 on pt1
            if (!m_Acceptable)
            {
                return(VerbResult.Rejected);
            }
            Float(position);
            m_DefinedVertices = FixedVerticesLength();
            return(VerbResult.Completed);
        }
Esempio n. 13
0
        protected internal override void DoGrabMove(GrabMovement move)
        {
            // we must implement the functionality at the base class, because we cannot use the version of this in Curve
            // however if we disallow single vertex movement there is almost no base functionality to be fitted
            m_Targets = null;
            // not really needed; but at the moment I have been leaving the targets in place for diagnostics
            switch (move.GrabType)
            {
            case GrabTypes.Move:
                this.ApplyTransformation(move.Transform);                         // will transform the control points
                m_Bounds = RectangleF.Empty;
                break;

            case GrabTypes.SingleVertex:
                PointF newPoint = Vertices[move.ShapeIndex];
                move.Transform.TransformPoint(ref newPoint);
                // we need to check that this point does not collide with the previous or next ones before actually storing it
                if (move.ShapeIndex > 0 && newPoint.ApproxEqual(Vertices[move.ShapeIndex - 1]))
                {
                    return;
                }
                if (move.ShapeIndex < Vertices.Count - 1 && newPoint.ApproxEqual(Vertices[move.ShapeIndex + 1]))
                {
                    return;
                }
                Vertices[move.ShapeIndex] = newPoint;
                if (move.GrabType == GrabTypes.SingleVertex && m_Closed && move.ShapeIndex == 0)
                {
                    // if moving the initial point, we must also move the closing point
                    Vertices[Vertices.Count - 1] = Vertices[0];
                }
                // and we move the previous and next control points by a similar amount
                if (move.ShapeIndex > 0 || m_Closed)
                {
                    int previous = move.ShapeIndex * 2 - 1;
                    if (move.ShapeIndex == 0)
                    {
                        previous = m_ControlPoints.Count - 1;
                    }
                    PointF temp = m_ControlPoints[previous];
                    move.Transform.TransformPoint(ref temp);
                    m_ControlPoints[previous] = temp;
#if DEBUG
                    if (m_ControlPoints[previous].ApproxEqual(Vertices[move.ShapeIndex]))
                    {
                        // splatter won't like this.  Shouldn't have been created in first place, but Andrew's doc had this
                        m_ControlPoints[previous] = Geometry.Interpolate(Vertices[move.ShapeIndex], Vertices[move.ShapeIndex - 1 % Vertices.Count], 0.25F);
                    }
#endif
                }
                if (move.ShapeIndex < m_DefinedVertices - 1 || m_Closed)
                {
                    int    control = move.ShapeIndex * 2 % (Vertices.Count * 2 - 2);
                    PointF temp    = m_ControlPoints[control];
                    move.Transform.TransformPoint(ref temp);
                    m_ControlPoints[control] = temp;
#if DEBUG
                    if (m_ControlPoints[control].ApproxEqual(Vertices[move.ShapeIndex]))
                    {
                        m_ControlPoints[control] = Geometry.Interpolate(Vertices[move.ShapeIndex], Vertices[(move.ShapeIndex + 1) % Vertices.Count], 0.25F);
                    }
#endif
                }
                m_Bounds = RectangleF.Empty;
                break;

            case GrabTypes.Rotate:
                base.DoGrabMove(move);
                break;

            default:
                Debug.Fail("Unexpected GrabSpot movement type in Pencil curve: " + move.GrabType);
                break;
            }
        }