示例#1
0
        /// <summary>
        /// Create and add new control point to the given curve at a given Vec2F gpt</summary>
        /// <param name="curve">Curve to modify</param>
        /// <param name="gpt">Location on the x-axis at which to add a control point. Whether
        /// or not the y-coordinate is used depends on 'insert' parameter.</param>
        /// <param name="insert">If true, the y-value is inserted on the existing curve, using
        /// curve.Evaluate(gpt.X). If false, the y-value comes from gpt.Y.</param>
        /// <param name="computeTangent">Whether ComputeTangent() should be called</param>
        public static void AddControlPoint(ICurve curve, Vec2F gpt, bool insert, bool computeTangent)
        {
            if (curve == null)
            {
                throw new ArgumentNullException("curve");
            }

            // add/insert new control point to the given curve. Using the following rules.
            // if adding then add the point at gpt and set is tangent type to spline.
            // if inserting then add the point at (gpt.x,curve.eval(gpt.x)) and compute its tangent at the point.
            // recompute tangents for the curve.
            // find insersion index.
            int index = GetValidInsertionIndex(curve, gpt.X);

            if (index >= 0)
            {
                IControlPoint p = curve.CreateControlPoint();
                p.EditorData.SelectedRegion = PointSelectionRegions.None;
                if (insert)
                {
                    p.X = gpt.X;
                    ICurveEvaluator cv = CurveUtils.CreateCurveEvaluator(curve);

                    float prevY = cv.Evaluate(gpt.X - s_epsilone);
                    float nextY = cv.Evaluate(gpt.X + s_epsilone);
                    p.Y              = cv.Evaluate(gpt.X);
                    p.TangentInType  = CurveTangentTypes.Fixed;
                    p.TangentOutType = CurveTangentTypes.Fixed;
                    Vec2F tanIn = new Vec2F(s_epsilone, p.Y - prevY);
                    tanIn.Normalize();
                    Vec2F tanOut = new Vec2F(s_epsilone, nextY - p.Y);
                    tanOut.Normalize();
                    p.TangentIn  = tanIn;
                    p.TangentOut = tanOut;
                }
                else
                {
                    p.X              = gpt.X;
                    p.Y              = gpt.Y;
                    p.TangentInType  = CurveTangentTypes.Spline;
                    p.TangentOutType = CurveTangentTypes.Spline;
                }
                curve.InsertControlPoint(index, p);
                if (computeTangent)
                {
                    ComputeTangent(curve);
                }
            }
        }
示例#2
0
        /// <summary>
        /// Hit test curve</summary>
        /// <param name="curve">Curve</param>
        /// <param name="pickRect">Rectangle</param>
        /// <returns>True iff hit</returns>
        public bool HitTest(ICurve curve, RectangleF pickRect)
        {
            if (curve == null)
            {
                return(false);
            }

            ReadOnlyCollection <IControlPoint> points = curve.ControlPoints;

            if (!curve.Visible || points.Count == 0)
            {
                return(false);
            }
            float           step   = m_tessellation / m_canvas.Zoom.X;
            ICurveEvaluator cv     = CurveUtils.CreateCurveEvaluator(curve);
            float           start  = m_canvas.ClientToGraph(pickRect.X);
            float           end    = m_canvas.ClientToGraph(pickRect.Right);
            float           rangeX = end - start;
            PointF          scrPt  = new PointF();
            float           fpx    = points[0].X;
            float           lpx    = points[points.Count - 1].X;

            if ((start < fpx && end < fpx) || (start > lpx && end > lpx))
            {
                return(false);
            }
            for (float x = 0; x < rangeX; x += step)
            {
                float xv = start + x;
                float y  = cv.Evaluate(xv);
                scrPt = m_canvas.GraphToClient(xv, y);
                if (pickRect.Contains(scrPt))
                {
                    return(true);
                }
            }
            return(false);
        }
示例#3
0
        /// <summary>
        /// Draws given curve</summary>
        /// <param name="curve">Curve</param>
        /// <param name="g">Graphics object</param>
        public void DrawCurve(ICurve curve, Graphics g)
        {
            // draw pre-infinity
            // draw actual
            // draw post-inifiny.

            ReadOnlyCollection <IControlPoint> points = curve.ControlPoints;

            if (points.Count == 0)
            {
                return;
            }
            m_infinityPen.Color = curve.CurveColor;
            m_curvePen.Color    = curve.CurveColor;
            if (points.Count == 1)
            {
                Vec2F p = m_canvas.GraphToClient(0, points[0].Y);
                g.DrawLine(m_infinityPen, 0, p.Y, m_canvas.ClientSize.Width, p.Y);
                return;
            }

            float           w         = m_canvas.ClientSize.Width;
            float           h         = m_canvas.ClientSize.Height;
            float           x0        = m_canvas.ClientToGraph(0);
            float           x1        = m_canvas.ClientToGraph(w);
            IControlPoint   fpt       = points[0];
            IControlPoint   lpt       = points[points.Count - 1];
            float           step      = m_tessellation / m_canvas.Zoom.X;
            List <PointF>   pointList = new List <PointF>(m_canvas.Width / m_tessellation);
            ICurveEvaluator cv        = CurveUtils.CreateCurveEvaluator(curve);
            PointF          scrPt     = new PointF();
            float           bound     = 500; // guard again gdi+ overflow.
            float           minY      = -bound;
            float           maxY      = h + bound;

            // draw pre infinity
            if (fpt.X > x0)
            {
                float start  = x0;
                float end    = Math.Min(fpt.X, x1);
                float rangeX = end - start;
                for (float x = 0; x < rangeX; x += step)
                {
                    float xv = start + x;
                    float y  = cv.Evaluate(xv);
                    scrPt   = m_canvas.GraphToClient(xv, y);
                    scrPt.Y = MathUtil.Clamp(scrPt.Y, minY, maxY);
                    pointList.Add(scrPt);
                }
                scrPt   = m_canvas.GraphToClient(end, cv.Evaluate(end));
                scrPt.Y = MathUtil.Clamp(scrPt.Y, minY, maxY);
                pointList.Add(scrPt);
                if (pointList.Count > 1)
                {
                    g.DrawLines(m_infinityPen, pointList.ToArray());
                }
            }

            // draw actual
            if ((fpt.X > x0 || lpt.X > x0) && (fpt.X < x1 || lpt.X < x1))
            {
                int leftIndex;
                int rightIndex;
                ComputeIndices(curve, out leftIndex, out rightIndex);
                if (curve.CurveInterpolation == InterpolationTypes.Linear)
                {
                    for (int i = leftIndex; i < rightIndex; i++)
                    {
                        IControlPoint p1  = points[i];
                        IControlPoint p2  = points[i + 1];
                        PointF        cp1 = m_canvas.GraphToClient(p1.X, p1.Y);
                        PointF        cp2 = m_canvas.GraphToClient(p2.X, p2.Y);
                        g.DrawLine(m_curvePen, cp1.X, cp1.Y, cp2.X, cp2.Y);
                    }
                }
                else
                {
                    for (int i = leftIndex; i < rightIndex; i++)
                    {
                        IControlPoint p1 = points[i];
                        IControlPoint p2 = points[i + 1];
                        if (p1.TangentOutType == CurveTangentTypes.Stepped)
                        {
                            PointF cp1 = m_canvas.GraphToClient(p1.X, p1.Y);
                            PointF cp2 = m_canvas.GraphToClient(p2.X, p2.Y);
                            g.DrawLine(m_curvePen, cp1.X, cp1.Y, cp2.X, cp1.Y);
                            g.DrawLine(m_curvePen, cp2.X, cp1.Y, cp2.X, cp2.Y);
                        }
                        else if (p1.TangentOutType != CurveTangentTypes.SteppedNext)
                        {
                            float start = Math.Max(p1.X, x0);
                            float end   = Math.Min(p2.X, x1);
                            pointList.Clear();
                            float rangeX = end - start;
                            for (float x = 0; x < rangeX; x += step)
                            {
                                float xv = start + x;
                                float y  = cv.Evaluate(xv);
                                scrPt   = m_canvas.GraphToClient(xv, y);
                                scrPt.Y = MathUtil.Clamp(scrPt.Y, minY, maxY);
                                pointList.Add(scrPt);
                            }
                            scrPt   = m_canvas.GraphToClient(end, cv.Evaluate(end));
                            scrPt.Y = MathUtil.Clamp(scrPt.Y, minY, maxY);
                            pointList.Add(scrPt);
                            if (pointList.Count > 1)
                            {
                                g.DrawLines(m_curvePen, pointList.ToArray());
                            }
                        }
                    }// for (int i = leftIndex; i < rightIndex; i++)
                }
            }
            //draw post-infinity.
            if (lpt.X < x1)
            {
                pointList.Clear();
                float start  = Math.Max(x0, lpt.X);
                float end    = x1;
                float rangeX = end - start;
                for (float x = 0; x < rangeX; x += step)
                {
                    float xv = start + x;
                    float y  = cv.Evaluate(xv);
                    scrPt   = m_canvas.GraphToClient(xv, y);
                    scrPt.Y = MathUtil.Clamp(scrPt.Y, minY, maxY);
                    pointList.Add(scrPt);
                }
                scrPt   = m_canvas.GraphToClient(end, cv.Evaluate(end));
                scrPt.Y = MathUtil.Clamp(scrPt.Y, minY, maxY);
                pointList.Add(scrPt);
                if (pointList.Count > 1)
                {
                    g.DrawLines(m_infinityPen, pointList.ToArray());
                }
            }
        }