예제 #1
0
        public static MatrixHelper operator *(MatrixHelper Matrix1, MatrixHelper Matrix2)
        {
            var result = new MatrixHelper();

            result._value.M11 = (Matrix1.Value.M11 * Matrix2.Value.M11) + (Matrix1.Value.M12 * Matrix2.Value.M21);
            result._value.M12 = (Matrix1.Value.M11 * Matrix2.Value.M12) + (Matrix1.Value.M12 * Matrix2.Value.M22);
            result._value.M21 = (Matrix1.Value.M21 * Matrix2.Value.M11) + (Matrix1.Value.M22 * Matrix2.Value.M21);
            result._value.M22 = (Matrix1.Value.M21 * Matrix2.Value.M12) + (Matrix1.Value.M22 * Matrix2.Value.M22);
            result._value.OffsetX = (Matrix1.Value.OffsetX * Matrix2.Value.M11) +
                                    (Matrix1.Value.OffsetY * Matrix2.Value.M21) + Matrix2.Value.OffsetX;
            result._value.OffsetY = (Matrix1.Value.OffsetX * Matrix2.Value.M12) +
                                    (Matrix1.Value.OffsetY * Matrix2.Value.M22) + Matrix2.Value.OffsetY;

            return (result);
        }
예제 #2
0
 public static MatrixHelper Multiply(MatrixHelper Matrix1, MatrixHelper Matrix2)
 {
     return (Matrix1 * Matrix2);
 }
예제 #3
0
        public void Scale(double XScale, double YScale)
        {
            var scaleMatrix = new MatrixHelper();
            scaleMatrix._value.M11 = XScale;
            scaleMatrix._value.M12 = 0;
            scaleMatrix._value.M21 = 0;
            scaleMatrix._value.M22 = YScale;

            MatrixHelper result = this * scaleMatrix;
            _value.M11 = result.Value.M11;
            _value.M12 = result.Value.M12;
            _value.M21 = result.Value.M21;
            _value.M22 = result.Value.M22;
            _value.OffsetX = result.Value.OffsetX;
            _value.OffsetY = result.Value.OffsetY;
        }
예제 #4
0
        public void Rotate(double Angle)
        {
            double angleRadians = Angle * Math.PI / 180.0;

            var rotationMatrix = new MatrixHelper();
            rotationMatrix._value.M11 = Math.Cos(angleRadians);
            rotationMatrix._value.M12 = Math.Sin(angleRadians);
            rotationMatrix._value.M21 = -rotationMatrix.Value.M12;
            rotationMatrix._value.M22 = rotationMatrix.Value.M11;

            MatrixHelper result = this * rotationMatrix;
            _value.M11 = result.Value.M11;
            _value.M12 = result.Value.M12;
            _value.M21 = result.Value.M21;
            _value.M22 = result.Value.M22;
            _value.OffsetX = result.Value.OffsetX;
            _value.OffsetY = result.Value.OffsetY;
        }
        // By the time we get here, we know that no part of the Geometry is
        //  a StreamGeometry or a CombinedGeometry
        private void FlattenGeometry(PathGeometry pathGeoDst, Geometry geoSrc, double tolerance, Matrix matxPrevious)
        {
            #if SILVERLIGHT
            MatrixHelper matxHelper = new MatrixHelper(TransformHelper.GetTransformValue(geoSrc.Transform)) *
                                      new MatrixHelper(matxPrevious);
            Matrix matx = matxHelper.Value;
            #else
            Matrix matx = geoSrc.Transform.Value * matxPrevious;
            #endif
            if (geoSrc is GeometryGroup)
            {
                foreach (Geometry geoChild in (geoSrc as GeometryGroup).Children)
                {
                    FlattenGeometry(pathGeoDst, geoChild, tolerance, matx);
                }
            }
            else if (geoSrc is LineGeometry)
            {
                var lineGeoSrc = geoSrc as LineGeometry;

                PathFigure figDst = GetPathFigure();

                PolyLineSegment segDst = GetPolyLineSegment();

                figDst.StartPoint = matx.Transform(lineGeoSrc.StartPoint);
                segDst.Points.Add(matx.Transform(lineGeoSrc.EndPoint));

                figDst.Segments.Add(segDst);
                pathGeoDst.Figures.Add(figDst);
            }
            else if (geoSrc is RectangleGeometry)
            {
                var rectGeoSrc = geoSrc as RectangleGeometry;
                PathFigure figDst = GetPathFigure();
                PolyLineSegment segDst = GetPolyLineSegment();

                if (rectGeoSrc.RadiusX == 0 || rectGeoSrc.RadiusY == 0)
                {
            #if SILVERLIGHT
                    figDst.StartPoint = matx.Transform(new RectHelper(rectGeoSrc.Rect).TopLeft);
                    segDst.Points.Add(matx.Transform(new RectHelper(rectGeoSrc.Rect).TopRight));
                    segDst.Points.Add(matx.Transform(new RectHelper(rectGeoSrc.Rect).BottomRight));
                    segDst.Points.Add(matx.Transform(new RectHelper(rectGeoSrc.Rect).BottomLeft));
                    segDst.Points.Add(matx.Transform(new RectHelper(rectGeoSrc.Rect).TopLeft));
            #else
                    figDst.StartPoint = matx.Transform(rectGeoSrc.Rect.TopLeft);
                    segDst.Points.Add(matx.Transform(rectGeoSrc.Rect.TopRight));
                    segDst.Points.Add(matx.Transform(rectGeoSrc.Rect.BottomRight));
                    segDst.Points.Add(matx.Transform(rectGeoSrc.Rect.BottomLeft));
                    // Note: added line below to Petzold code, added for compatability with WPF's method
                    segDst.Points.Add(matx.Transform(rectGeoSrc.Rect.TopLeft));
            #endif
                }
                else
                {
                    double radiusX = Math.Min(rectGeoSrc.Rect.Width / 2, rectGeoSrc.RadiusX);
                    double radiusY = Math.Min(rectGeoSrc.Rect.Height / 2, rectGeoSrc.RadiusY);
                    Rect rect = rectGeoSrc.Rect;

                    figDst.StartPoint = matx.Transform(new Point(rect.Left + radiusX, rect.Top));

                    AddCorner(segDst, matx, new Point(rect.Right - radiusX, rect.Top),
                              new Point(rect.Right, rect.Top + radiusY), radiusX, radiusY, tolerance);
                    AddCorner(segDst, matx, new Point(rect.Right, rect.Bottom - radiusY),
                              new Point(rect.Right - radiusX, rect.Bottom), radiusX, radiusY, tolerance);
                    AddCorner(segDst, matx, new Point(rect.Left + radiusX, rect.Bottom),
                              new Point(rect.Left, rect.Bottom - radiusY), radiusX, radiusY, tolerance);
                    AddCorner(segDst, matx, new Point(rect.Left, rect.Top + radiusY),
                              new Point(rect.Left + radiusX, rect.Top), radiusX, radiusY, tolerance);
                }

                figDst.IsClosed = true;
                figDst.Segments.Add(segDst);
                pathGeoDst.Figures.Add(figDst);
            }
            else if (geoSrc is EllipseGeometry)
            {
                var elipGeoSrc = geoSrc as EllipseGeometry;
                PathFigure figDst = GetPathFigure();
                PolyLineSegment segDst = GetPolyLineSegment();

                var max = (int)(4 * (elipGeoSrc.RadiusX + elipGeoSrc.RadiusY) / tolerance);

                for (int i = 0; i < max; i++)
                {
                    double x = elipGeoSrc.Center.X + elipGeoSrc.RadiusX * Math.Sin(i * 2 * Math.PI / max);
                    double y = elipGeoSrc.Center.Y - elipGeoSrc.RadiusY * Math.Cos(i * 2 * Math.PI / max);
                    Point pt = matx.Transform(new Point(x, y));

                    if (i == 0)
                        figDst.StartPoint = pt;
                    else
                        segDst.Points.Add(pt);
                }

                figDst.IsClosed = true;
                figDst.Segments.Add(segDst);
                pathGeoDst.Figures.Add(figDst);
            }

            else if (geoSrc is PathGeometry)
            {
                var pathGeoSrc = geoSrc as PathGeometry;
                pathGeoDst.FillRule = pathGeoSrc.FillRule;

                foreach (PathFigure figSrc in pathGeoSrc.Figures)
                {
                    PathFigure figDst = GetPathFigure();
                    figDst.IsFilled = figSrc.IsFilled;
                    figDst.IsClosed = figSrc.IsClosed;
                    figDst.StartPoint = matx.Transform(figSrc.StartPoint);
                    Point ptLast = figDst.StartPoint;

                    foreach (PathSegment segSrc in figSrc.Segments)
                    {
                        PolyLineSegment segDst = GetPolyLineSegment();
            #if !SILVERLIGHT
                        segDst.IsStroked = segSrc.IsStroked;
                        segDst.IsSmoothJoin = segSrc.IsSmoothJoin;
            #endif
                        if (segSrc is LineSegment)
                        {
                            var lineSegSrc = segSrc as LineSegment;
                            ptLast = matx.Transform(lineSegSrc.Point);
                            segDst.Points.Add(ptLast);
                        }

                        else if (segSrc is PolyLineSegment)
                        {
                            var polySegSrc = segSrc as PolyLineSegment;

                            foreach (Point pt in polySegSrc.Points)
                            {
                                ptLast = matx.Transform(pt);
                                segDst.Points.Add(ptLast);
                            }
                        }

                        else if (segSrc is BezierSegment)
                        {
                            var bezSeg = segSrc as BezierSegment;
                            Point pt0 = ptLast;
                            Point pt1 = matx.Transform(bezSeg.Point1);
                            Point pt2 = matx.Transform(bezSeg.Point2);
                            Point pt3 = matx.Transform(bezSeg.Point3);

                            points.Clear();
                            FlattenCubicBezier(points, pt0, pt1, pt2, pt3, tolerance);

                            for (int i = 1; i < points.Count; i++)
                                segDst.Points.Add(points[i]);

                            ptLast = points[points.Count - 1];
                        }

                        else if (segSrc is PolyBezierSegment)
                        {
                            var polyBezSeg = segSrc as PolyBezierSegment;

                            for (int bez = 0; bez < polyBezSeg.Points.Count; bez += 3)
                            {
                                if (bez + 2 > polyBezSeg.Points.Count - 1)
                                    break;

                                Point pt0 = ptLast;
                                Point pt1 = matx.Transform(polyBezSeg.Points[bez]);
                                Point pt2 = matx.Transform(polyBezSeg.Points[bez + 1]);
                                Point pt3 = matx.Transform(polyBezSeg.Points[bez + 2]);

                                points.Clear();
                                FlattenCubicBezier(points, pt0, pt1, pt2, pt3, tolerance);

                                for (int i = 1; i < points.Count; i++)
                                    segDst.Points.Add(points[i]);

                                ptLast = points[points.Count - 1];
                            }
                        }

                        else if (segSrc is QuadraticBezierSegment)
                        {
                            var quadBezSeg = segSrc as QuadraticBezierSegment;
                            Point pt0 = ptLast;
                            Point pt1 = matx.Transform(quadBezSeg.Point1);
                            Point pt2 = matx.Transform(quadBezSeg.Point2);

                            points.Clear();
                            FlattenQuadraticBezier(points, pt0, pt1, pt2, tolerance);

                            for (int i = 1; i < points.Count; i++)
                                segDst.Points.Add(points[i]);

                            ptLast = points[points.Count - 1];
                        }

                        else if (segSrc is PolyQuadraticBezierSegment)
                        {
                            var polyQuadBezSeg = segSrc as PolyQuadraticBezierSegment;

                            for (int bez = 0; bez < polyQuadBezSeg.Points.Count; bez += 2)
                            {
                                if (bez + 1 > polyQuadBezSeg.Points.Count - 1)
                                    break;

                                Point pt0 = ptLast;
                                Point pt1 = matx.Transform(polyQuadBezSeg.Points[bez]);
                                Point pt2 = matx.Transform(polyQuadBezSeg.Points[bez + 1]);

                                points.Clear();
                                FlattenQuadraticBezier(points, pt0, pt1, pt2, tolerance);

                                for (int i = 1; i < points.Count; i++)
                                    segDst.Points.Add(points[i]);

                                ptLast = points[points.Count - 1];
                            }
                        }

                        else if (segSrc is ArcSegment)
                        {
                            var arcSeg = segSrc as ArcSegment;
                            points.Clear();

                            FlattenArc(points, ptLast, arcSeg.Point,
                                       arcSeg.Size.Width, arcSeg.Size.Height,
                                       arcSeg.RotationAngle,
                                       arcSeg.IsLargeArc,
                                       arcSeg.SweepDirection == SweepDirection.Counterclockwise,
                                       tolerance);

                            // Set ptLast while transferring points
                            for (int i = 1; i < points.Count; i++)
                                segDst.Points.Add(ptLast = points[i]);
                        }
                        figDst.Segments.Add(segDst);
                    }
                    pathGeoDst.Figures.Add(figDst);
                }
            }
        }
        private void FlattenArc(List<Point> points, Point pt1, Point pt2,
                                double radiusX, double radiusY, double angleRotation,
                                bool isLargeArc, bool isCounterclockwise,
                                double tolerance)
        {
            // Adjust for different radii and rotation angle
            #if SILVERLIGHT
            var matx = new MatrixHelper();
            matx.Rotate(-angleRotation);
            matx.Scale(radiusY / radiusX, 1);
            pt1 = matx.Value.Transform(pt1);
            pt2 = matx.Value.Transform(pt2);
            #else
            Matrix matx = new Matrix();
            matx.Rotate(-angleRotation);
            matx.Scale(radiusY / radiusX, 1);
            pt1 = matx.Transform(pt1);
            pt2 = matx.Transform(pt2);
            #endif

            // Get info about chord that connects both points
            var midPoint = new Point((pt1.X + pt2.X) / 2, (pt1.Y + pt2.Y) / 2);
            #if SILVERLIGHT
            Vector vect = new PointHelper(pt2) - new PointHelper(pt1);
            #else
            Vector vect = pt2 - pt1;
            #endif
            double halfChord = vect.Length / 2;

            // Get vector from chord to center
            Vector vectRotated;

            // (comparing two Booleans here!)
            vectRotated = isLargeArc == isCounterclockwise ? new Vector(-vect.Y, vect.X) : new Vector(vect.Y, -vect.X);

            vectRotated.Normalize();

            // Distance from chord to center
            double centerDistance = Math.Sqrt(radiusY * radiusY - halfChord * halfChord);

            // Calculate two center points
            Point center = midPoint + centerDistance * vectRotated;

            // Get angles from center to the two points
            double angle1 = Math.Atan2(pt1.Y - center.Y, pt1.X - center.X);
            double angle2 = Math.Atan2(pt2.Y - center.Y, pt2.X - center.X);

            // (another comparison of two Booleans!)
            if (isLargeArc == (Math.Abs(angle2 - angle1) < Math.PI))
            {
                if (angle1 < angle2)
                    angle1 += 2 * Math.PI;
                else
                    angle2 += 2 * Math.PI;
            }

            // Invert matrix for final point calculation
            matx.Invert();

            // Calculate number of points for polyline approximation
            var max = (int)((4 * (radiusX + radiusY) * Math.Abs(angle2 - angle1) / (2 * Math.PI)) / tolerance);

            // Loop through the points
            for (int i = 0; i <= max; i++)
            {
                double angle = ((max - i) * angle1 + i * angle2) / max;
                double x = center.X + radiusY * Math.Cos(angle);
                double y = center.Y + radiusY * Math.Sin(angle);

                // Transform the point back
                Point pt = matx.Transform(new Point(x, y));
                points.Add(pt);
            }
        }