示例#1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OsmSharp.Math.Primitives.RectangleF2D"/> class.
 /// </summary>
 /// <param name="x">The x coordinate.</param>
 /// <param name="y">The y coordinate.</param>
 /// <param name="width">Width.</param>
 /// <param name="height">Height.</param>
 /// <param name="directionY">Direction y.</param>
 public RectangleF2D(double x, double y, double width, double height, VectorF2D directionY)
 {
     _bottomLeft = new PointF2D (x, y);
     directionY = directionY.Normalize ();
     _vectorY = directionY * height;
     _vectorX = directionY.Rotate90 (true) * width;
 }
示例#2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OsmSharp.Math.Primitives.RectangleF2D"/> class.
 /// </summary>
 /// <param name="x">The x coordinate of the bottom-left corner.</param>
 /// <param name="y">The y coordinate of the bottom-left corner.</param>
 /// <param name="width">Width.</param>
 /// <param name="height">Height.</param>
 /// <remarks>This creates a rectangle in the direction of the x- and y-axis, performance is almost always better when using <see cref="OsmSharp.Math.Primitives.BoxF2D"/> in this case.</remarks>
 public RectangleF2D(double x, double y, double width, double height)
 {
     _bottomLeft = new PointF2D (x, y);
     _vectorX = new VectorF2D (width, 0);
     _vectorY = new VectorF2D (0, height);
 }
示例#3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OsmSharp.Math.Primitives.RectangleF2D"/> class.
 /// </summary>
 /// <param name="x">The x coordinate of the bottom-left corner.</param>
 /// <param name="y">The y coordinate of the bottom-left corner.</param>
 /// <param name="width">Width.</param>
 /// <param name="height">Height.</param>
 /// <param name="angleY">The angle relative to the y-axis.</param>
 public RectangleF2D(double x, double y, double width, double height, Degree angleY)
 {
     _bottomLeft = new PointF2D (x, y);
     VectorF2D directionY = VectorF2D.FromAngleY (angleY);
     _vectorY = directionY * height;
     _vectorX = directionY.Rotate90 (true) * width;
 }
示例#4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OsmSharp.Math.Primitives.RectangleF2D"/> class.
 /// </summary>
 /// <param name="bottomLeft">Bottom left.</param>
 /// <param name="width">Width.</param>
 /// <param name="height">Height.</param>
 /// <param name="directionY">Direction y.</param>
 public RectangleF2D(PointF2D bottomLeft, double width, double height, VectorF2D directionY)
 {
     _bottomLeft = bottomLeft;
     VectorF2D directionYNormal = directionY.Normalize ();
     _vectorY = directionYNormal * height;
     _vectorX = directionYNormal.Rotate90 (true) * width;
 }
示例#5
0
 /// <summary>
 /// Creates a new RectangleF2D from given bounds, center and direction.
 /// </summary>
 /// <param name="centerX"></param>
 /// <param name="centerY"></param>
 /// <param name="width">Width.</param>
 /// <param name="height">Height.</param>
 /// <param name="directionY">The direction of the y-axis.</param>
 /// <returns></returns>
 public static RectangleF2D FromBoundsAndCenter(double width, double height, double centerX, double centerY, VectorF2D directionY)
 {
     VectorF2D directionYNormal = directionY.Normalize();
     VectorF2D directionXNormal = directionYNormal.Rotate90(true);
     PointF2D center = new PointF2D(centerX, centerY);
     PointF2D bottomLeft = center - (directionYNormal * (height / 2)) - (directionXNormal * (width / 2));
     return new RectangleF2D(bottomLeft, width, height, directionY);
 }
示例#6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OsmSharp.Math.Primitives.RectangleF2D"/> class.
 /// </summary>
 /// <param name="x">The x coordinate of the bottom-left corner.</param>
 /// <param name="y">The y coordinate of the bottom-left corner.</param>
 /// <param name="width">Width.</param>
 /// <param name="height">Height.</param>
 /// <remarks>This creates a rectangle in the direction of the x- and y-axis, performance is almost always better when using <see cref="OsmSharp.Math.Primitives.BoxF2D"/> in this case.</remarks>
 public RectangleF2D(double x, double y, double width, double height)
 {
     _bottomLeft = new PointF2D(x, y);
     _vectorX    = new VectorF2D(width, 0);
     _vectorY    = new VectorF2D(0, height);
 }
        public void DrawLineTextSegment(Target2DWrapper <Graphics> target, double[] x, double[] y, string text, int color,
                                        double size, int?haloColor, int?haloRadius, double middlePosition, float[] characterWidths, double textLength,
                                        Font font, float characterHeight, Brush haloBrush, Brush brush)
        {
            // see if the text is 'upside down'.
            double   averageAngle = 0;
            double   first        = middlePosition - (textLength / 2.0);
            PointF2D current      = Polyline2D.PositionAtPosition(x, y, first);

            for (int idx = 0; idx < text.Length; idx++)
            {
                double   nextPosition = middlePosition - (textLength / 2.0) + ((textLength / (text.Length)) * (idx + 1));
                PointF2D next         = Polyline2D.PositionAtPosition(x, y, nextPosition);

                // Translate to the final position, the center of line-segment between 'current' and 'next'
                PointF2D position = current + ((next - current) / 2.0);

                // calculate the angle.
                VectorF2D vector       = next - current;
                VectorF2D horizontal   = new VectorF2D(1, 0);
                double    angleDegrees = ((Degree)horizontal.Angle(vector)).Value;
                averageAngle = averageAngle + angleDegrees;
                current      = next;
            }
            averageAngle = averageAngle / text.Length;

            // reverse if 'upside down'.
            double[] xText = x;
            double[] yText = y;
            if (averageAngle > 90 && averageAngle < 180 + 90)
            { // the average angle is > PI => means upside down.
                xText = x.Reverse <double>().ToArray <double>();
                yText = y.Reverse <double>().ToArray <double>();
            }

            // calculate a central position along the line.
            first   = middlePosition - (textLength / 2.0);
            current = Polyline2D.PositionAtPosition(xText, yText, first);
            double nextPosition2 = first;

            for (int idx = 0; idx < text.Length; idx++)
            {
                nextPosition2 = nextPosition2 + characterWidths[idx];
                //double nextPosition = middle - (textLength / 2.0) + ((textLength / (text.Length)) * (idx + 1));
                PointF2D next        = Polyline2D.PositionAtPosition(xText, yText, nextPosition2);
                char     currentChar = text[idx];
                using (GraphicsPath characterPath = new GraphicsPath())
                {
                    characterPath.AddString(currentChar.ToString(), font.FontFamily, (int)font.Style, font.Size, Point.Empty,
                                            StringFormat.GenericTypographic);

                    var pathBounds = characterPath.GetBounds();

                    // Transformation matrix to move the character to the correct location.
                    // Note that all actions on the Matrix class are prepended, so we apply them in reverse.
                    var transform = new Matrix();

                    // Translate to the final position, the center of line-segment between 'current' and 'next'
                    PointF2D position = current;
                    //PointF2D position = current + ((next - current) / 2.0);
                    double[] transformed = this.Tranform(position[0], position[1]);
                    transform.Translate((float)transformed[0], (float)transformed[1]);

                    // calculate the angle.
                    VectorF2D vector       = next - current;
                    VectorF2D horizontal   = new VectorF2D(1, 0);
                    double    angleDegrees = ((Degree)horizontal.Angle(vector)).Value;

                    // Rotate the character
                    transform.Rotate((float)angleDegrees);

                    // Translate the character so the centre of its base is over the origin
                    transform.Translate(0, -characterHeight / 2.5f);

                    //transform.Scale((float)this.FromPixels(_target, _view, 1),
                    //    (float)this.FromPixels(_target, _view, 1));
                    characterPath.Transform(transform);

                    if (haloColor.HasValue && haloRadius.HasValue && haloRadius.Value > 0)
                    {
                        GraphicsPath haloPath = characterPath.Clone() as GraphicsPath;
                        using (haloPath)
                        {
                            haloPath.Widen(new Pen(haloBrush, haloRadius.Value * 2));

                            // Draw the character
                            target.Target.FillPath(haloBrush, haloPath);
                        }
                    }

                    // Draw the character
                    target.Target.FillPath(brush, characterPath);
                }
                current = next;
            }
        }
示例#8
0
 /// <summary>
 /// Creates a new RectangleF2D from given bounds, center and angle.
 /// </summary>
 /// <param name="centerX"></param>
 /// <param name="centerY"></param>
 /// <param name="width">Width.</param>
 /// <param name="height">Height.</param>
 /// <param name="angleY">The angle.</param>
 /// <returns></returns>
 public static RectangleF2D FromBoundsAndCenter(double width, double height, double centerX, double centerY, Degree angleY)
 {
     return(RectangleF2D.FromBoundsAndCenter(width, height, centerX, centerY, VectorF2D.FromAngleY(angleY)));
 }
示例#9
0
        /// <summary>
        /// Creates a new RectangleF2D from given bounds, center and direction.
        /// </summary>
        /// <param name="centerX"></param>
        /// <param name="centerY"></param>
        /// <param name="width">Width.</param>
        /// <param name="height">Height.</param>
        /// <param name="directionY">The direction of the y-axis.</param>
        /// <returns></returns>
        public static RectangleF2D FromBoundsAndCenter(double width, double height, double centerX, double centerY, VectorF2D directionY)
        {
            VectorF2D directionYNormal = directionY.Normalize();
            VectorF2D directionXNormal = directionYNormal.Rotate90(true);
            PointF2D  center           = new PointF2D(centerX, centerY);
            PointF2D  bottomLeft       = center - (directionYNormal * (height / 2)) - (directionXNormal * (width / 2));

            return(new RectangleF2D(bottomLeft, width, height, directionY));
        }
示例#10
0
        private void DrawLineTextSegment(Target2DWrapper <CGContextWrapper> target, double[] xTransformed, double[] yTransformed, ushort[] glyphs, int color,
                                         int?haloColor, int?haloRadius, double middlePosition, float[] characterWidths,
                                         double textLength, float charachterHeight, CTFont font)
        {
            // see if text is 'upside down'
            double   averageAngle = 0;
            double   first        = middlePosition - (textLength / 2.0);
            PointF2D current      = Polyline2D.PositionAtPosition(xTransformed, yTransformed, first);

            for (int idx = 0; idx < glyphs.Length; idx++)
            {
                double   nextPosition = middlePosition - (textLength / 2.0) + ((textLength / (glyphs.Length)) * (idx + 1));
                PointF2D next         = Polyline2D.PositionAtPosition(xTransformed, yTransformed, nextPosition);

                // translate to the final position, the center of the line segment between 'current' and 'next'.
                //PointF2D position = current + ((next - current) / 2.0);

                // calculate the angle.
                VectorF2D vector       = next - current;
                VectorF2D horizontal   = new VectorF2D(1, 0);
                double    angleDegrees = ((Degree)horizontal.Angle(vector)).Value;
                averageAngle = averageAngle + angleDegrees;
                current      = next;
            }
            averageAngle = averageAngle / glyphs.Length;


            // revers if 'upside down'
            double[] xText = xTransformed;
            double[] yText = yTransformed;
            if (averageAngle > 90 && averageAngle < 180 + 90)
            {
                xText = xTransformed.Reverse().ToArray();
                yText = yTransformed.Reverse().ToArray();
            }
            first   = middlePosition - (textLength / 2.0);
            current = Polyline2D.PositionAtPosition(xText, yText, first);

            double nextPosition2 = first;

            for (int idx = 0; idx < glyphs.Length; idx++)
            {
                nextPosition2 = nextPosition2 + characterWidths[idx];
                PointF2D next = Polyline2D.PositionAtPosition(xText, yText, nextPosition2);
                //ushort currentChar = glyphs [idx];

                PointF2D position = current;

                target.Target.CGContext.SaveState();

                // translate to the final position, the center of the line segment between 'current' and 'next'.
                //                double[] transformed = this.Tranform(position[0], position[1]);
                //				target.Target.CGContext.TranslateCTM (
                //					(float)transformed [0],
                //					(float)transformed [1]);
                target.Target.CGContext.TranslateCTM((float)position[0], (float)position[1]);

                // calculate the angle.
                VectorF2D vector       = next - current;
                VectorF2D horizontal   = new VectorF2D(1, 0);
                double    angleDegrees = (horizontal.Angle(vector)).Value;

                // rotate the character.
                target.Target.CGContext.RotateCTM((float)angleDegrees);

                // rotate the text to point down no matter what the map tilt is.
                //target.Target.CGContext.RotateCTM ((float)_view.Angle.Value);

                // translate the character so the center of its base is over the origin.
                target.Target.CGContext.TranslateCTM(0, charachterHeight / 3.0f);

                // rotate 'upside down'
                target.Target.CGContext.ConcatCTM(new CGAffineTransform(1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f));

                target.Target.CGContext.BeginPath();

                CGPath path = font.GetPathForGlyph(glyphs[idx]);

                if (haloRadius.HasValue && haloColor.HasValue)
                {                 // also draw the halo.
                    using (CGPath haloPath = path.CopyByStrokingPath(
                               haloRadius.Value * 2, CGLineCap.Round, CGLineJoin.Round, 0))
                    {
                        SimpleColor haloSimpleColor = SimpleColor.FromArgb(haloColor.Value);
                        target.Target.CGContext.SetFillColor(haloSimpleColor.R / 256.0f, haloSimpleColor.G / 256.0f, haloSimpleColor.B / 256.0f,
                                                             haloSimpleColor.A / 256.0f);
                        target.Target.CGContext.BeginPath();
                        target.Target.CGContext.AddPath(haloPath);
                        target.Target.CGContext.DrawPath(CGPathDrawingMode.Fill);
                    }
                }

                // set the fill color as the regular text-color.
                SimpleColor simpleColor = SimpleColor.FromArgb(color);
                target.Target.CGContext.SetFillColor(simpleColor.R / 256.0f, simpleColor.G / 256.0f, simpleColor.B / 256.0f,
                                                     simpleColor.A / 256.0f);

                // draw the text paths.
                target.Target.CGContext.BeginPath();
                target.Target.CGContext.AddPath(path);
                target.Target.CGContext.DrawPath(CGPathDrawingMode.Fill);

                //				target.Target.CGContext.AddPath (path);
                //				if (haloRadius.HasValue && haloColor.HasValue) { // also draw the halo.
                //					target.Target.CGContext.DrawPath (CGPathDrawingMode.FillStroke);
                //				} else {
                //					target.Target.CGContext.DrawPath (CGPathDrawingMode.Fill);
                //				}
                //target.Target.CGContext.ClosePath ();
                target.Target.CGContext.RestoreState();

                current = next;
            }
        }
示例#11
0
        /// <summary>
        /// Draws the line text segment.
        /// </summary>
        /// <param name="target">Target.</param>
        /// <param name="xTransformed">X transformed.</param>
        /// <param name="yTransformed">Y transformed.</param>
        /// <param name="text">Text.</param>
        /// <param name="color">Color.</param>
        /// <param name="size">Size.</param>
        /// <param name="haloColor">Halo color.</param>
        /// <param name="haloRadius">Halo radius.</param>
        /// <param name="middlePosition">Middle position.</param>
        /// <param name="characterWidths">Character widths.</param>
        /// <param name="textLength">Text length.</param>
        /// <param name="characterHeight">Character height.</param>
        public void DrawLineTextSegment(Target2DWrapper <global::Android.Graphics.Canvas> target, double[] xTransformed, double[] yTransformed, string text, int color,
                                        double size, int?haloColor, int?haloRadius, double middlePosition, float[] characterWidths, double textLength,
                                        float characterHeight)
        {
            _paint.Color = new global::Android.Graphics.Color(color);
            _paint.SetStyle(global::Android.Graphics.Paint.Style.Fill);

            // see if the text is 'upside down'.
            double   averageAngle = 0;
            double   first        = middlePosition - (textLength / 2.0);
            PointF2D current      = Polyline2D.PositionAtPosition(xTransformed, yTransformed, first);
            bool     isVisible    = false;

            for (int idx = 0; idx < text.Length; idx++)
            {
                double   nextPosition = middlePosition - (textLength / 2.0) + ((textLength / (text.Length)) * (idx + 1));
                PointF2D next         = Polyline2D.PositionAtPosition(xTransformed, yTransformed, nextPosition);

                // calculate the angle.
                VectorF2D vector       = next - current;
                VectorF2D horizontal   = new VectorF2D(1, 0);
                double    angleDegrees = ((Degree)horizontal.Angle(vector)).Value;
                averageAngle = averageAngle + angleDegrees;
                current      = next;

                double[] untransformed = this.TransformReverse(next [0], next [1]);
                if (_view.Contains(untransformed [0], untransformed [1]))
                {
                    isVisible = true;
                }
            }
            averageAngle = averageAngle / text.Length;

            if (!isVisible)
            {
                return;
            }

            // reverse if 'upside down'.
            double[] xText = xTransformed;
            double[] yText = yTransformed;
//			if (averageAngle > 90 && averageAngle < 180 + 90)
//			{ // the average angle is > PI => means upside down.
//				for (int idx = 0; idx < (xTransformed.Length / 2) + 1; idx++) {
//					double other = xTransformed [xTransformed.Length - idx - 1];
//					xTransformed [xTransformed.Length - idx - 1] = xTransformed [0];
//					xTransformed [0] = other;
//					other = yTransformed [yTransformed.Length - idx - 1];
//					yTransformed [yTransformed.Length - idx - 1] = yTransformed [0];
//					yTransformed [0] = other;
//				}
//			}

            // calculate a central position along the line.
            first   = middlePosition - (textLength / 2.0);
            current = Polyline2D.PositionAtPosition(xText, yText, first);
            double nextPosition2 = first;

            for (int idx = 0; idx < text.Length; idx++)
            {
                nextPosition2 = nextPosition2 + characterWidths[idx];
                //double nextPosition = middle - (textLength / 2.0) + ((textLength / (text.Length)) * (idx + 1));
                PointF2D next        = Polyline2D.PositionAtPosition(xText, yText, nextPosition2);
                char     currentChar = text[idx];
                global::Android.Graphics.Path characterPath = new global::Android.Graphics.Path();;
                _paint.GetTextPath(text, idx, idx + 1, 0, 0, characterPath);
                using (characterPath) {
                    // Transformation matrix to move the character to the correct location.
                    // Note that all actions on the Matrix class are prepended, so we apply them in reverse.
                    using (var transform = new Matrix()) {
                        // Translate to the final position, the center of line-segment between 'current' and 'next'
                        PointF2D position = current;
                        //PointF2D position = current + ((next - current) / 2.0);
                        //double[] transformed = this.Tranform(position[0], position[1]);
                        transform.SetTranslate((float)position [0], (float)position [1]);

                        // calculate the angle.
                        VectorF2D vector       = next - current;
                        VectorF2D horizontal   = new VectorF2D(1, 0);
                        double    angleDegrees = ((Degree)horizontal.Angle(vector)).Value;

                        // Rotate the character
                        transform.PreRotate((float)angleDegrees);

                        // Translate the character so the centre of its base is over the origin
                        transform.PreTranslate(0, characterHeight / 2.5f);

                        //transform.Scale((float)this.FromPixels(_target, _view, 1),
                        //    (float)this.FromPixels(_target, _view, 1));
                        characterPath.Transform(transform);

                        if (haloColor.HasValue && haloRadius.HasValue && haloRadius.Value > 0)
                        {
                            _paint.SetStyle(global::Android.Graphics.Paint.Style.FillAndStroke);
                            _paint.StrokeWidth = haloRadius.Value;
                            _paint.Color       = new global::Android.Graphics.Color(haloColor.Value);
                            using (global::Android.Graphics.Path haloPath = new global::Android.Graphics.Path()) {
                                _paint.GetFillPath(characterPath, haloPath);
                                // Draw the character
                                target.Target.DrawPath(haloPath, _paint);
                            }
                        }

                        // Draw the character
                        _paint.SetStyle(global::Android.Graphics.Paint.Style.Fill);
                        _paint.StrokeWidth = 0;
                        _paint.Color       = new global::Android.Graphics.Color(color);
                        target.Target.DrawPath(characterPath, _paint);
                    }
                }
                current = next;
            }
        }
示例#12
0
        /// <summary>
        /// Calculates and returns the line intersection.
        /// </summary>
        /// <param name="line"></param>
        /// <param name="doSegment"></param>
        /// <returns></returns>
        public PrimitiveF2D Intersection(LineF2D line, bool doSegment)
        {
            if (line == this)
            { // if the lines equal, the full lines intersect.
                return(line);
            }
            else if (line.A == this.A &&
                     line.B == this.B &&
                     line.C == this.C)
            { // if the lines equal in direction and position; return the smallest segment.
                KeyValuePair <double, PointF2D> point1 = new KeyValuePair <double, PointF2D>(
                    0, this.Point1);

                KeyValuePair <double, PointF2D> point2 = new KeyValuePair <double, PointF2D>(
                    this.Point1.Distance(this.Point2), this.Point2);

                // sort.
                KeyValuePair <double, PointF2D> temp;
                if (point2.Key < point1.Key)
                { // point2 smaller than point1.
                    temp   = point2;
                    point2 = point1;
                    point1 = temp;
                }

                KeyValuePair <double, PointF2D> point = new KeyValuePair <double, PointF2D>(
                    this.Point1.Distance(line.Point1), line.Point1);

                if (point.Key < point2.Key) // sort.
                {                           // point smaller than point2.
                    temp   = point;
                    point  = point2;
                    point2 = temp;
                }
                if (point2.Key < point1.Key)
                { // point2 smaller than point1.
                    temp   = point2;
                    point2 = point1;
                    point1 = temp;
                }

                point = new KeyValuePair <double, PointF2D>(
                    this.Point1.Distance(line.Point2), line.Point2);

                if (point.Key < point2.Key) // sort.
                {                           // point smaller than point2.
                    temp   = point;
                    point  = point2;
                    point2 = temp;
                }
                if (point2.Key < point1.Key)
                { // point2 smaller than point1.
                    temp   = point2;
                    point2 = point1;
                    point1 = temp;
                }

                // this line is a segment.
                if (doSegment && (this.IsSegment1 || this.IsSegment2))
                { // test where the intersection lies.
                    double this_distance =
                        this.Point1.Distance(this.Point2);
                    if (this.IsSegment)
                    { // if in any directions one of the points are further away from the point.
                        double this_distance_1 = System.Math.Min(this.Point1.Distance(point1.Value),
                                                                 this.Point1.Distance(point2.Value));
                        if (this_distance_1 > this_distance)
                        { // the point is further away.
                            return(null);
                        }
                    }
                    else if (this.IsSegment1)
                    { // if in any directions one of the points are further away from the point.
                        double this_distance_1 = this.Point1.Distance(point1.Value);
                        if (this_distance_1 > this_distance)
                        { // the point is further away.
                            return(null);
                        }
                    }
                    else if (this.IsSegment2)
                    { // if in any directions one of the points are further away from the point.
                        double this_distance_2 = this.Point2.Distance(point1.Value);
                        if (this_distance_2 > this_distance)
                        { // the point is further away.
                            return(null);
                        }
                    }
                }
                // other line is a segment.
                if (doSegment && (line.IsSegment1 || line.IsSegment2))
                { // test where the intersection lies.
                    double this_distance =
                        line.Point1.Distance(line.Point2);
                    if (line.IsSegment)
                    {// if in any directions one of the points are further away from the point.
                        double this_distance_1 = System.Math.Min(line.Point1.Distance(point1.Value),
                                                                 line.Point1.Distance(point2.Value));
                        if (this_distance_1 > this_distance)
                        { // the point is further away.
                            return(null);
                        }
                    }
                    else if (line.IsSegment1)
                    { // if in any directions one of the points are further away from the point.
                        double this_distance_1 = line.Point1.Distance(point1.Value);
                        if (this_distance_1 > this_distance)
                        { // the point is further away.
                            return(null);
                        }
                    }
                    else if (line.IsSegment2)
                    { // if in any directions one of the points are further away from the point.
                        double this_distance_2 = line.Point2.Distance(point2.Value);
                        if (this_distance_2 > this_distance)
                        { // the point is further away.
                            return(null);
                        }
                    }
                }
                return(new LineF2D(
                           point1.Value,
                           point2.Value,
                           true));
            }
            else
            {                 // line.A = A1, line.B = B1, line.C = C1, this.A = A2, this.B = B2, this.C = C2
                double det = (line.A * this.B - this.A * line.B);
                if (det == 0) // TODO: implement an accuracy threshold epsilon.
                {             // lines are parallel; no intersections.
                    return(null);
                }
                else
                { // lines are not the same and not parallel so they will intersect.
                    double x = (this.B * line.C - line.B * this.C) / det;
                    double y = (line.A * this.C - this.A * line.C) / det;

                    // create the point.
                    PointF2D point = new PointF2D(new double[] { x, y });

                    // this line is a segment.
                    if (doSegment && (this.IsSegment1 || this.IsSegment2))
                    { // test where the intersection lies.
                        double this_distance =
                            this.Point1.Distance(this.Point2);
                        if (this.IsSegment)
                        {// if in any directions one of the points are further away from the point.
                            double this_distance_1 = this.Point1.Distance(point);
                            if (this_distance_1 > this_distance)
                            { // the point is further away.
                                return(null);
                            }
                            double this_distance_2 = this.Point2.Distance(point);
                            if (this_distance_2 > this_distance)
                            { // the point is further away.
                                return(null);
                            }
                        }
                        else if (this.IsSegment1 && this.Point2.Distance(point) > this_distance)
                        { // only check this direction and only if the points lies far enough away from point2.
                            VectorF2D pointDirection = point - this.Point2;
                            VectorF2D point2ToPoint1 = this.Direction.Inverse;
                            if (pointDirection.CompareNormalized(point2ToPoint1, 0.001))
                            { // point lies in the direction of the segmented point1 and far away from point2
                                return(null);
                            }
                        }
                        else if (this.IsSegment1 && this.Point1.Distance(point) > this_distance)
                        { // only check this direction and only if the points lies far enough away from point1.
                            VectorF2D pointDirection = point - this.Point1;
                            VectorF2D point1ToPoint2 = this.Direction;
                            if (pointDirection.CompareNormalized(point1ToPoint2, 0.001))
                            { // point lies in the direction of the segmented point1 and far away from point2
                                return(null);
                            }
                        }
                    }
                    // line this is a segment.
                    if (doSegment && (line.IsSegment1 || line.IsSegment2))
                    { // test where the intersection lies.
                        double line_distance =
                            line.Point1.Distance(line.Point2);
                        if (line.IsSegment)
                        {// if in any directions one of the points are further away from the point.
                            double line_distance_1 = line.Point1.Distance(point);
                            if (line_distance_1 > line_distance)
                            { // the point is further away.
                                return(null);
                            }
                            double line_distance_2 = line.Point2.Distance(point);
                            if (line_distance_2 > line_distance)
                            { // the point is further away.
                                return(null);
                            }
                        }
                        else if (line.IsSegment1 && line.Point2.Distance(point) > line_distance)
                        { // only check line direction and only if the points lies far enough away from point2.
                            VectorF2D pointDirection = point - line.Point2;
                            VectorF2D point2ToPoint1 = line.Direction.Inverse;
                            if (pointDirection.CompareNormalized(point2ToPoint1, 0.001))
                            { // point lies in the direction of the segmented point1 and far away from point2
                                return(null);
                            }
                        }
                        else if (line.IsSegment1 && line.Point1.Distance(point) > line_distance)
                        { // only check line direction and only if the points lies far enough away from point1.
                            VectorF2D pointDirection = point - line.Point1;
                            VectorF2D point1ToPoint2 = line.Direction;
                            if (pointDirection.CompareNormalized(point1ToPoint2, 0.001))
                            { // point lies in the direction of the segmented point1 and far away from point2
                                return(null);
                            }
                        }
                    }

                    // the intersection is valid.
                    return(point);
                }
            }
        }
示例#13
0
        /// <summary>
        /// Calculates a polygon out of a list of points. The resulting polygon the convex hull of all points.
        /// </summary>
        /// <param name="points"></param>
        /// <returns></returns>
        public static IList <PointF2D> Calculate(IList <PointF2D> points)
        {
            if (points.Count < 3)
            {
                throw new ArgumentOutOfRangeException(string.Format("Cannot calculate the convex hull of {0} points!",
                                                                    points.Count));
            }

            // find the 'left-most' and 'top-most' point.
            PointF2D start = points[0];

            foreach (PointF2D point in points)
            {
                if (start[0] > point[0])
                {
                    start = point;
                }
                else if (start[0] == point[0])
                {
                    if (start[1] < point[01])
                    {
                        start = point;
                    }
                }
            }

            // produce the first reference vector.
            double[]  before_start_coords = new double[] { start[0], start[1] - 10 };
            PointF2D  before_start        = new PointF2D(before_start_coords);
            VectorF2D reference           = start - before_start;

            // start the gift-wrapping!
            List <PointF2D> result  = new List <PointF2D>();
            PointF2D        current = start;

            result.Add(current);

            do
            {
                // find the point with the smallest angle.
                double   angle = double.MaxValue;
                PointF2D next  = null;
                foreach (PointF2D point in points)
                {
                    if (point != current)
                    {
                        VectorF2D next_vector = point - current;

                        double next_angle = reference.Angle(next_vector).Value;
                        if (next_angle < angle)
                        {
                            angle = next_angle;
                            next  = point;
                        }
                    }
                }

                // the found point is the next one.
                reference = next - current;
                current   = next;
                result.Add(current);
            }while(current != start);

            // return the result.
            return(result);
        }
示例#14
0
        public static RectangleF2D FromBoundsAndCenter(double width, double height, double centerX, double centerY, VectorF2D directionY)
        {
            VectorF2D vectorF2D1 = directionY.Normalize();
            VectorF2D vectorF2D2 = vectorF2D1.Rotate90(true);

            return(new RectangleF2D(new PointF2D(centerX, centerY) - vectorF2D1 * (height / 2.0) - vectorF2D2 * (width / 2.0), width, height, directionY));
        }
示例#15
0
        /// <summary>
        /// Creates a new line.
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="is_segment1"></param>
        /// <param name="is_segment2"></param>
        public LineF2D(PointF2D a, PointF2D b, bool is_segment1, bool is_segment2)
        {
            _a = a;
            _b = b;

            _dir = _b - _a;
            _is_segment1 = is_segment1;
            _is_segment2 = is_segment2;
        }
示例#16
0
        private void DrawLineTextSegment(Target2DWrapper <CGContextWrapper> target, double[] x, double[] y, ushort[] glyphs, int color,
                                         int?haloColor, int?haloRadius, double middlePosition, float[] characterWidths,
                                         double textLength, float charachterHeight, CTFont font)
        {
            // see if text is 'upside down'
            double   averageAngle = 0;
            double   first        = middlePosition - (textLength / 2.0);
            PointF2D current      = Polyline2D.PositionAtPosition(x, y, first);

            for (int idx = 0; idx < glyphs.Length; idx++)
            {
                double   nextPosition = middlePosition - (textLength / 2.0) + ((textLength / (glyphs.Length)) * (idx + 1));
                PointF2D next         = Polyline2D.PositionAtPosition(x, y, nextPosition);

                // translate to the final position, the center of the line segment between 'current' and 'next'.
                //PointF2D position = current + ((next - current) / 2.0);

                // calculate the angle.
                VectorF2D vector       = next - current;
                VectorF2D horizontal   = new VectorF2D(1, 0);
                double    angleDegrees = ((Degree)horizontal.Angle(vector)).Value;
                averageAngle = averageAngle + angleDegrees;
                current      = next;
            }
            averageAngle = averageAngle / glyphs.Length;


            // revers if 'upside down'
            double[] xText = x;
            double[] yText = y;
            if (averageAngle > 90 && averageAngle < 180 + 90)
            {
                xText = x.Reverse().ToArray();
                yText = y.Reverse().ToArray();
            }

            first   = middlePosition - (textLength / 2.0);
            current = Polyline2D.PositionAtPosition(xText, yText, first);

            //target.Target.CGContext.SaveState ();
            //target.Target.CGContext.TranslateCTM (xText[0], yText[0]);

            double nextPosition2 = first;

            for (int idx = 0; idx < glyphs.Length; idx++)
            {
                nextPosition2 = nextPosition2 + characterWidths [idx];
                PointF2D next = Polyline2D.PositionAtPosition(xText, yText, nextPosition2);
                //ushort currentChar = glyphs [idx];

                PointF2D position = current;

                target.Target.CGContext.SaveState();

                // translate to the final position, the center of the line segment between 'current' and 'next'.
                double[] transformed = this.Tranform(position[0], position[1]);
                target.Target.CGContext.TranslateCTM(
                    (float)transformed [0],
                    (float)transformed [1]);

                // calculate the angle.
                VectorF2D vector       = next - current;
                VectorF2D horizontal   = new VectorF2D(1, 0);
                double    angleDegrees = (horizontal.Angle(vector)).Value;

                // rotate the character.
                target.Target.CGContext.RotateCTM((float)angleDegrees);
//
//				// translate the character so the center of its base is over the origin.
                target.Target.CGContext.TranslateCTM(0, charachterHeight / 3.0f);

                // rotate 'upside down'
                target.Target.CGContext.ConcatCTM(new CGAffineTransform(1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f));

                target.Target.CGContext.BeginPath();

                CGPath path = font.GetPathForGlyph(glyphs [idx]);
                target.Target.CGContext.AddPath(path);
                if (haloRadius.HasValue && haloColor.HasValue)                   // also draw the halo.
                {
                    target.Target.CGContext.DrawPath(CGPathDrawingMode.FillStroke);
                }
                else
                {
                    target.Target.CGContext.DrawPath(CGPathDrawingMode.Fill);
                }
                //target.Target.CGContext.ClosePath ();
                target.Target.CGContext.RestoreState();

                current = next;
            }
        }