TransformVectors() public method

public TransformVectors ( Point pts ) : void
pts Point
return void
Example #1
0
        internal static float ConvertSweepAngle(float sweepAngle, float startAngle, SpatialTransform transform, CoordinateSystem targetSystem)
        {
            PointF x = new PointF(100, 0);

            PointF[] startVector = new PointF[] { x };
            Matrix   rotation    = new Matrix();

            rotation.Rotate(startAngle);
            rotation.TransformVectors(startVector);

            PointF[] sweepVector = (PointF[])startVector.Clone();
            rotation.Reset();
            rotation.Rotate(sweepAngle);
            rotation.TransformVectors(sweepVector);
            rotation.Dispose();

            SizeF startVectorTransformed, sweepVectorTransformed;

            if (targetSystem == Graphics.CoordinateSystem.Destination)
            {
                startVectorTransformed = transform.ConvertToDestination(new SizeF(startVector[0]));
                sweepVectorTransformed = transform.ConvertToDestination(new SizeF(sweepVector[0]));
            }
            else
            {
                startVectorTransformed = transform.ConvertToSource(new SizeF(startVector[0]));
                sweepVectorTransformed = transform.ConvertToSource(new SizeF(sweepVector[0]));
            }

            // simply return the angle between the start and sweep angle, in the target system.
            return((int)Math.Round(Vector.SubtendedAngle(sweepVectorTransformed.ToPointF(), PointF.Empty, startVectorTransformed.ToPointF())));
        }
Example #2
0
        partial void TransformVectorsImpl(PointF [] pts)
        {
            var tmp = ToSDDPoints(pts);

            t.TransformVectors(tmp);
            Copy(tmp, pts);
        }
        // Draw the graph.
        private void DrawGraph(Graphics gr)
        {
            // Map to turn right-side up and center at the origin.
            const float wxmin = -10;
            const float wymin = -10;
            const float wxmax = 10;
            const float wymax = 10;
            RectangleF rect = new RectangleF(wxmin, wymin, wxmax - wxmin, wymax - wymin);
            PointF[] pts =
            {
                new PointF(0, graphPictureBox.ClientSize.Height),
                new PointF(graphPictureBox.ClientSize.Width, graphPictureBox.ClientSize.Height),
                new PointF(0, 0),
            };
            Matrix transform = new Matrix(rect, pts);
            gr.Transform = transform;

            // See how far it is between horizontal pixels in world coordinates.
            pts = new PointF[] { new PointF(1, 0) };
            transform.Invert();
            transform.TransformVectors(pts);
            float dx = pts[0].X;

            // Generate points on the curve.
            List<PointF> points = new List<PointF>();
            for (float x = wxmin; x <= wxmax; x += dx)
                points.Add(new PointF(x, TheFunction(x)));

            // Use a thin pen.
            using (Pen thin_pen = new Pen(Color.Gray, 0))
            {
                // Draw the coordinate axes.
                gr.DrawLine(thin_pen, wxmin, 0, wxmax, 0);
                gr.DrawLine(thin_pen, 0, wymin, 0, wymax);
                for (float x = wxmin; x <= wxmax; x++)
                    gr.DrawLine(thin_pen, x, -0.5f, x, 0.5f);
                for (float y = wymin; y <= wymax; y++)
                    gr.DrawLine(thin_pen, -0.5f, y, 0.5f, y);

                // Draw the graph.
                thin_pen.Color = Color.Red;
                //thin_pen.Color = Color.Black;
                gr.DrawLines(thin_pen, points.ToArray());
            }
        }
Example #4
0
        internal static float ConvertStartAngle(float angle, SpatialTransform transform, CoordinateSystem targetSystem)
        {
            PointF xVector = new PointF(100, 0);

            Matrix rotation = new Matrix();

            PointF[] angleVector = new PointF[] { xVector };
            rotation.Rotate(angle);
            rotation.TransformVectors(angleVector);
            rotation.Dispose();

            SizeF xVectorTransformed, angleVectorTransformed;

            if (targetSystem == Graphics.CoordinateSystem.Destination)
            {
                xVectorTransformed     = transform.ConvertToDestination(new SizeF(xVector));
                angleVectorTransformed = transform.ConvertToDestination(new SizeF(angleVector[0]));
            }
            else
            {
                xVectorTransformed     = transform.ConvertToSource(new SizeF(xVector));
                angleVectorTransformed = transform.ConvertToSource(new SizeF(angleVector[0]));
            }

            float xRotationOffset =
                (int)Math.Round(Vector.SubtendedAngle(xVectorTransformed.ToPointF(), PointF.Empty, xVector));

            float angleTransformed =
                (int)Math.Round(Vector.SubtendedAngle(angleVectorTransformed.ToPointF(), PointF.Empty, xVectorTransformed.ToPointF()));

            // have to figure out where x-axis moved to and then return the difference between the angle
            // and the x-axis, where both are in 'target' coordinates.
            float returnAngle = angleTransformed + xRotationOffset;

            if (returnAngle < 0)
            {
                returnAngle += 360;
            }

            return(returnAngle);
        }
Example #5
0
 public static PointF MatrixByVector(Matrix M, PointF P)
 {
     PointFSingleArray[0] = P;
     M.TransformVectors(PointFSingleArray);
     return PointFSingleArray[0];
 }
            private void updateImage()
            {
                List<PointF> boundingBox = null;
                List<PointF> hull = null;
                mOriginalImageReference = BrickLibrary.Instance.getImage(mPartNumber, ref boundingBox, ref hull);
                // check if the image is not in the library, create one
                if (mOriginalImageReference == null)
                {
                    // add a default image in the library and ask it again
                    BrickLibrary.Instance.AddUnknownBrick(mPartNumber, (int)(mDisplayArea.Width), (int)(mDisplayArea.Height));
                    mOriginalImageReference = BrickLibrary.Instance.getImage(mPartNumber, ref boundingBox, ref hull);
                }
                // normally now, we should have an image
                // transform the bounding box of the part
                PointF[] boundingPoints = boundingBox.ToArray();
                Matrix rotation = new Matrix();
                rotation.Rotate(mOrientation);
                rotation.TransformVectors(boundingPoints);

                // get the min, max and the size of the bounding box
                PointF boundingMin = new PointF();
                PointF boundingMax = new PointF();
                PointF boundingSize = sGetMinMaxAndSize(boundingPoints, ref boundingMin, ref boundingMax);

                // store computationnal variable for optimization
                const float PIXEL_TO_STUD_RATIO = 1.0f / NUM_PIXEL_PER_STUD_FOR_BRICKS;

                // transform the hull to get the selection area
                PointF[] hullArray = hull.ToArray();
                rotation.TransformVectors(hullArray);

                // check if this picture has a specific hull
                if (hull != boundingBox)
                {
                    // get the bounding size from the hull
                    PointF hullMin = new PointF();
                    PointF hullMax = new PointF();
                    PointF hullSize = sGetMinMaxAndSize(hullArray, ref hullMin, ref hullMax);

                    // compute the offset between the hull and the normal bounding box
                    PointF deltaMin = new PointF(boundingMin.X - hullMin.X, boundingMin.Y - hullMin.Y);
                    PointF deltaMax = new PointF(boundingMax.X - hullMax.X, boundingMax.Y - hullMax.Y);
                    mOffsetFromOriginalImage = new PointF((deltaMax.X + deltaMin.X) * PIXEL_TO_STUD_RATIO * 0.5f,
                                                          (deltaMax.Y + deltaMin.Y) * PIXEL_TO_STUD_RATIO * 0.5f);

                    // overwrite the bounding size and min with the hull ones which are more precise
                    boundingSize = hullSize;
                    boundingMin = hullMin;
                }
                else
                {
                    mOffsetFromOriginalImage = new PointF(0, 0);
                }

                // set the size of the display area with the new computed bounding size, and recompute the snap to grid offset
                mDisplayArea.Width = boundingSize.X * PIXEL_TO_STUD_RATIO;
                mDisplayArea.Height = boundingSize.Y * PIXEL_TO_STUD_RATIO;
                mTopLeftCornerInPixel = new PointF(-boundingMin.X, -boundingMin.Y);

                // adjust the selection area after computing the new display area size to have a correct center
                // first we add the translation of the top left corner in pixel to the hull point already in pixel
                // then convert the pixel to studs, and finally add the top left corner in stud
                Matrix translation = new Matrix();
                translation.Translate(mTopLeftCornerInPixel.X, mTopLeftCornerInPixel.Y);
                translation.Scale(PIXEL_TO_STUD_RATIO, PIXEL_TO_STUD_RATIO, MatrixOrder.Append);
                translation.Translate(Center.X - (mDisplayArea.Width * 0.5f), Center.Y - (mDisplayArea.Height * 0.5f), MatrixOrder.Append);
                translation.TransformPoints(hullArray);

                // create the new selection area from the rotated hull
                mSelectionArea = new Tools.Polygon(hullArray);

                // clear the new images array for all the levels
                clearMipmapImages(0, mMipmapImages.Length - 1);
            }
Example #7
0
        //take a world vector and make it a relative vector
        public Vector WorldToRelative(Vector world)
        {
            Matrix mat = new Matrix();
            PointF[] vectors = new PointF[1];

            vectors[0].X = world.X;
            vectors[0].Y = world.Y;

            mat.Rotate(-m_angle / (float)Math.PI * 180.0f);
            mat.TransformVectors(vectors);

            return new Vector(vectors[0].X, vectors[0].Y);
        }
Example #8
0
            public void SetSteeringAngle(float newAngle)
            {
                Matrix mat = new Matrix();
                PointF[] vectors = new PointF[2];

                //foward vector
                vectors[0].X = 0;
                vectors[0].Y = 1;
                //side vector
                vectors[1].X = -1;
                vectors[1].Y = 0;

                mat.Rotate(newAngle / (float)Math.PI * 180.0f);
                mat.TransformVectors(vectors);

                m_forwardAxis = new Vector(vectors[0].X, vectors[0].Y);
                m_sideAxis = new Vector(vectors[1].X, vectors[1].Y);
            }
Example #9
0
		internal static float ConvertSweepAngle(float sweepAngle, float startAngle, SpatialTransform transform, CoordinateSystem targetSystem)
		{
			PointF x = new PointF(100, 0);

			PointF[] startVector = new PointF[] { x };
			Matrix rotation = new Matrix();
			rotation.Rotate(startAngle);
			rotation.TransformVectors(startVector);

			PointF[] sweepVector = (PointF[])startVector.Clone();
			rotation.Reset();
			rotation.Rotate(sweepAngle);
			rotation.TransformVectors(sweepVector);
			rotation.Dispose();

			SizeF startVectorTransformed, sweepVectorTransformed;
			if (targetSystem == Graphics.CoordinateSystem.Destination)
			{
				startVectorTransformed = transform.ConvertToDestination(new SizeF(startVector[0]));
				sweepVectorTransformed = transform.ConvertToDestination(new SizeF(sweepVector[0]));
			}
			else
			{
				startVectorTransformed = transform.ConvertToSource(new SizeF(startVector[0]));
				sweepVectorTransformed = transform.ConvertToSource(new SizeF(sweepVector[0]));
			}

			// simply return the angle between the start and sweep angle, in the target system.
			return (int)Math.Round(Vector.SubtendedAngle(sweepVectorTransformed.ToPointF(), PointF.Empty, startVectorTransformed.ToPointF()));
		}
 public void rotate(Matrix matrix)
 {
     PointF[] vector = { mLocalAttachOffsetFromCenter };
     matrix.TransformVectors(vector);
     mWorldAttachOffsetFromCenter = vector[0];
 }
Example #11
0
 // Transform X-distance via a transform.
 protected float TransformDistance(float distance, Matrix xform)
 {
     PointF[] vectors = { new PointF(distance, 0) };
     xform.TransformVectors(vectors);
     return (float) Math.Sqrt(vectors[0].X * vectors[0].X + vectors[0].Y * vectors[0].Y);
 }
Example #12
0
        /// <summary>
        /// Draw some debug information like the chain bones
        /// </summary>
        /// <param name="g">the graphic context in which draw</param>
        /// <param name="areaInStud">the area in which draw</param>
        /// <param name="scalePixelPerStud">the current scale</param>
        public void draw(Graphics g, RectangleF areaInStud, double scalePixelPerStud)
        {
            int lastIndex = mBoneList.Count - 1;

            // draw the bones
            for (int i = 0; i < lastIndex; i++)
            {
                IKSolver.Bone_2D_CCD firstBone = mBoneList[i];
                IKSolver.Bone_2D_CCD nextBone = mBoneList[i+1];

                g.DrawLine(Pens.Black, (float)((firstBone.worldX - areaInStud.Left) * scalePixelPerStud),
                            (float)((-firstBone.worldY - areaInStud.Top) * scalePixelPerStud),
                            (float)((nextBone.worldX - areaInStud.Left) * scalePixelPerStud),
                            (float)((-nextBone.worldY - areaInStud.Top) * scalePixelPerStud));
            }

            // the last bone vector
            LayerBrick.Brick.ConnectionPoint endConnection = mBoneList[lastIndex].connectionPoint;
            if (!endConnection.IsFree)
            {
                // rotate the second target vector according to the orientation of the snapped connection
                PointF[] translation = { mLastBoneVector };
                Matrix rotation = new Matrix();
                rotation.Rotate(endConnection.ConnectedBrick.Orientation + endConnection.ConnectionLink.Angle + 180);
                rotation.TransformVectors(translation);

                // draw the translation
                IKSolver.Bone_2D_CCD lastBone = mBoneList[mBoneList.Count - 1];
                float endX = (float)(lastBone.worldX - areaInStud.Left);
                float endY = (float)(-lastBone.worldY - areaInStud.Top);
                g.DrawLine(Pens.Green, endX * (float)scalePixelPerStud, endY * (float)scalePixelPerStud,
                            (endX + translation[0].X) * (float)scalePixelPerStud,
                            (endY + translation[0].Y) * (float)scalePixelPerStud);
            }
        }
Example #13
0
        protected void rotate(Layer.LayerItem item, Matrix rotation, float rotationAngle, bool adjustPivot)
        {
            // get the pivot point of the part before the rotation
            PointF pivot = item.Pivot;

            // change the orientation of the picture
            item.Orientation = (item.Orientation + rotationAngle);

            // for some items partially attached, we may don't want to adjust the pivot
            if (adjustPivot)
            {
                // adjust the position of the pivot for a group of items
                if (mItems.Count > 1)
                {
                    PointF[] points = { new PointF(pivot.X - mCenter.X, pivot.Y - mCenter.Y) };
                    rotation.TransformVectors(points);
                    // assign the new position
                    pivot.X = mCenter.X + points[0].X;
                    pivot.Y = mCenter.Y + points[0].Y;
                }

                // assign the new pivot position after rotation
                item.Pivot = pivot;
            }
        }
 SizeF Transform(Matrix m, SizeF s)
 {
     PointF[] ps = new PointF[] { new PointF(s.Width, s.Height) };
     m.TransformVectors(ps);
     return new SizeF(ps[0].X, ps[0].Y);
 }
Example #15
0
		public void TransformVectors  ()
		{
			Matrix matrix = new Matrix (2, 4, 6, 8, 10, 12);
			PointF [] pointsF = new PointF [] {new PointF (2, 4), new PointF (4, 8)};
			matrix.TransformVectors (pointsF);
						
			Assert.AreEqual (28, pointsF[0].X, "N#1");
			Assert.AreEqual (40, pointsF[0].Y, "N#2");
			Assert.AreEqual (56, pointsF[1].X, "N#3");
			Assert.AreEqual (80, pointsF[1].Y, "N#4");
			
			Point [] points = new Point [] {new Point (2, 4), new Point (4, 8)};
			matrix.TransformVectors (points);
			Assert.AreEqual (28, pointsF[0].X, "N#5");
			Assert.AreEqual (40, pointsF[0].Y, "N#6");
			Assert.AreEqual (56, pointsF[1].X, "N#7");
			Assert.AreEqual (80, pointsF[1].Y, "N#8");
		}
        public bool RotateImage( string sourceImagePath, int rotationDegree )
        {
            try
            {
                string fileExt = Path.GetExtension( sourceImagePath ).ToLowerInvariant().Trim( '.' );
                // create file name of the temp file
                string tempFilePath = getTempFileName( sourceImagePath, fileExt );

                using( Bitmap inputImage = new Bitmap( sourceImagePath ) )
                {
                    EncoderParameters encParams = null;
                    var encoder = getEncoder( fileExt, out encParams );

                    // calculate width and height of the new image
                    float iW = (float)inputImage.Width;
                    float iH = (float)inputImage.Height;

                    Matrix whRotation = new Matrix();
                    whRotation.Rotate( rotationDegree );
                    // rotate every vertex of our "image rectangle"
                    var tmpDims = new PointF[] { new PointF(0,0), new PointF( iW, 0 ), new PointF( iW, iH ), new PointF( 0, iH ) };
                    whRotation.TransformVectors( tmpDims );
                    // find extends
                    iW = Math.Abs( tmpDims.Max( x => x.X ) - tmpDims.Min( x => x.X ) );
                    iH = Math.Abs( tmpDims.Max( x => x.Y ) - tmpDims.Min( x => x.Y ) );

                    using( Bitmap tempBmp = new Bitmap( (int)Math.Ceiling( iW ), (int)Math.Ceiling( iH ) ) )
                    {
                        // rotate image
                        tempBmp.SetResolution( inputImage.HorizontalResolution, inputImage.VerticalResolution );
                        using( Graphics g = Graphics.FromImage( tempBmp ) )
                        {
                            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
                            // rotate at the center
                            g.TranslateTransform( tempBmp.Width/2, tempBmp.Height/2 );
                            g.RotateTransform( rotationDegree );
                            g.TranslateTransform( -tempBmp.Width / 2, -tempBmp.Height / 2 );
                            g.DrawImage( inputImage,
                                new Point( ( tempBmp.Width - inputImage.Width ) / 2,
                                    ( tempBmp.Height - inputImage.Height ) / 2 ) );
                        }
                        tempBmp.Save( tempFilePath, encoder, encParams );
                    }
                }
                // now replace images
                File.Delete( sourceImagePath );
                File.Move( tempFilePath, sourceImagePath );
                return true;
            }
            catch
            {
                return false;
            }
        }
            private void updateBitmap(bool redrawImage)
            {
                // create a bitmap if the text is not empty
                if (mText != "")
                {
                    // create a font to mesure the text
                    Font textFont = new Font(mTextFont.FontFamily, mTextFont.Size, mTextFont.Style);

                    Graphics graphics = Graphics.FromImage(mImage);
                    SizeF textFontSize = graphics.MeasureString(mText, textFont);
                    float halfWidth = textFontSize.Width * 0.5f;
                    float halfHeight = textFontSize.Height * 0.5f;

                    Matrix rotation = new Matrix();
                    rotation.Rotate(mOrientation);
                    // compute the rotated corners
                    PointF[] corners = new PointF[] { new PointF(-halfWidth, -halfHeight), new PointF(-halfWidth, halfHeight), new PointF(halfWidth, halfHeight), new PointF(halfWidth, -halfHeight) };
                    rotation.TransformVectors(corners);

                    PointF min = corners[0];
                    PointF max = corners[0];
                    for (int i = 1; i < 4; ++i)
                    {
                        if (corners[i].X < min.X)
                            min.X = corners[i].X;
                        if (corners[i].Y < min.Y)
                            min.Y = corners[i].Y;
                        if (corners[i].X > max.X)
                            max.X = corners[i].X;
                        if (corners[i].Y > max.Y)
                            max.Y = corners[i].Y;
                    }
                    // adjust the display area and selection area
                    mDisplayArea.Width = Math.Abs(max.X - min.X);
                    mDisplayArea.Height = Math.Abs(max.Y - min.Y);

                    // adjust the selection area (after adjusting the display area such as the center properties is correct)
                    Matrix translation = new Matrix();
                    translation.Translate(Center.X, Center.Y);
                    translation.TransformPoints(corners);

                    // then create the new selection area
                    mSelectionArea = new Tools.Polygon(corners);

                    if (redrawImage)
                    {
                        // now create a scaled font from the current one, to avoid aliasing
                        Font scaledTextFont = new Font(mTextFont.FontFamily, mTextFont.Size * ANTI_ALIASING_FONT_SCALE, mTextFont.Style);
                        mImage = new Bitmap(mImage, new Size((int)(textFontSize.Width * ANTI_ALIASING_FONT_SCALE), (int)(textFontSize.Height * ANTI_ALIASING_FONT_SCALE)));

                        // compute the position where to draw according to the alignment (if centered == 0)
                        float posx = 0;
                        if (this.TextAlignment == StringAlignment.Far)
                            posx = halfWidth;
                        else if (this.TextAlignment == StringAlignment.Near)
                            posx = -halfWidth;

                        graphics = Graphics.FromImage(mImage);
                        rotation = new Matrix();
                        rotation.Translate(mImage.Width / 2, mImage.Height / 2, MatrixOrder.Append);
                        graphics.Transform = rotation;
                        graphics.Clear(Color.Transparent);
                        graphics.SmoothingMode = SmoothingMode.HighQuality;
                        graphics.DrawString(mText, scaledTextFont, mTextBrush, posx * ANTI_ALIASING_FONT_SCALE, 0, mTextStringFormat);
                        graphics.Flush();
                    }
                }
            }
            /// <summary>
            /// update the image used to draw the mesurement of the ruler correctly oriented
            /// The image is drawn with the current selected unit.
            /// This method should be called when the mesurement unit change or when one of the
            /// points change
            /// </summary>
            protected void updateMesurementImage()
            {
                // get the mesured distance in the current unit
                string distanceAsString = mMeasuredDistance.ToString("N2", mDisplayUnit);

                // draw the size
                Graphics graphics = Graphics.FromImage(mMeasureImage);
                SizeF textFontSize = graphics.MeasureString(distanceAsString, mMeasureFont);
                int width = (int)textFontSize.Width;
                int height = (int)textFontSize.Height;

                // after setting the text size, call the function to compute the scale
                mMeasureTextSizeInPixel.X = width;
                mMeasureTextSizeInPixel.Y = height;
                updateMesurementImageScale(MainForm.Instance.MapViewScale);

                // create an array with the 4 corner of the text (actually 3 if you exclude the origin)
                // and rotate them according to the orientation
                Matrix rotation = new Matrix();
                rotation.Rotate(mOrientation);
                Point[] points = { new Point(width, 0), new Point(0, height), new Point(width, height) };
                rotation.TransformVectors(points);

                // search the min and max of all the rotated corner to compute the necessary size of the bitmap
                Point min = new Point(0, 0);
                Point max = new Point(0, 0);
                for (int i = 0; i < 3; ++i)
                {
                    if (points[i].X < min.X)
                        min.X = points[i].X;
                    if (points[i].Y < min.Y)
                        min.Y = points[i].Y;
                    if (points[i].X > max.X)
                        max.X = points[i].X;
                    if (points[i].Y > max.Y)
                        max.Y = points[i].Y;
                }

                // create the bitmap and draw the text inside
                mMeasureImage = new Bitmap(mMeasureImage, new Size(Math.Abs(max.X - min.X), Math.Abs(max.Y - min.Y)));
                graphics = Graphics.FromImage(mMeasureImage);
                rotation.Translate(mMeasureImage.Width / 2, mMeasureImage.Height / 2, MatrixOrder.Append);
                graphics.Transform = rotation;
                graphics.Clear(Color.Transparent);
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.DrawString(distanceAsString, mMeasureFont, mMeasureBrush, 0, 0, mMeasureStringFormat);
                graphics.Flush();
            }
            private void updateConnectionPosition()
            {
                if (mConnectionPoints != null)
                {
                    List<PointF> pointList = BrickLibrary.Instance.getConnectionPositionList(mPartNumber);
                    if (pointList != null)
                    {
                        Matrix rotation = new Matrix();
                        rotation.Rotate(mOrientation);
                        PointF[] pointArray = pointList.ToArray();
                        rotation.TransformVectors(pointArray);

                        PointF center = this.Center;
                        center.X += mOffsetFromOriginalImage.X;
                        center.Y += mOffsetFromOriginalImage.Y;

                        // in this function we assume the two arrays have the same size,
                        // i.e. mConnectionPoints.Count == pointArray.Length
                        // during the loading code we have created the mConnectionPoints with the
                        // same size as the part library.
                        for (int i = 0; i < pointList.Count; ++i)
                        {
                            mConnectionPoints[i].setPositionReservedForBrick(center.X + pointArray[i].X,
                                                                            center.Y + pointArray[i].Y);
                        }
                    }
                }
            }
Example #20
0
		internal static float ConvertStartAngle(float angle, SpatialTransform transform, CoordinateSystem targetSystem)
		{
			PointF xVector = new PointF(100, 0);

			Matrix rotation = new Matrix();
			PointF[] angleVector = new PointF[] { xVector };
			rotation.Rotate(angle);
			rotation.TransformVectors(angleVector);
			rotation.Dispose();

			SizeF xVectorTransformed, angleVectorTransformed;
			if (targetSystem == Graphics.CoordinateSystem.Destination)
			{
				xVectorTransformed = transform.ConvertToDestination(new SizeF(xVector));
				angleVectorTransformed = transform.ConvertToDestination(new SizeF(angleVector[0]));
			}
			else
			{
				xVectorTransformed = transform.ConvertToSource(new SizeF(xVector));
				angleVectorTransformed = transform.ConvertToSource(new SizeF(angleVector[0]));
			}

			float xRotationOffset =
				(int)Math.Round(Vector.SubtendedAngle(xVectorTransformed.ToPointF(), PointF.Empty, xVector));

			float angleTransformed =
				(int)Math.Round(Vector.SubtendedAngle(angleVectorTransformed.ToPointF(), PointF.Empty, xVectorTransformed.ToPointF()));

			// have to figure out where x-axis moved to and then return the difference between the angle
			// and the x-axis, where both are in 'target' coordinates.
			float returnAngle = angleTransformed + xRotationOffset;
			if (returnAngle < 0)
				returnAngle += 360;

			return returnAngle;
		}
Example #21
0
        //take a relative vector and make it a world vector
        public Vector RelativeToWorld(Vector relative)
        {
            Matrix mat = new Matrix();
            PointF[] vectors = new PointF[1];

            vectors[0].X = relative.X;
            vectors[0].Y = relative.Y;

            mat.Rotate(m_angle / (float)Math.PI * 180.0f);
            mat.TransformVectors(vectors);

            return new Vector(vectors[0].X, vectors[0].Y);
        }
Example #22
0
        /// <summary>
        /// Create a flex chain from a set of brick given a starting brick. From the free connection point
        /// of this starting brick go through all the linked connection points while the brick only have
        /// two connections. If the brick has only one or more than 2 connection (like a joint or crossing)
        /// we stop the chain.
        /// </summary>
        /// <param name="trackList">A set of track hopefully connected together, and hopefully containing flex track</param>
        /// <param name="grabbedTrack">The part which will try to reach the target. It should be part of the list.</param>
        /// <param name="currentFirstConnection">The first connection from which to start, which can be null and belongs to the grabbed track</param>
        public void ceateFlexChain(List<Layer.LayerItem> trackList, LayerBrick.Brick grabbedTrack, LayerBrick.Brick.ConnectionPoint currentFirstConnection)
        {
            // init all the arrays
            int boneCount = trackList.Count;
            mBoneList = new List<IKSolver.Bone_2D_CCD>(boneCount);
            mFlexChainList = new List<ChainLink>(boneCount * 2);
            mBricksInTheFlexChain = new List<Layer.LayerItem>(boneCount);

            // start to iterate from the grabbed track
            LayerBrick.Brick currentBrick = grabbedTrack;
            ChainLink hingedLink = null;
            addNewBone(currentFirstConnection, grabbedTrack, 0.0);
            // continue to iterate until we reach the end (no current brick) or the end of the selection
            // and continue only if the chain is made with track that exclusively has 2 connections to make a chain
            // (or one for the first iteration).
            while ((currentBrick != null) && trackList.Contains(currentBrick) &&
                    ((currentFirstConnection == null) || (currentBrick.ConnectionPoints.Count == 2)))
            {
                // get the other connection on the current brick
                int secondIndex = (currentBrick.ConnectionPoints[0] == currentFirstConnection) ? 1 : 0;
                LayerBrick.Brick.ConnectionPoint currentSecondConnection = currentBrick.ConnectionPoints[secondIndex];
                LayerBrick.Brick nextBrick = currentSecondConnection.ConnectedBrick;
                LayerBrick.Brick.ConnectionPoint nextFirstConnection = currentSecondConnection.ConnectionLink;

                // add the two connections of the brick
                ChainLink link = new ChainLink(nextFirstConnection, currentSecondConnection);
                mFlexChainList.Insert(0, link);

                // check if the connection can rotate (if it is an hinge)
                float hingeAngle = BrickLibrary.Instance.getConnexionHingeAngle(currentSecondConnection.Type);
                if (hingeAngle != 0.0f)
                {
                    // advance the hinge conncetion
                    hingedLink = link;
                    // add the link in the list
                    addNewBone(currentSecondConnection, currentBrick, hingeAngle);
                    // compute the current angle between the hinge connection and set it to the current bone
                    // to do that we use the current angle between the connected brick and remove the static angle between them
                    // to only get the flexible angle.
                    float angleInDegree = 0.0f;
                    if (nextBrick != null)
                        angleInDegree = simplifyAngle(nextBrick.Orientation - currentBrick.Orientation - link.mAngleBetween);
                    mBoneList[0].localAngleInRad = angleInDegree * (Math.PI / 180);

                    // save the initial static cumulative orientation: start with the orientation of the root brick
                    // if the hinge is connected to a brick, otherwise, if the hinge is free (connected to the world)
                    // use the orientation of the hinge brick.
                    // we set the value several time in the loop, in order to set it with the brick directly
                    // connected to the last hinge in the chain
                    if (nextBrick != null)
                        mInitialStaticCumulativeOrientation = -nextBrick.Orientation;
                    else
                        mInitialStaticCumulativeOrientation = -currentBrick.Orientation;
                }

                // advance to the next link
                currentBrick = nextBrick;
                currentFirstConnection = nextFirstConnection;

                // check if the track is not a loop, otherwise we will have an infinite loop.
                // but don't add the test in the while because the first iteration must pass
                if (currentBrick == grabbedTrack)
                    break;
            }

            // store the root hinge connection index (the last hinge found is the flexible root)
            if (hingedLink != null)
                mRootHingedLinkIndex = mFlexChainList.IndexOf(hingedLink);

            // compute the last bone vector if there is enough bones
            if (mBoneList.Count > 2)
            {
                int lastIndex = mBoneList.Count - 1;
                int beforeLastIndex = lastIndex - 1;
                mLastBoneVector = new PointF((float)(mBoneList[beforeLastIndex].worldX - mBoneList[lastIndex].worldX),
                                            (float)(mBoneList[beforeLastIndex].worldY - mBoneList[lastIndex].worldY));
                // rotate the vector such as to compute it for a null angle
                // but if the last bone doesn't have connection, it can never snap, so the last bone will never be used
                if (mBoneList[lastIndex].connectionPoint != null)
                {
                    PointF[] translation = { mLastBoneVector };
                    Matrix rotation = new Matrix();
                    rotation.Rotate(mBoneList[lastIndex].connectionPoint.mMyBrick.Orientation);
                    rotation.TransformVectors(translation);
                    mLastBoneVector = translation[0];
                }
            }

            // add the current brick in the list of bricks, by not going further than the root brick
            LayerBrick.Brick.ConnectionPoint rootConnection = mFlexChainList[mRootHingedLinkIndex].mFirstConnection;
            if (rootConnection.mMyBrick != null)
                mBricksInTheFlexChain.Add(rootConnection.mMyBrick);
            for (int i = mRootHingedLinkIndex; i < mFlexChainList.Count; ++i)
                mBricksInTheFlexChain.Add(mFlexChainList[i].mSecondConnection.mMyBrick);
        }
 public static PointF sComputeLocalOffsetFromLayerItem(LayerBrick.Brick brick, PointF worldPositionInStud)
 {
     // get the brick pivot in world coordinate
     PointF brickPivot = brick.Pivot;
     // compute the offset from the brick center in world coordinate
     PointF offset = new PointF(worldPositionInStud.X - brickPivot.X, worldPositionInStud.Y - brickPivot.Y);
     // compute the rotation matrix of the brick in order to find the local offset
     Matrix matrix = new Matrix();
     matrix.Rotate(-brick.Orientation);
     PointF[] vector = { offset };
     matrix.TransformVectors(vector);
     // return the local offset
     return vector[0];
 }
Example #24
0
        /// <summary>
        /// Try to reach the specify target position with this chain
        /// </summary>
        /// <param name="targetInWorldStudCoord">the target position in world stud coord</param>
        /// <param name="targetConnection">If the end of the flex chain need to be connected to a connection, this parameter indicates which one, otherwise it is null</param>
        public void reachTarget(PointF targetInWorldStudCoord, LayerBrick.Brick.ConnectionPoint targetConnection)
        {
            // save the primary target
            mPrimaryTarget = targetInWorldStudCoord;

            // check if we need to compute a second target position
            mUseTwoTargets = (targetConnection != null);
            if (mUseTwoTargets)
            {
                // rotate the second target vector according to the orientation of the snapped connection
                PointF[] translation = { mLastBoneVector };
                Matrix rotation = new Matrix();
                rotation.Rotate(targetConnection.mMyBrick.Orientation + targetConnection.Angle + 180);
                rotation.TransformVectors(translation);

                // translate the target with the rotated vector for the second target
                mSecondaryTarget.X = targetInWorldStudCoord.X + translation[0].X;
                mSecondaryTarget.Y = targetInWorldStudCoord.Y + translation[0].Y;
            }

            // reset the status flag
            mCurrentUpdateStatus = IKSolver.CCDResult.Processing;

            // and call the update method
            update();
        }
Example #25
0
        private void createGroupImageRecursive(Brick group, List<Brick> parentGroups)
        {
            if (group.mGroupInfo.mGroupSubPartList.Count == 0)
                throw new Exception("The group is empty. The tag <SubPartList> cannot be empty.");

            // check if we have a cyclic group
            if (parentGroups.Contains(group))
                throw new Exception("Cyclic group detected. The group contains itself in its list or contains another group that contains it.");

            // use a temp list of transform to compute and store the transform of each sub part only for drawing purpose
            List<Matrix> subPartDrawingTransforms = new List<Matrix>(group.mGroupInfo.mGroupSubPartList.Count);

            // declare 4 variable to get the bounding box of the group part (in stud)
            float minX = float.MaxValue;
            float minY = float.MaxValue;
            float maxX = float.MinValue;
            float maxY = float.MinValue;
            // iterate on the bricks to compute the size of the image
            foreach (Brick.SubPart subPart in group.mGroupInfo.mGroupSubPartList)
            {
                // try to get the part from the library, otherwise add an unknown image
                if (!mBrickDictionary.TryGetValue(subPart.mSubPartNumber, out subPart.mSubPartBrick))
                    subPart.mSubPartBrick = AddUnknownBrick(subPart.mSubPartNumber, 32, 32);

                // check if the current sub part is a group not yet created in that case call the function recursively
                if ((subPart.mSubPartBrick.IsAGroup) && (subPart.mSubPartBrick.Image == null))
                {
                    List<Brick> newParentGroups = new List<Brick>(parentGroups);
                    newParentGroups.Add(group);
                    createGroupImageRecursive(subPart.mSubPartBrick, newParentGroups);
                }

                // create the drawing transform and add it to the list
                Matrix drawingTransform = new Matrix();
                subPartDrawingTransforms.Add(drawingTransform);

                // add the rotation to the transform
                drawingTransform.Rotate(subPart.mOrientation);
                // transform the bounding box (which is in pixel) after that the image is created otherwise the hull may be null
                PointF[] hullPoints = subPart.mSubPartBrick.mHull.ToArray();
                drawingTransform.TransformVectors(hullPoints);

                // get the local min and max for this sub part
                PointF hullMin = new PointF();
                PointF hullMax = new PointF();
                PointF hullHalfSize = LayerBrick.Brick.sGetMinMaxAndSize(hullPoints, ref hullMin, ref hullMax);
                hullHalfSize.X *= 0.5f;
                hullHalfSize.Y *= 0.5f;
                // compute the part translation in pixel
                float translateX = (subPart.mLocalTransformInStud.OffsetX * Layer.NUM_PIXEL_PER_STUD_FOR_BRICKS);
                float translateY = (subPart.mLocalTransformInStud.OffsetY * Layer.NUM_PIXEL_PER_STUD_FOR_BRICKS);
                // compute the hull min and max inside the whole group (so with the translation of the part)
                PointF hullMinInsideGroup = new PointF(translateX - hullHalfSize.X, translateY - hullHalfSize.Y);
                PointF hullMaxInsideGroup = new PointF(translateX + hullHalfSize.X, translateY + hullHalfSize.Y);
                // add the part transaltion to the transform for drawing.
                // The drawing transform want the top left corner of the image as a reference. So to compute it
                // we use the center position of the part inside the group (translateX) from which we remove the half size
                // of the part (hullHallSize.X) i.e. it is hullMinInsideGroup.X. But we also need to remove hullMin of the sub part
                // to but I don't know why. So now the translation of the sub part is relative to the XML origin of the group
                // but we will need to recentrate this, after finishing computing the whole size of the group, we can know where
                // is the origin of the group compare to the center of the group, but this will be added after this loop
                drawingTransform.Translate(hullMinInsideGroup.X - hullMin.X, hullMinInsideGroup.Y - hullMin.Y, MatrixOrder.Append);

                // check the local min and max with the global ones
                if (hullMinInsideGroup.X < minX)
                    minX = hullMinInsideGroup.X;
                if (hullMaxInsideGroup.X > maxX)
                    maxX = hullMaxInsideGroup.X;
                if (hullMinInsideGroup.Y < minY)
                    minY = hullMinInsideGroup.Y;
                if (hullMaxInsideGroup.Y > maxY)
                    maxY = hullMaxInsideGroup.Y;
            }

            // compute the position of the center of the group inside the coordinate system defined in the XML file
            float centerPositionRelativeToGroupOriginX = (maxX + minX) * 0.5f;
            float centerPositionRelativeToGroupOriginY = (maxY + minY) * 0.5f;

            // adjust the translate of each sub part to make the center of the group, the origin of the translate
            // This is easier when later we create an instance of this group from drag'n'droping from the library
            foreach (Brick.SubPart subPart in group.mGroupInfo.mGroupSubPartList)
                subPart.mLocalTransformInStud.Translate(-centerPositionRelativeToGroupOriginX / Layer.NUM_PIXEL_PER_STUD_FOR_BRICKS,
                                                        -centerPositionRelativeToGroupOriginY / Layer.NUM_PIXEL_PER_STUD_FOR_BRICKS,
                                                        MatrixOrder.Append);

            // also compute the vector between the center expressed in the drawing coord system (whose origin is in the
            // top left corner of the image) and the center expressed in the XML coord system
            float centerXMLToCenterImageX = ((maxX - minX) * 0.5f) - centerPositionRelativeToGroupOriginX;
            float centerXMLToCenterImageY = ((maxY - minY) * 0.5f) - centerPositionRelativeToGroupOriginY;

            // create a new image with the correct size
            int width = (int)(maxX - minX);
            int height = (int)(maxY - minY);
            if ((width > 0) && (height > 0))
            {
                group.Image = new Bitmap(width, height);
                // get the graphic context and draw the referenc image in it with the correct transform and scale
                Graphics graphics = Graphics.FromImage(group.Image);
                graphics.Clear(Color.Transparent);
                graphics.CompositingMode = CompositingMode.SourceOver;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.CompositingQuality = CompositingQuality.HighSpeed;
                graphics.InterpolationMode = InterpolationMode.HighQualityBilinear; // we need it for the high scale down version
                for (int i = 0; i < group.mGroupInfo.mGroupSubPartList.Count; ++i)
                {
                    // get the sub part and its transform
                    Brick.SubPart subPart = group.mGroupInfo.mGroupSubPartList[i];
                    Matrix drawingTransform = subPartDrawingTransforms[i];
                    // add a final translate to the drawing transform
                    drawingTransform.Translate(centerXMLToCenterImageX, centerXMLToCenterImageY, MatrixOrder.Append);
                    // set the transform to the graphics context and draw
                    graphics.Transform = drawingTransform;
                    graphics.DrawImage(subPart.mSubPartBrick.Image, 0, 0, subPart.mSubPartBrick.Image.Width, subPart.mSubPartBrick.Image.Height);
                }
                graphics.Flush();
            }
            else
            {
                throw new Exception("The group is too small to be visible.");
            }
        }