예제 #1
0
        public override void MouseDown(Canvas canvas, PointO location)
        {
            switch (Mode)
            {
            case ToolMode.Create:
                Curve = new DrawableCurve(location, location);
                canvas.Drawables.AddLast(Curve);
                Mode = ToolMode.Resize;
                break;

            case ToolMode.AddCurve:
                if (Curve.Intersect(location))
                {
                    Curve.AddCurve(location);
                    CurvePoint = location;
                    Mode       = ToolMode.MoveCurve;
                }
                else
                {
                    Curve.State = LockState.Instance;
                    Mode        = ToolMode.Create;
                }
                break;
            }
        }
예제 #2
0
 public override void Move(PointO offset)
 {
     foreach (var point in points)
     {
         point.Offset(offset);
     }
 }
예제 #3
0
        private double PythagorasDistance(PointO a, PointO b)
        {
            var dx = a.X - b.X;
            var dy = a.Y - b.Y;

            return(Math.Sqrt(dx * dx + dy * dy));
        }
예제 #4
0
 public override void Move(PointO offset)
 {
     foreach (var drawable in drawables)
     {
         drawable.Move(offset);
     }
 }
예제 #5
0
        private bool InBetween(PointO start, PointO mid, PointO end)
        {
            var alpha = FindAngle(mid, start, end);
            var beta  = FindAngle(mid, end, start);

            return(alpha <= 90 && beta <= 90);
        }
예제 #6
0
        public override void MouseDown(Canvas canvas, PointO location)
        {
            var drawable = GetDrawableAtLocation(canvas, location);

            switch (Mode)
            {
            case ToolMode.Select:
                if (drawable == null)
                {
                    canvas.LockDrawables();
                }
                else if (drawable.State == EditState.Instance)
                {
                    moveDrawables     = GetDrawableWithState(canvas, EditState.Instance);
                    moveStartLocation = location;
                    Mode = ToolMode.Move;
                }
                else
                {
                    canvas.LockDrawables();
                    drawable.State = EditState.Instance;
                }
                break;

            case ToolMode.MultiSelect:
                if (drawable == null)
                {
                    break;
                }
                ToggleDrawableState(drawable);
                break;
            }
        }
예제 #7
0
        public override bool Intersect(PointO point)
        {
            var minDistance = double.MaxValue;

            // distance from curve point
            for (var i = 0; i < points.Count; i++)
            {
                var distance = PythagorasDistance(point, points[i]);
                minDistance = Math.Min(minDistance, distance);
                if (minDistance < IntersectDistanceLimit)
                {
                    return(true);
                }
            }

            // distance from curve line
            for (var i = 1; i < points.Count; i++)
            {
                var a = points[i - 1];
                var b = points[i];
                if (InBetween(a, point, b))
                {
                    var distance = PerpendicularDistance(point, a, b);
                    minDistance = Math.Min(minDistance, distance);
                    if (minDistance < IntersectDistanceLimit)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
예제 #8
0
 public override void DrawGuide(Graphics graphics)
 {
     graphics.DrawLines(LineGuidePen, PointO.ToPrimitiveArray(points.ToArray()));
     foreach (var point in points)
     {
         graphics.DrawEllipse(CurvePointGuidePen, point.X - 2, point.Y - 2, 4, 4);
     }
 }
예제 #9
0
 public override void MouseUp(Canvas canvas, PointO location)
 {
     switch (Mode)
     {
     case ToolMode.Move:
         Mode = ToolMode.Select;
         break;
     }
 }
예제 #10
0
        private double PerpendicularDistance(PointO point, PointO lineA, PointO lineB)
        {
            // reference: https://math.stackexchange.com/questions/637922/how-can-i-find-coefficients-a-b-c-given-two-points
            var a = lineA.Y - lineB.Y;
            var b = -(lineA.X - lineB.X);
            var c = lineA.X * lineB.Y - lineB.X * lineA.Y;

            return(PerpendicularDistance(point, a, b, c));
        }
예제 #11
0
 public override bool Intersect(PointO point)
 {
     foreach (var drawable in drawables)
     {
         if (drawable.Intersect(point))
         {
             return(true);
         }
     }
     return(false);
 }
예제 #12
0
 private static Drawable GetDrawableAtLocation(Canvas canvas, PointO location)
 {
     foreach (var drawable in canvas.Drawables)
     {
         if (drawable.Intersect(location))
         {
             return(drawable);
         }
     }
     return(null);
 }
예제 #13
0
        public override void MouseUp(Canvas canvas, PointO location)
        {
            switch (Mode)
            {
            case ToolMode.Resize:
                Mode = ToolMode.AddCurve;
                break;

            case ToolMode.MoveCurve:
                Mode = ToolMode.AddCurve;
                break;
            }
        }
예제 #14
0
        private double FindAngle(PointO a, PointO b, PointO c)
        {
            // reference: https://stackoverflow.com/questions/19729831/angle-between-3-points-in-3d-space
            var v1     = new double[] { a.X - b.X, a.Y - b.Y };
            var v2     = new double[] { c.X - b.X, c.Y - b.Y };
            var v1Mag  = Math.Sqrt(v1[0] * v1[0] + v1[1] * v1[1]);
            var v2Mag  = Math.Sqrt(v2[0] * v2[0] + v2[1] * v2[1]);
            var v1Norm = new[] { v1[0] / v1Mag, v1[1] / v1Mag };
            var v2Norm = new[] { v2[0] / v2Mag, v2[1] / v2Mag };
            var res    = v1Norm[0] * v2Norm[0] + v1Norm[1] * v2Norm[1];

            return(Math.Acos(res) * 180.0 / 3.141592653589793);
        }
예제 #15
0
 public override void MouseMove(Canvas canvas, PointO location)
 {
     switch (Mode)
     {
     case ToolMode.Move:
         foreach (var drawable in moveDrawables)
         {
             var offset = PointO.FromOffset(moveStartLocation, location);
             drawable.Move(offset);
         }
         moveStartLocation = location;
         break;
     }
 }
예제 #16
0
        public override void MouseMove(Canvas canvas, PointO location)
        {
            switch (Mode)
            {
            case ToolMode.Resize:
                Curve.SetEndPoint(location);
                break;

            case ToolMode.MoveCurve:
                var offset = PointO.FromOffset(CurvePoint, location);
                CurvePoint.Offset(offset);
                break;
            }
        }
예제 #17
0
        private int FindBestPointPosition(PointO point)
        {
            var bestPointPosition = -1;
            var minDistance       = double.MaxValue;

            for (var i = 0; i < points.Count; i++)
            {
                var distance = PythagorasDistance(point, points[i]);
                if (distance < IntersectDistanceLimit && distance < minDistance)
                {
                    bestPointPosition = i;
                    minDistance       = distance;
                }
            }

            return(bestPointPosition);
        }
예제 #18
0
        public void AddCurve(PointO point)
        {
            // try use old curve
            var position = FindBestPointPosition(point);

            if (position != -1)
            {
                points[position] = point;
            }
            else
            {
                // try add curve between 2 point
                position = FindBestPosition(point);
                if (position != -1)
                {
                    points.Insert(position, point);
                }
            }
        }
예제 #19
0
        private int FindBestPosition(PointO point)
        {
            var bestPosition = -1;
            var minDistance  = double.MaxValue;

            for (var i = 1; i < points.Count; i++)
            {
                var a = points[i - 1];
                var b = points[i];
                if (!InBetween(a, point, b))
                {
                    continue;
                }
                var distance = PerpendicularDistance(point, a, b);
                if (!(distance < minDistance))
                {
                    continue;
                }
                bestPosition = i;
                minDistance  = distance;
            }

            return(bestPosition);
        }
예제 #20
0
 public virtual void MouseMove(Canvas canvas, PointO location)
 {
 }
예제 #21
0
 public virtual void MouseDown(Canvas canvas, PointO location)
 {
 }
예제 #22
0
 public DrawableCurve(PointO from, PointO to)
 {
     points.Add(from);
     points.Add(to);
 }
예제 #23
0
 private double PerpendicularDistance(PointO p, float a, float b, float c)
 {
     // reference: https://www.geeksforgeeks.org/perpendicular-distance-between-a-point-and-a-line-in-2-d/
     return(Math.Abs(a * p.X + b * p.Y + c) / Math.Sqrt(a * a + b * b));
 }
예제 #24
0
 public void SetStartPoint(PointO newStartPoint)
 {
     points[0] = newStartPoint;
 }
예제 #25
0
 public void SetEndPoint(PointO newEndPoint)
 {
     points[points.Count - 1] = newEndPoint;
 }
예제 #26
0
 public abstract void Move(PointO offset);
예제 #27
0
 public abstract bool Intersect(PointO point);
예제 #28
0
 public override void DrawItem(Graphics graphics)
 {
     graphics.DrawCurve(DrawPen, PointO.ToPrimitiveArray(points.ToArray()));
 }