Ejemplo n.º 1
0
        void UpdateTransform()
        {
            // set the transform
            mat  = Matrix3x2.Identity;
            mat *= Matrix3x2.CreateTranslation(-rect.Width * 0.5f, -rect.Height * 0.5f);
            mat *= Matrix3x2.CreateScale(this.scale, this.scale);
            mat *= Matrix3x2.CreateRotation((float)(Math.PI * this.angle / 180f));
            mat *= Matrix3x2.CreateTranslation(pos.X, pos.Y);

            // get the inversed matrix
            Matrix3x2.Invert(mat, out matInv);
        }
Ejemplo n.º 2
0
        public void Matrix3x2InvertScaleTest()
        {
            Matrix3x2 mtx = Matrix3x2.CreateScale(23, -42);

            Matrix3x2 actual;

            Assert.IsTrue(Matrix3x2.Invert(mtx, out actual));

            Matrix3x2 i = mtx * actual;

            Assert.IsTrue(MathHelper.Equal(i, Matrix3x2.Identity));
        }
Ejemplo n.º 3
0
        public void Matrix3x2InvertRotationTest()
        {
            Matrix3x2 mtx = Matrix3x2.CreateRotation(2);

            Matrix3x2 actual;

            Assert.True(Matrix3x2.Invert(mtx, out actual));

            Matrix3x2 i = mtx * actual;

            Assert.True(MathHelper.Equal(i, Matrix3x2.Identity));
        }
Ejemplo n.º 4
0
        public void Draw(DrawArgs drawArgs)
        {
            _prerenderProvider.CreatePrerenders(drawArgs, _map.Size);

            // apply view matrix
            drawArgs.PushScale(_zoom);
            drawArgs.PushTranslation(_pan);

            // apply level of detail
            var drawLod = _zoom > 0.5 ? DrawLevelOfDetail.Normal : DrawLevelOfDetail.Low;

            drawArgs.LevelOfDetail = drawLod;

            // calculate viewport transform, used for zoom/pan
            Matrix3x2.Invert(drawArgs.CurrentTransform, out _mapTransform);

            // calculate visible field coords
            var bottomLeftFieldCoords = TranslateToFieldCoords(_bottomLeftViewLimit);
            var blx = bottomLeftFieldCoords.X;
            var bly = bottomLeftFieldCoords.Y;
            var topRightFieldCoords = TranslateToFieldCoords(_topRightViewLimit);
            var urx = topRightFieldCoords.X;
            var ury = topRightFieldCoords.Y;

            // have agents draw themselves layer by layer
            foreach (var drawLayer in DrawLayers)
            {
                drawArgs.Layer = drawLayer;

                var prerender = _prerenderProvider.GetPrerender(drawLod, drawLayer);

                if (prerender != null)
                {
                    drawArgs.Ds.DrawImage(prerender, -_tileRadius, -2.0f * _tileRadiusH);
                }
                else
                {
                    // find indicators which are currently on screen
                    var culledIndicators = _indicatorRegistry
                                           .GetIndicators(drawLod, drawLayer)
                                           .Where(tm => blx <= tm.Position.X && tm.Position.X <= urx && bly <= tm.Position.Y && tm.Position.Y <= ury);

                    foreach (var indicator in culledIndicators)
                    {
                        indicator.Draw(drawArgs);
                    }
                }
            }

            // restore view matrix
            drawArgs.Pop();
            drawArgs.Pop();
        }
Ejemplo n.º 5
0
        public Vector2 InvertTransformPoint(Matrix3x2 matrix, Vector2 point)
        {
            if (Matrix3x2.Invert(matrix, out Matrix3x2 inverted))
            {
                return(new Vector2(
                           x: point.X *inverted.M11 + point.Y *inverted.M21 + inverted.M31,
                           y: point.X * inverted.M12 + point.Y * inverted.M22 + inverted.M32
                           ));
            }

            return(point);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Pushes a matrix transformation.
        /// </summary>
        /// <param name="matrix">The matrix</param>
        /// <returns>A disposable used to undo the transformation.</returns>
        public IDisposable PushTransform(Matrix matrix)
        {
            Matrix3x2 m3x2      = matrix.ToDirect2D();
            Matrix3x2 transform = this.renderTarget.Transform * m3x2;

            this.renderTarget.Transform = transform;

            return(Disposable.Create(() =>
            {
                m3x2.Invert();
                this.renderTarget.Transform = transform * m3x2;
            }));
        }
Ejemplo n.º 7
0
        private void DrawDiagnostics(DeviceContext renderTarget)
        {
            renderTarget.Transform = Matrix3x2.Identity;
            Matrix3x2 wt = GlobalTransform;

            wt.Invert();
            var worldPos = Matrix3x2.TransformPoint(wt, MouseClientPosition);

            renderTarget.DrawText(
                $"FPS: {RenderTimer.FramesPerSecond:0}\r\nFrameTime: {RenderTimer.DurationSinceLastFrame}\r\n({worldPos.X:0}, {worldPos.Y:0})",
                XResource.TextFormats[11],
                new RectangleF(0, 0, 100, 30),
                XResource.GetColor(Color.White));
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Gets the centered transform matrix based upon the source and destination rectangles
        /// </summary>
        /// <param name="sourceRectangle">The source image bounds.</param>
        /// <param name="destinationRectangle">The destination image bounds.</param>
        /// <param name="matrix">The transformation matrix.</param>
        /// <returns>The <see cref="Matrix3x2"/></returns>
        public static Matrix3x2 GetCenteredTransformMatrix(Rectangle sourceRectangle, Rectangle destinationRectangle, Matrix3x2 matrix)
        {
            // We invert the matrix to handle the transformation from screen to world space.
            // This ensures scaling matrices are correct.
            Matrix3x2.Invert(matrix, out Matrix3x2 inverted);

            var translationToTargetCenter = Matrix3x2.CreateTranslation(-destinationRectangle.Width * .5F, -destinationRectangle.Height * .5F);
            var translateToSourceCenter   = Matrix3x2.CreateTranslation(sourceRectangle.Width * .5F, sourceRectangle.Height * .5F);

            Matrix3x2.Invert(translationToTargetCenter * inverted * translateToSourceCenter, out Matrix3x2 centered);

            // Translate back to world to pass to the Transform method.
            return(centered);
        }
        public void Matrix3x2InvertAffineTest()
        {
            Matrix3x2 mtx = Matrix3x2.CreateRotation(2) *
                            Matrix3x2.CreateScale(23, -42) *
                            Matrix3x2.CreateTranslation(17, 53);

            Matrix3x2 actual;

            Assert.True(Matrix3x2.Invert(mtx, out actual));

            Matrix3x2 i = mtx * actual;

            Assert.True(MathHelper.Equal(i, Matrix3x2.Identity));
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Gets the centered transform matrix based upon the source and destination rectangles.
        /// </summary>
        /// <param name="sourceRectangle">The source image bounds.</param>
        /// <param name="matrix">The transformation matrix.</param>
        /// <returns>The <see cref="Matrix3x2"/></returns>
        public static Matrix3x2 CreateCenteredTransformMatrix(Rectangle sourceRectangle, Matrix3x2 matrix)
        {
            Rectangle destinationRectangle = GetTransformedBoundingRectangle(sourceRectangle, matrix);

            // We invert the matrix to handle the transformation from screen to world space.
            // This ensures scaling matrices are correct.
            Matrix3x2.Invert(matrix, out Matrix3x2 inverted);

            var translationToTargetCenter = Matrix3x2.CreateTranslation(new Vector2(-destinationRectangle.Width, -destinationRectangle.Height) * .5F);
            var translateToSourceCenter   = Matrix3x2.CreateTranslation(new Vector2(sourceRectangle.Width, sourceRectangle.Height) * .5F);

            // Translate back to world space.
            Matrix3x2.Invert(translationToTargetCenter * inverted * translateToSourceCenter, out Matrix3x2 centered);

            return(centered);
        }
Ejemplo n.º 11
0
        // Toggles the color of cells when they are clicked on.
        private void ProcessPointerInput(PointerRoutedEventArgs e)
        {
            if (!isPointerDown)
            {
                return;
            }

            // Invert the display transform, to convert pointer positions into simulation rendertarget space.
            Matrix3x2 transform;

            Matrix3x2.Invert(Utils.GetDisplayTransform(canvas.Size, canvas, simulationW, simulationH), out transform);

            foreach (var point in e.GetIntermediatePoints(canvas))
            {
                if (!point.IsInContact)
                {
                    continue;
                }

                var pos = Vector2.Transform(point.Position.ToVector2(), transform);

                var x = canvas.ConvertDipsToPixels(pos.X);
                var y = canvas.ConvertDipsToPixels(pos.Y);

                // If the point is within the bounds of the rendertarget, and not the same as the last point...
                if (x >= 0 &&
                    y >= 0 &&
                    x < simulationW &&
                    y < simulationH &&
                    ((x != lastPointerX || y != lastPointerY)))
                {
                    // Read the current color.
                    var cellColor = currentSurface.GetPixelColors(x, y, 1, 1);

                    // Toggle the value.
                    cellColor[0] = cellColor[0].R > 0 ? Colors.Black : Colors.White;

                    // Set the new color.
                    currentSurface.SetPixelColors(cellColor, x, y, 1, 1);

                    lastPointerX = x;
                    lastPointerY = y;
                }
            }
        }
        public void OnEraseSelectFinished(object sender, bool blendCurrentStroke)
        {
            List <List <Vector2> > convexHulls = new List <List <Vector2> >(VectorInkBuilder.ConvexHullChainProducer.AllData);


            if (!TransformationMatrix.IsIdentity)
            {
                bool res = Matrix3x2.Invert(TransformationMatrix, out Matrix3x2 viewToModelTransformationMatrix);

                if (!res)
                {
                    throw new InvalidOperationException("Transform matrix could not be inverted.");
                }

                TransformUtils.TransformPolysXY(convexHulls, viewToModelTransformationMatrix);
            }

            mSpatialModel.Erase(convexHulls, mSelectTool.ManipulationMode);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Constructor, creates grid representation and transformations.
        /// </summary>
        /// <param name="mapResolution">Map resolution in meters per pixel</param>
        /// <param name="size">Map size in pixels</param>
        /// <param name="offset">Offset if meters</param>
        public GridMap(float mapResolution, Point size, Vector2 offset)
        {
            Properties = new MapProperties(mapResolution, size, offset);

            // Construct map array
            mapArray = new LogOddsCell[Dimensions.X * Dimensions.Y];
            for (int i = 0; i < mapArray.Length; ++i)
            {
                mapArray[i].Reset();
            }

            // Construct transformation matrix
            // TODO Not quite sure if offset is needed
            mapTworld = Matrix3x2.CreateScale(Properties.ScaleToMap) * Matrix3x2.CreateTranslation(Properties.Offset.X, Properties.Offset.Y);
            if (!Matrix3x2.Invert(mapTworld, out worldTmap))
            {
                throw new Exception("Map to world matrix is not invertible");
            }
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Gets the individual pixel coordinates of a collision between two sprites.
        /// </summary>
        /// <param name="sprite1">The first sprite.</param>
        /// <param name="subImage1">The subimage of the first sprite.</param>
        /// <param name="modelWorldTransform1">The transformation matrix of the first sprite.</param>
        /// <param name="sprite2">The second sprite.</param>
        /// <param name="subImage2">The subimage of the second sprite.</param>
        /// <param name="modelWorldTransform2">The transformation matrix of the second sprite.</param>
        /// <returns>An enumerable of (x, y) tuple values representing the pixels in the collision.</returns>
        public IEnumerable <(int x, int y)> GetSpriteCollisions(GameSprite sprite1, int subImage1,
                                                                Matrix3x2 modelWorldTransform1, GameSprite sprite2, int subImage2, Matrix3x2 modelWorldTransform2)
        {
            // First, transform the bounding boxes to account for sprite origin, rotations, scaling, and position.
            var bb1 = GetSpriteTransformedBoundingBox(sprite1, modelWorldTransform1);
            var bb2 = GetSpriteTransformedBoundingBox(sprite2, modelWorldTransform2);

            // Invert the transformation matrixes so we can map world coordinates into sprite coordinates.
            Matrix3x2.Invert(modelWorldTransform1, out var spriteLocalTransform1);
            Matrix3x2.Invert(modelWorldTransform2, out var spriteLocalTransform2);

            // Get the intersection of both bounding boxes.
            var bbIntersection = bb1.Intersection(ref bb2);

            // If the bounding boxes don't overlap, there is no collision.
            if (!bbIntersection.IsValid)
            {
                yield break;
            }

            // Get the collision mask for each sprite.
            var mask1 = sprite1.SeparateCollisionMasks ? sprite1.CollisionMasks[subImage1] : sprite1.CollisionMasks[0];
            var mask2 = sprite2.SeparateCollisionMasks ? sprite2.CollisionMasks[subImage2] : sprite2.CollisionMasks[0];

            // Look at each pixel in the bounding box intersection.
            for (var x = bbIntersection.Left; x <= bbIntersection.Right; x++)
            {
                for (var y = bbIntersection.Top; y <= bbIntersection.Bottom; y++)
                {
                    // Transform the pixel coordinate to sprite coordinates for both sprites
                    // using the inverted world matrix.
                    var localV1 = Vector2.Transform(new Vector2(x, y), spriteLocalTransform1);
                    var localV2 = Vector2.Transform(new Vector2(x, y), spriteLocalTransform2);

                    // Check if the respective sprite coordinates overlap solid pixels in both sprites.
                    if (mask1.HitTest((int)localV1.X, (int)localV1.Y) &&
                        mask2.HitTest((int)localV2.X, (int)localV2.Y))
                    {
                        yield return(x, y);
                    }
                }
            }
        }
Ejemplo n.º 15
0
        // Toggles the color of cells when they are clicked on.
        private void ProcessPointerInput(PointerRoutedEventArgs e)
        {
            if (!isPointerDown)
            {
                return;
            }

            // Invert the display transform, to convert pointer positions into simulation rendertarget space.
            Matrix3x2 transform;

            Matrix3x2.Invert(GetDisplayTransform(canvas), out transform);

            foreach (var point in e.GetIntermediatePoints(canvas))
            {
                if (!point.IsInContact)
                {
                    continue;
                }

                var pos = Vector2.Transform(point.Position.ToVector2(), transform);

                var x = canvas.ConvertDipsToPixels(pos.X, CanvasDpiRounding.Floor);
                var y = canvas.ConvertDipsToPixels(pos.Y, CanvasDpiRounding.Floor);

                // If the point is within the bounds of the rendertarget, and not the same as the last point...
                if (x >= 0 &&
                    y >= 0 &&
                    x < simulationW &&
                    y < simulationH &&
                    ((x != lastPointerX || y != lastPointerY)))
                {
                    // We avoid manipulating GPU resources from inside an input event handler
                    // (since we'd need to handle device lost and possible concurrent running with CreateResources).
                    // Instead, we collect up a list of points and process them from the Draw handler.
                    hitPoints.Add(new IntPoint(x, y));

                    lastPointerX = x;
                    lastPointerY = y;
                }
            }

            canvas.Invalidate();
        }
Ejemplo n.º 16
0
            /// <inheritdoc />
            public Point GetPosition(object?relativeTo)
            {
                var rawWpfPosition = _wpfArgs.GetPosition(WpfHost.Current);
                var rawPosition    = new Point(rawWpfPosition.X, rawWpfPosition.Y);

                if (relativeTo is null)
                {
                    return(rawPosition);
                }

                if (relativeTo is UIElement elt)
                {
                    var eltToRoot = UIElement.GetTransform(elt, null);
                    Matrix3x2.Invert(eltToRoot, out var rootToElt);

                    return(rootToElt.Transform(rawPosition));
                }

                throw new InvalidOperationException("The relative to must be a UIElement.");
            }
Ejemplo n.º 17
0
        public override void OnReleased(UIElement uiElement, PointerRoutedEventArgs args)
        {
            if (mIsTranslating)
            {
                Matrix3x2 translation = Matrix3x2.Identity;

                var pt = args.GetCurrentPoint(uiElement).Position;
                if (!mStrokeHandler.TransformationMatrix.IsIdentity)
                {
                    bool res = Matrix3x2.Invert(mStrokeHandler.TransformationMatrix, out Matrix3x2 modelTransformationMatrix);

                    if (!res)
                    {
                        throw new InvalidOperationException("Transform matrix could not be inverted.");
                    }

                    Vector2 currentPointPos      = new Vector2((float)pt.X, (float)pt.Y);
                    Vector2 startPos             = new Vector2((float)mStartPosition.X, (float)mStartPosition.Y);
                    Vector2 modelCurrentPointPos = Vector2.Transform(currentPointPos, modelTransformationMatrix);
                    Vector2 modelStartPos        = Vector2.Transform(startPos, modelTransformationMatrix);

                    double dX = modelCurrentPointPos.X - modelStartPos.X;
                    double dY = modelCurrentPointPos.Y - modelStartPos.Y;
                    translation = Matrix3x2.CreateTranslation((float)dX, (float)dY);
                }
                else
                {
                    double dX = pt.X - mStartPosition.X;
                    double dY = pt.Y - mStartPosition.Y;
                    translation = Matrix3x2.CreateTranslation((float)dX, (float)dY);
                }

                TranslateFinished?.Invoke(this, translation);
            }
            else
            {
                base.OnReleased(uiElement, args);
            }

            mIsTranslating = false;
        }
Ejemplo n.º 18
0
        public void Matrix3x2DeterminantTest1()
        {
            Matrix3x2 a = new Matrix3x2();

            a.M11 = 5.0f; a.M12 = 2.0f;
            a.M21 = 12.0f; a.M22 = 6.8f;
            a.M31 = 6.5f; a.M32 = 1.0f;
            Matrix3x2 i;

            Assert.IsTrue(Matrix3x2.Invert(a, out i));

            float detA = a.GetDeterminant();
            float detI = i.GetDeterminant();
            float t    = 1.0f / detI;

            // only accurate to 3 precision
            Assert.IsTrue(System.Math.Abs(detA - t) < 1e-3, "Matrix3x2.GetDeterminant was not set correctly.");

            // sanity check against 4x4 version
            Assert.AreEqual(new Matrix4x4(a).GetDeterminant(), detA);
            Assert.AreEqual(new Matrix4x4(i).GetDeterminant(), detI);
        }
Ejemplo n.º 19
0
        private Matrix3x2 unNormScreen;          // just flip Y


        public void CalcultateMatrixes()
        {
            worldToScreenAndFlipY = Matrix3x2.CreateTranslation(-PositionInWorldCoordinates.X, -PositionInWorldCoordinates.Y) *
                                    Matrix3x2.CreateScale(new Vector2(Zoom.X, Zoom.Y)) * //  Y up is plus
                                    Matrix3x2.CreateScale(GraphAreaSize) *
                                    Matrix3x2.CreateTranslation(GraphAreaSize.X / 2 + GraphOffsetInPx.X, GraphAreaSize.Y / 2 + GraphOffsetInPx.Y) *

                                    // move 0,0 corner in pix from upper left corner to lower, left corner
                                    Matrix3x2.CreateScale(new Vector2(1, -1)) *
                                    Matrix3x2.CreateTranslation(new Vector2(0, ImageSize.Y));

            worldToScreen = Matrix3x2.CreateTranslation(-PositionInWorldCoordinates.X, -PositionInWorldCoordinates.Y) *
                            Matrix3x2.CreateScale(new Vector2(Zoom.X, Zoom.Y)) * //  Y up is plus
                            Matrix3x2.CreateScale(GraphAreaSize) *
                            Matrix3x2.CreateTranslation(GraphAreaSize.X / 2 + GraphOffsetInPx.X, GraphAreaSize.Y / 2 + GraphOffsetInPx.Y);

            normScreen = Matrix3x2.CreateScale(new Vector2(1, -1)) *
                         Matrix3x2.CreateTranslation(new Vector2(0, ImageSize.Y));

            Matrix3x2.Invert(worldToScreen, out screenToWorld);
            Matrix3x2.Invert(worldToScreenAndFlipY, out screenToWorldAndFlipY);
            Matrix3x2.Invert(normScreen, out unNormScreen);
        }
Ejemplo n.º 20
0
        public void Matrix3x2InvertTest1()
        {
            Matrix3x2 a = new Matrix3x2();

            a.M11 = 0.0f; a.M12 = 2.0f;
            a.M21 = 0.0f; a.M22 = 4.0f;
            a.M31 = 5.0f; a.M32 = 6.0f;

            float detA = a.GetDeterminant();

            Assert.IsTrue(MathHelper.Equal(detA, 0.0f), "Matrix3x2.Invert did not return the expected value.");

            Matrix3x2 actual;

            Assert.IsFalse(Matrix3x2.Invert(a, out actual));

            // all the elements in Actual is NaN
            Assert.IsTrue(
                float.IsNaN(actual.M11) && float.IsNaN(actual.M12) &&
                float.IsNaN(actual.M21) && float.IsNaN(actual.M22) &&
                float.IsNaN(actual.M31) && float.IsNaN(actual.M32)
                , "Matrix3x2.Invert did not return the expected value.");
        }
        public void OnManipulationSelectFinished(object sender, bool blendCurrentStroke)
        {
            List <List <Vector2> > clonedSimpl    = new List <List <Vector2> >(VectorInkBuilder.PolygonSimplifier.AllData);
            List <List <Vector2> > mergedPolygons = PolygonUtils.MergePolygons(clonedSimpl);

            if (!TransformationMatrix.IsIdentity)
            {
                bool res = Matrix3x2.Invert(TransformationMatrix, out Matrix3x2 viewToModelTransformationMatrix);

                if (!res)
                {
                    throw new InvalidOperationException("Transform matrix could not be inverted.");
                }

                TransformUtils.TransformPolysXY(mergedPolygons, viewToModelTransformationMatrix);
            }

            // NOTE: If ManipulationMode is PartialStroke, affected strokes are deleted and new strokes created
            //       for selected and non-selected portions. This occurs BEFORE any manipulation takes place.
            //       Reverting to previous state in the event of no manipulation taking place requires
            //       undo functionality (delete added strokes, restore deleted strokes)
            mSpatialModel.Select(mergedPolygons[0], mSelectTool.ManipulationMode);
        }
        private void OnRenderFormMouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            // Mouse clicks are in "screen space". DirectX might be rendering the client/form in a different resolution (i.e., "world space")
            // so we need to transform the click coordinates from "screen space" to "world space".
            // It gets trickier. We want to know what facial point is clicked on. The facial point coordinates exist in "local/object space". They
            // were transformed to "world space" prior to being rendered. So, we need to transform the mouse click coordinates from "world space" to
            // the facial point "local/object space".

            Matrix3x2 inverseOfRenderTargetTransform = new Matrix3x2();

            Matrix3x2.Invert(ref this.transformation, out inverseOfRenderTargetTransform);

            Size2F renderTargetSize = this.d2dRenderTarget.Size;

            System.Drawing.Rectangle clientSize = this.renderForm.ClientRectangle;

            float scalingFromClientToRenderTargetX = renderTargetSize.Width / clientSize.Right;
            float scalingFromClientToRenderTargetY = renderTargetSize.Height / clientSize.Bottom;

            Vector2 renderTargetClickCoord            = new Vector2(e.X * scalingFromClientToRenderTargetX, e.Y * scalingFromClientToRenderTargetY);
            Vector2 transformedRenderTargetClickCoord = Matrix3x2.TransformPoint(inverseOfRenderTargetTransform, renderTargetClickCoord);

            RectangleF transformedRenderTargetClickArea = new RectangleF(transformedRenderTargetClickCoord.X, transformedRenderTargetClickCoord.Y, ClickSize, ClickSize);

            this.selectedFacePointIndex = null;

            for (int pointIndex = 0; pointIndex < this.facePoints.Length; pointIndex++)
            {
                if (transformedRenderTargetClickArea.Contains(this.facePoints[pointIndex]))
                {
                    this.selectedFacePointIndex = pointIndex;
                    break;
                }
            }

            this.selectedFacePointTimeout = this.framesPerSecond.RunTime.Add(new TimeSpan(0, 0, EventTimeoutSeconds));
        }
        public void Matrix3x2InvertTest()
        {
            Matrix3x2 mtx = Matrix3x2.CreateRotation(MathHelper.ToRadians(30.0f));

            Matrix3x2 expected = new Matrix3x2();

            expected.M11 = 0.8660254f;
            expected.M12 = -0.5f;

            expected.M21 = 0.5f;
            expected.M22 = 0.8660254f;

            expected.M31 = 0;
            expected.M32 = 0;

            Matrix3x2 actual;

            Assert.True(Matrix3x2.Invert(mtx, out actual));
            Assert.True(MathHelper.Equal(expected, actual), "Matrix3x2.Invert did not return the expected value.");

            Matrix3x2 i = mtx * actual;

            Assert.True(MathHelper.Equal(i, Matrix3x2.Identity), "Matrix3x2.Invert did not return the expected value.");
        }
        /// <inheritdoc/>
        protected override void OnFrameApply(
            ImageFrame <TPixel> source,
            ImageFrame <TPixel> destination,
            Rectangle sourceRectangle,
            Configuration configuration)
        {
            int height = this.TargetDimensions.Height;
            int width  = this.TargetDimensions.Width;

            Rectangle sourceBounds = source.Bounds();
            var       targetBounds = new Rectangle(0, 0, width, height);

            // Since could potentially be resizing the canvas we might need to re-calculate the matrix
            Matrix3x2 matrix = this.GetProcessingMatrix(sourceBounds, targetBounds);

            // Convert from screen to world space.
            Matrix3x2.Invert(matrix, out matrix);

            if (this.Sampler is NearestNeighborResampler)
            {
                ParallelHelper.IterateRows(
                    targetBounds,
                    configuration,
                    rows =>
                {
                    for (int y = rows.Min; y < rows.Max; y++)
                    {
                        Span <TPixel> destRow = destination.GetPixelRowSpan(y);

                        for (int x = 0; x < width; x++)
                        {
                            var point = Point.Transform(new Point(x, y), matrix);
                            if (sourceBounds.Contains(point.X, point.Y))
                            {
                                destRow[x] = source[point.X, point.Y];
                            }
                        }
                    }
                });

                return;
            }

            int maxSourceX = source.Width - 1;
            int maxSourceY = source.Height - 1;

            (float radius, float scale, float ratio)xRadiusScale = this.GetSamplingRadius(source.Width, destination.Width);
            (float radius, float scale, float ratio)yRadiusScale = this.GetSamplingRadius(source.Height, destination.Height);
            float      xScale    = xRadiusScale.scale;
            float      yScale    = yRadiusScale.scale;
            var        radius    = new Vector2(xRadiusScale.radius, yRadiusScale.radius);
            IResampler sampler   = this.Sampler;
            var        maxSource = new Vector4(maxSourceX, maxSourceY, maxSourceX, maxSourceY);
            int        xLength   = (int)MathF.Ceiling((radius.X * 2) + 2);
            int        yLength   = (int)MathF.Ceiling((radius.Y * 2) + 2);

            MemoryAllocator memoryAllocator = configuration.MemoryAllocator;

            using (Buffer2D <float> yBuffer = memoryAllocator.Allocate2D <float>(yLength, height))
                using (Buffer2D <float> xBuffer = memoryAllocator.Allocate2D <float>(xLength, height))
                {
                    ParallelHelper.IterateRows(
                        targetBounds,
                        configuration,
                        rows =>
                    {
                        for (int y = rows.Min; y < rows.Max; y++)
                        {
                            ref TPixel destRowRef = ref MemoryMarshal.GetReference(destination.GetPixelRowSpan(y));
                            ref float ySpanRef    = ref MemoryMarshal.GetReference(yBuffer.GetRowSpan(y));
                            ref float xSpanRef    = ref MemoryMarshal.GetReference(xBuffer.GetRowSpan(y));

                            for (int x = 0; x < width; x++)
                            {
                                // Use the single precision position to calculate correct bounding pixels
                                // otherwise we get rogue pixels outside of the bounds.
                                var point = Vector2.Transform(new Vector2(x, y), matrix);

                                // Clamp sampling pixel radial extents to the source image edges
                                Vector2 maxXY = point + radius;
                                Vector2 minXY = point - radius;

                                // max, maxY, minX, minY
                                var extents = new Vector4(
                                    MathF.Floor(maxXY.X + .5F),
                                    MathF.Floor(maxXY.Y + .5F),
                                    MathF.Ceiling(minXY.X - .5F),
                                    MathF.Ceiling(minXY.Y - .5F));

                                int right  = (int)extents.X;
                                int bottom = (int)extents.Y;
                                int left   = (int)extents.Z;
                                int top    = (int)extents.W;

                                extents = Vector4.Clamp(extents, Vector4.Zero, maxSource);

                                int maxX = (int)extents.X;
                                int maxY = (int)extents.Y;
                                int minX = (int)extents.Z;
                                int minY = (int)extents.W;

                                if (minX == maxX || minY == maxY)
                                {
                                    continue;
                                }

                                // It appears these have to be calculated on-the-fly.
                                // Precalculating transformed weights would require prior knowledge of every transformed pixel location
                                // since they can be at sub-pixel positions on both axis.
                                // I've optimized where I can but am always open to suggestions.
                                if (yScale > 1 && xScale > 1)
                                {
                                    CalculateWeightsDown(
                                        top,
                                        bottom,
                                        minY,
                                        maxY,
                                        point.Y,
                                        sampler,
                                        yScale,
                                        ref ySpanRef,
                                        yLength);

                                    CalculateWeightsDown(
                                        left,
                                        right,
                                        minX,
                                        maxX,
                                        point.X,
                                        sampler,
                                        xScale,
                                        ref xSpanRef,
                                        xLength);
                                }
                                else
                                {
                                    CalculateWeightsScaleUp(minY, maxY, point.Y, sampler, ref ySpanRef);
                                    CalculateWeightsScaleUp(minX, maxX, point.X, sampler, ref xSpanRef);
                                }

                                // Now multiply the results against the offsets
                                Vector4 sum = Vector4.Zero;
                                for (int yy = 0, j = minY; j <= maxY; j++, yy++)
                                {
                                    float yWeight = Unsafe.Add(ref ySpanRef, yy);

                                    for (int xx = 0, i = minX; i <= maxX; i++, xx++)
                                    {
                                        float xWeight = Unsafe.Add(ref xSpanRef, xx);

                                        // Values are first premultiplied to prevent darkening of edge pixels
                                        var current = source[i, j].ToVector4();
                                        Vector4Utils.Premultiply(ref current);
                                        sum += current * xWeight * yWeight;
                                    }
                                }

                                ref TPixel dest = ref Unsafe.Add(ref destRowRef, x);

                                // Reverse the premultiplication
                                Vector4Utils.UnPremultiply(ref sum);
                                dest.FromVector4(sum);
                            }
Ejemplo n.º 25
0
        /// <inheritdoc/>
        protected override void OnFrameApply(
            ImageFrame <TPixel> source,
            ImageFrame <TPixel> destination,
            Rectangle sourceRectangle,
            Configuration configuration)
        {
            int height = this.TargetDimensions.Height;
            int width  = this.TargetDimensions.Width;

            Rectangle sourceBounds = source.Bounds();
            var       targetBounds = new Rectangle(0, 0, width, height);

            // Since could potentially be resizing the canvas we might need to re-calculate the matrix
            Matrix3x2 matrix = this.GetProcessingMatrix(sourceBounds, targetBounds);

            // Convert from screen to world space.
            Matrix3x2.Invert(matrix, out matrix);

            if (this.Sampler is NearestNeighborResampler)
            {
                Parallel.For(
                    0,
                    height,
                    configuration.ParallelOptions,
                    y =>
                {
                    Span <TPixel> destRow = destination.GetPixelRowSpan(y);

                    for (int x = 0; x < width; x++)
                    {
                        var point = Point.Transform(new Point(x, y), matrix);
                        if (sourceBounds.Contains(point.X, point.Y))
                        {
                            destRow[x] = source[point.X, point.Y];
                        }
                    }
                });

                return;
            }

            int maxSourceX = source.Width - 1;
            int maxSourceY = source.Height - 1;

            (float radius, float scale, float ratio)xRadiusScale = this.GetSamplingRadius(source.Width, destination.Width);
            (float radius, float scale, float ratio)yRadiusScale = this.GetSamplingRadius(source.Height, destination.Height);
            float      xScale    = xRadiusScale.scale;
            float      yScale    = yRadiusScale.scale;
            var        radius    = new Vector2(xRadiusScale.radius, yRadiusScale.radius);
            IResampler sampler   = this.Sampler;
            var        maxSource = new Vector4(maxSourceX, maxSourceY, maxSourceX, maxSourceY);
            int        xLength   = (int)MathF.Ceiling((radius.X * 2) + 2);
            int        yLength   = (int)MathF.Ceiling((radius.Y * 2) + 2);

            MemoryManager memoryManager = configuration.MemoryManager;

            using (Buffer2D <float> yBuffer = memoryManager.Allocate2D <float>(yLength, height))
                using (Buffer2D <float> xBuffer = memoryManager.Allocate2D <float>(xLength, height))
                {
                    Parallel.For(
                        0,
                        height,
                        configuration.ParallelOptions,
                        y =>
                    {
                        ref TPixel destRowRef = ref MemoryMarshal.GetReference(destination.GetPixelRowSpan(y));
                        ref float ySpanRef    = ref MemoryMarshal.GetReference(yBuffer.GetRowSpan(y));
                        ref float xSpanRef    = ref MemoryMarshal.GetReference(xBuffer.GetRowSpan(y));
Ejemplo n.º 26
0
 public bool InvertBenchmark() => Matrix3x2.Invert(Matrix3x2.Identity, out Matrix3x2 result);
Ejemplo n.º 27
0
 public static Matrix3x2 Invert(this Matrix3x2 matrix)
 {
     return(Matrix3x2.Invert(matrix));
 }
Ejemplo n.º 28
0
 public Vector2 InvertTransformPoint(Matrix3x2 matrix, Vector2 point)
 {
     matrix.Invert();
     return(Matrix3x2.TransformPoint(matrix, point));
 }
Ejemplo n.º 29
0
            /// <summary>
            ///     Gets the tile at the location given.
            /// </summary>
            /// <param name="location">The location.</param>
            /// <returns></returns>
            private TileBase GetTileOver(Vector2 location)
            {
                Dictionary <Tile, IGraphicsPath> tilePaths = new Dictionary <Tile, IGraphicsPath>();

                try
                {
                    Matrix3x2 inverseViewMatrix = Controller.View.InverseViewMatrix;

                    IEnumerable <TileBase> tiles = Controller.Tiles;
                    foreach (TileBase tile in tiles)
                    {
                        IGraphicsPath path;
                        bool          disposePath = false;

                        TileInstance tileInstance;
                        Tile         rawTile = tile as Tile;
                        if (rawTile != null)
                        {
                            path = new GDIGraphics.GraphicsPath();
                            rawTile.PopulateGraphicsPath(path);
                            tilePaths.Add(rawTile, path);
                        }
                        else if ((tileInstance = tile as TileInstance) != null)
                        {
                            if (!tilePaths.TryGetValue(tileInstance.Tile, out path))
                            {
                                path = new GDIGraphics.GraphicsPath();
                                tileInstance.Tile.PopulateGraphicsPath(path);
                                tilePaths.Add(tileInstance.Tile, path);
                            }
                            Debug.Assert(path != null, "path != null");
                        }
                        else
                        {
                            disposePath = true;
                            path        = new GDIGraphics.GraphicsPath();
                            tile.PopulateGraphicsPath(path);
                        }

                        using (disposePath ? path : null)
                        {
                            Matrix3x2 tranform;
                            if (Matrix3x2.Invert(tile.Transform, out tranform) &&
                                path.ContainsPoint(location, inverseViewMatrix * tranform))
                            {
                                return(tile);
                            }
                        }
                    }
                }
                finally
                {
                    foreach (IGraphicsPath path in tilePaths.Values)
                    {
                        Debug.Assert(path != null, "path != null");
                        path.Dispose();
                    }
                }

                Debug.Fail("There should be a tile");
                return(null);
            }
Ejemplo n.º 30
0
 static Matrix3x2 Inverse(Matrix3x2 m)
 {
     Matrix3x2.Invert(m, out var r);
     return(r);
 }