/** * Construct Java Graphics object which translates graphic calls in ppt Drawing layer. * * @param group The shape group to write the graphics calls into. */ public PPGraphics2D(ShapeGroup group){ this._group = group; _transform = new AffineTransform(); _stroke = new BasicStroke(); _paint = Color.black; _font = new Font("Arial", Font.PLAIN, 12); _background = Color.black; _foreground = Color.white; _hints = new RenderingHints(null); }
private void UpdateSurfaceVertices() { hullVertices.Clear(); if (Volume > 0) { ConvexHullHelper.GetConvexHull(triangleMesh.Data.vertices, hullVertices); var transformableData = triangleMesh.Data as TransformableMeshData; if (transformableData != null) { var transform = transformableData.worldTransform; for (int i = 0; i < hullVertices.Count; i++) { AffineTransform.Transform(ref hullVertices.Elements[i], ref transform, out hullVertices.Elements[i]); } } } else { hullVertices.Clear(); //A mobile mesh is allowed to have zero volume, so long as it isn't solid. //In this case, compute the bounding box of all points. BoundingBox box = new BoundingBox(); for (int i = 0; i < triangleMesh.Data.vertices.Length; i++) { Vector3 v; triangleMesh.Data.GetVertexPosition(i, out v); if (v.X > box.Max.X) { box.Max.X = v.X; } if (v.X < box.Min.X) { box.Min.X = v.X; } if (v.Y > box.Max.Y) { box.Max.Y = v.Y; } if (v.Y < box.Min.Y) { box.Min.Y = v.Y; } if (v.Z > box.Max.Z) { box.Max.Z = v.Z; } if (v.Z < box.Min.Z) { box.Min.Z = v.Z; } } //Add the corners. This will overestimate the size of the surface a bit. hullVertices.Add(box.Min); hullVertices.Add(box.Max); hullVertices.Add(new Vector3(box.Min.X, box.Min.Y, box.Max.Z)); hullVertices.Add(new Vector3(box.Min.X, box.Max.Y, box.Min.Z)); hullVertices.Add(new Vector3(box.Max.X, box.Min.Y, box.Min.Z)); hullVertices.Add(new Vector3(box.Min.X, box.Max.Y, box.Max.Z)); hullVertices.Add(new Vector3(box.Max.X, box.Max.Y, box.Min.Z)); hullVertices.Add(new Vector3(box.Max.X, box.Min.Y, box.Max.Z)); } }
public PartialView(Color color, bool rotate = false) { // new[] { // Colors.Black, // color, // Colors.Black //}.ToGradient(DefaultHeight / 2).Select( // (c, i) => // new Rectangle // { // Fill = new SolidColorBrush(c), // Width = DefaultWidth / 2, // Height = 3, // }.MoveTo(0, i * 2).AttachTo(this) //).ToArray(); var bg1 = new bg1().AttachTo(this); var buildmode = new Canvas().AttachTo(this); buildmode_off = new buildmode().AttachTo(buildmode); buildmode_on = new buildmode_on().AttachTo(buildmode); buildmode_on.Hide(); this.SizeChanged += delegate { //var Height = Width; { var a = new AffineTransform { Width = 720, Height = 720, X2 = Width, Y2 = Height, X3 = 000, Y3 = Height }; if (rotate) { a.X1 = Width; a.X3 = Width; a.X2 = 0; } bg1.RenderTransform = a; } { var a = new AffineTransform { Width = 128, Height = 128, X1 = 0, Y1 = Height - 64, X2 = 64, Y2 = Height, X3 = 0, Y3 = Height }; if (!rotate) { a.X1 += Width - (64 + 32); a.X3 += Width - (64 + 32); a.X2 += Width - (64 + 32); } else { a.X1 = 64; a.Y1 = Height; a.X2 = 0; a.Y2 = Height - 64; a.X3 = 64; a.Y3 = Height - 64; a.X1 += 32; a.X3 += 32; a.X2 += 32; } buildmode_off.RenderTransform = a; buildmode_on.RenderTransform = a; } }; this.ClipToBounds = true; //this.ClipTo(0, 0, DefaultWidth / 2, DefaultHeight); }
private static IMathTransform ReadAffineTransform(WktStreamTokenizer tokenizer) { /* * PARAM_MT[ * "Affine", * PARAMETER["num_row",3], * PARAMETER["num_col",3], * PARAMETER["elt_0_0", 0.883485346527455], * PARAMETER["elt_0_1", -0.468458794848877], * PARAMETER["elt_0_2", 3455869.17937689], * PARAMETER["elt_1_0", 0.468458794848877], * PARAMETER["elt_1_1", 0.883485346527455], * PARAMETER["elt_1_2", 5478710.88035753], * PARAMETER["elt_2_2", 1] * ] */ //tokenizer stands on the first PARAMETER if (tokenizer.GetStringValue() != "PARAMETER") { tokenizer.ReadToken("PARAMETER"); } IParameterInfo paramInfo = ReadParameters(tokenizer); //manage required parameters - row, col var rowParam = paramInfo.GetParameterByName("num_row"); var colParam = paramInfo.GetParameterByName("num_col"); if (rowParam == null) { throw new ArgumentNullException("Affine transform does not contain 'num_row' parameter"); } if (colParam == null) { throw new ArgumentNullException("Affine transform does not contain 'num_col' parameter"); } int rowVal = (int)rowParam.Value; int colVal = (int)colParam.Value; if (rowVal <= 0) { throw new ArgumentException("Affine transform contains invalid value of 'num_row' parameter"); } if (colVal <= 0) { throw new ArgumentException("Affine transform contains invalid value of 'num_col' parameter"); } //creates working matrix; double[,] matrix = new double[rowVal, colVal]; //simply process matrix values - no elt_ROW_COL parsing foreach (var param in paramInfo.Parameters) { if (param == null || param.Name == null) { continue; } switch (param.Name) { case "num_row": case "num_col": break; case "elt_0_0": matrix[0, 0] = param.Value; break; case "elt_0_1": matrix[0, 1] = param.Value; break; case "elt_0_2": matrix[0, 2] = param.Value; break; case "elt_0_3": matrix[0, 3] = param.Value; break; case "elt_1_0": matrix[1, 0] = param.Value; break; case "elt_1_1": matrix[1, 1] = param.Value; break; case "elt_1_2": matrix[1, 2] = param.Value; break; case "elt_1_3": matrix[1, 3] = param.Value; break; case "elt_2_0": matrix[2, 0] = param.Value; break; case "elt_2_1": matrix[2, 1] = param.Value; break; case "elt_2_2": matrix[2, 2] = param.Value; break; case "elt_2_3": matrix[2, 3] = param.Value; break; case "elt_3_0": matrix[3, 0] = param.Value; break; case "elt_3_1": matrix[3, 1] = param.Value; break; case "elt_3_2": matrix[3, 2] = param.Value; break; case "elt_3_3": matrix[3, 3] = param.Value; break; default: //unknown parameter break; } } //read rest of WKT if (tokenizer.GetStringValue() != "]") { tokenizer.ReadToken("]"); } //use "matrix" constructor to create transformation matrix IMathTransform affineTransform = new AffineTransform(matrix); return(affineTransform); }
public java.awt.Shape GetOutline(){ GeneralPath path = GetPath(); Rectangle2D anchor = GetAnchor2D(); Rectangle2D bounds = path.GetBounds2D(); AffineTransform at = new AffineTransform(); at.translate(anchor.GetX(), anchor.GetY()); at.scale( anchor.Width/bounds.Width, anchor.Height/bounds.Height ); return at.CreateTransformedShape(path); }
public bool DrawImage(Image image, AffineTransform affinetransform) { AffineTransform affinetransform1 = (AffineTransform)GetTrans().Clone(); GetTrans().concatenate(affinetransform); DrawImage(image, 0, 0); SetTrans( affinetransform1 ); return true; }
/** * Renders a {@link RenderedImage}, * Applying a transform from image * space into user space before Drawing. * The transformation from user space into device space is done with * the current <code>Transform</code> in the <code>Graphics2D</code>. * The specified transformation is applied to the image before the * transform attribute in the <code>Graphics2D</code> context is applied. * The rendering attributes applied include the <code>Clip</code>, * <code>Transform</code>, and <code>Composite</code> attributes. Note * that no rendering is done if the specified transform is * noninvertible. * @param img the image to be rendered. This method does * nothing if <code>img</code> is null. * @param xform the transformation from image space into user space * @see #_transform * @see #setTransform * @see #setComposite * @see #clip * @see #setClip */ public void DrawRenderableImage(RenderableImage img, AffineTransform xform) { log.log(POILogger.WARN, "Not implemented"); }
///<summary> /// Transforms a vector using an affine transform. ///</summary> ///<param name="position">Position to transform.</param> ///<param name="affineTransform">Transform to apply.</param> ///<returns>Transformed position.</returns> public static System.Numerics.Vector3 Transform(System.Numerics.Vector3 position, AffineTransform affineTransform) { System.Numerics.Vector3 toReturn; Transform(ref position, ref affineTransform, out toReturn); return toReturn; }
///<summary> /// Gets the triangle vertex positions at a given index. ///</summary> ///<param name="triangleIndex">First index of a triangle's vertices in the index buffer.</param> ///<param name="v1">First vertex of the triangle.</param> ///<param name="v2">Second vertex of the triangle.</param> ///<param name="v3">Third vertex of the triangle.</param> public override void GetTriangle(int triangleIndex, out Vector3 v1, out Vector3 v2, out Vector3 v3) { AffineTransform.Transform(ref vertices[indices[triangleIndex]], ref worldTransform, out v1); AffineTransform.Transform(ref vertices[indices[triangleIndex + 1]], ref worldTransform, out v2); AffineTransform.Transform(ref vertices[indices[triangleIndex + 2]], ref worldTransform, out v3); }
///<summary> /// Constructs the mesh data. ///</summary> ///<param name="vertices">Vertice sto use in the mesh data.</param> ///<param name="indices">Indices to use in the mesh data.</param> ///<param name="worldTransform">Transform to apply to vertices before returning their positions.</param> public TransformableMeshData(Vector3[] vertices, uint[] indices, int indexCount, AffineTransform worldTransform) { this.worldTransform = worldTransform; Vertices = vertices; Indices = indices; IndexCount = indexCount; }
/// <summary> /// Constructs a RenderContext with a given transform. /// The area of interest is taken to be the entire renderable area. /// No rendering hints are used. /// </summary> /// <param name="usr2dev"> an AffineTransform. </param> public RenderContext(AffineTransform usr2dev) : this(usr2dev, null, null) { }
// Various constructors that allow different levels of // specificity. If the Shape is missing the whole renderable area // is assumed. If hints is missing no hints are assumed. /// <summary> /// Constructs a RenderContext with a given transform. /// The area of interest is supplied as a Shape, /// and the rendering hints are supplied as a RenderingHints object. /// </summary> /// <param name="usr2dev"> an AffineTransform. </param> /// <param name="aoi"> a Shape representing the area of interest. </param> /// <param name="hints"> a RenderingHints object containing rendering hints. </param> public RenderContext(AffineTransform usr2dev, Shape aoi, RenderingHints hints) { this.Hints = hints; this.Aoi = aoi; this.Usr2dev = (AffineTransform)usr2dev.Clone(); }
public virtual void ConcetenateTransform(AffineTransform modTransform) { Usr2dev.Concatenate(modTransform); }
/// <summary> /// Modifies the current user-to-device transform by appending another /// transform. In matrix notation the operation is: /// <pre> /// [this] = [this] x [modTransform] /// </pre> /// </summary> /// <param name="modTransform"> the AffineTransform to append to the /// current usr2dev transform. /// @since 1.3 </param> public virtual void ConcatenateTransform(AffineTransform modTransform) { this.ConcetenateTransform(modTransform); }
/// <summary> /// Casts a convex shape against the collidable. /// </summary> /// <param name="castShape">Shape to cast.</param> /// <param name="startingTransform">Initial transform of the shape.</param> /// <param name="sweep">Sweep to apply to the shape.</param> /// <param name="hit">Hit data, if any.</param> /// <returns>Whether or not the cast hit anything.</returns> public override bool ConvexCast(ConvexShape castShape, ref RigidTransform startingTransform, ref System.Numerics.Vector3 sweep, out RayHit hit) { if (Shape.solidity == MobileMeshSolidity.Solid) { //If the convex cast is inside the mesh and the mesh is solid, it should return t = 0. var ray = new Ray() { Position = startingTransform.Position, Direction = Toolbox.UpVector }; if (Shape.IsLocalRayOriginInMesh(ref ray, out hit)) { hit = new RayHit() { Location = startingTransform.Position, Normal = new System.Numerics.Vector3(), T = 0 }; return(true); } } hit = new RayHit(); BoundingBox boundingBox; var transform = new AffineTransform { Translation = worldTransform.Position }; Matrix3x3.CreateFromQuaternion(ref worldTransform.Orientation, out transform.LinearTransform); castShape.GetSweptLocalBoundingBox(ref startingTransform, ref transform, ref sweep, out boundingBox); var tri = PhysicsThreadResources.GetTriangle(); var hitElements = CommonResources.GetIntList(); if (this.Shape.TriangleMesh.Tree.GetOverlaps(boundingBox, hitElements)) { hit.T = float.MaxValue; for (int i = 0; i < hitElements.Count; i++) { Shape.TriangleMesh.Data.GetTriangle(hitElements[i], out tri.vA, out tri.vB, out tri.vC); AffineTransform.Transform(ref tri.vA, ref transform, out tri.vA); AffineTransform.Transform(ref tri.vB, ref transform, out tri.vB); AffineTransform.Transform(ref tri.vC, ref transform, out tri.vC); System.Numerics.Vector3 center; Vector3Ex.Add(ref tri.vA, ref tri.vB, out center); Vector3Ex.Add(ref center, ref tri.vC, out center); Vector3Ex.Multiply(ref center, 1f / 3f, out center); Vector3Ex.Subtract(ref tri.vA, ref center, out tri.vA); Vector3Ex.Subtract(ref tri.vB, ref center, out tri.vB); Vector3Ex.Subtract(ref tri.vC, ref center, out tri.vC); tri.MaximumRadius = tri.vA.LengthSquared(); float radius = tri.vB.LengthSquared(); if (tri.MaximumRadius < radius) { tri.MaximumRadius = radius; } radius = tri.vC.LengthSquared(); if (tri.MaximumRadius < radius) { tri.MaximumRadius = radius; } tri.MaximumRadius = (float)Math.Sqrt(tri.MaximumRadius); tri.collisionMargin = 0; var triangleTransform = new RigidTransform { Orientation = System.Numerics.Quaternion.Identity, Position = center }; RayHit tempHit; if (MPRToolbox.Sweep(castShape, tri, ref sweep, ref Toolbox.ZeroVector, ref startingTransform, ref triangleTransform, out tempHit) && tempHit.T < hit.T) { hit = tempHit; } } tri.MaximumRadius = 0; PhysicsThreadResources.GiveBack(tri); CommonResources.GiveBack(hitElements); return(hit.T != float.MaxValue); } PhysicsThreadResources.GiveBack(tri); CommonResources.GiveBack(hitElements); return(false); }
/// <summary>If present, process the preserveAspectRatio position.</summary> /// <param name="context">the svg draw context</param> /// <param name="viewBoxValues">the four values depicting the viewbox [min-x min-y width height]</param> /// <param name="align">alignment method to use</param> /// <param name="scaleWidth">the multiplier for scaling width</param> /// <param name="scaleHeight">the multiplier for scaling height</param> /// <returns>the transformation based on the preserveAspectRatio value</returns> internal virtual AffineTransform ProcessAspectRatioPosition(SvgDrawContext context, float[] viewBoxValues, String align, float scaleWidth, float scaleHeight) { AffineTransform transform = new AffineTransform(); Rectangle currentViewPort = context.GetCurrentViewPort(); float midXBox = viewBoxValues[0] + (viewBoxValues[2] / 2); float midYBox = viewBoxValues[1] + (viewBoxValues[3] / 2); float midXPort = currentViewPort.GetX() + (currentViewPort.GetWidth() / 2); float midYPort = currentViewPort.GetY() + (currentViewPort.GetHeight() / 2); float x = 0f; float y = 0f; // if x attribute of svg is present, then x value of current viewport should be set according to it if (attributesAndStyles.ContainsKey(SvgConstants.Attributes.X)) { x = CssUtils.ParseAbsoluteLength(attributesAndStyles.Get(SvgConstants.Attributes.X)); } // if y attribute of svg is present, then y value of current viewport should be set according to it if (attributesAndStyles.ContainsKey(SvgConstants.Attributes.Y)) { y = CssUtils.ParseAbsoluteLength(attributesAndStyles.Get(SvgConstants.Attributes.Y)); } if (!(this is MarkerSvgNodeRenderer)) { x -= currentViewPort.GetX(); y -= currentViewPort.GetY(); } // need to consider previous (parent) translation before applying the current one switch (align.ToLowerInvariant()) { case SvgConstants.Values.NONE: { break; } case SvgConstants.Values.XMIN_YMIN: { x -= viewBoxValues[0]; y -= viewBoxValues[1]; break; } case SvgConstants.Values.XMIN_YMID: { x -= viewBoxValues[0]; y += (midYPort - midYBox); break; } case SvgConstants.Values.XMIN_YMAX: { x -= viewBoxValues[0]; y += (currentViewPort.GetHeight() - viewBoxValues[3]); break; } case SvgConstants.Values.XMID_YMIN: { x += (midXPort - midXBox); y -= viewBoxValues[1]; break; } case SvgConstants.Values.XMID_YMAX: { x += (midXPort - midXBox); y += (currentViewPort.GetHeight() - viewBoxValues[3]); break; } case SvgConstants.Values.XMAX_YMIN: { x += (currentViewPort.GetWidth() - viewBoxValues[2]); y -= viewBoxValues[1]; break; } case SvgConstants.Values.XMAX_YMID: { x += (currentViewPort.GetWidth() - viewBoxValues[2]); y += (midYPort - midYBox); break; } case SvgConstants.Values.XMAX_YMAX: { x += (currentViewPort.GetWidth() - viewBoxValues[2]); y += (currentViewPort.GetHeight() - viewBoxValues[3]); break; } case SvgConstants.Values.DEFAULT_ASPECT_RATIO: default: { x += (midXPort - midXBox); y += (midYPort - midYBox); break; } } //Rescale x and y x /= scaleWidth; y /= scaleHeight; transform.Translate(x, y); return(transform); }
///<summary> /// Gets the position of a vertex in the data. ///</summary> ///<param name="i">Index of the vertex.</param> ///<param name="vertex">Position of the vertex.</param> public override void GetVertexPosition(int i, out Vector3 vertex) { AffineTransform.Transform(ref vertices[i], ref worldTransform, out vertex); }
/** * Composes an <code>AffineTransform</code> object with the * <code>Transform</code> in this <code>Graphics2D</code> according * to the rule last-specified-first-applied. If the current * <code>Transform</code> is Cx, the result of composition * with Tx is a new <code>Transform</code> Cx'. Cx' becomes the * current <code>Transform</code> for this <code>Graphics2D</code>. * Transforming a point p by the updated <code>Transform</code> Cx' is * equivalent to first transforming p by Tx and then transforming * the result by the original <code>Transform</code> Cx. In other * words, Cx'(p) = Cx(Tx(p)). A copy of the Tx is made, if necessary, * so further modifications to Tx do not affect rendering. * @param Tx the <code>AffineTransform</code> object to be composed with * the current <code>Transform</code> * @see #setTransform * @see AffineTransform */ public void transform(AffineTransform Tx) { _transform.concatenate(Tx); }
/// <summary> /// Precomputes the transform to bring triangles from their native local space to the local space of the convex. /// </summary> /// <param name="convexInverseWorldTransform">Inverse of the world transform of the convex shape.</param> /// <param name="fromMeshLocalToConvexLocal">Transform to apply to native local triangles to bring them into the local space of the convex.</param> protected override void PrecomputeTriangleTransform(ref AffineTransform convexInverseWorldTransform, out AffineTransform fromMeshLocalToConvexLocal) { //MobileMeshes only have TransformableMeshData sources. var data = ((TransformableMeshData)mesh.Shape.TriangleMesh.Data); //The mobile mesh has a shape-based transform followed by the rigid body transform. AffineTransform mobileMeshWorldTransform; AffineTransform.CreateFromRigidTransform(ref mesh.worldTransform, out mobileMeshWorldTransform); AffineTransform combinedMobileMeshWorldTransform; AffineTransform.Multiply(ref data.worldTransform, ref mobileMeshWorldTransform, out combinedMobileMeshWorldTransform); AffineTransform.Multiply(ref combinedMobileMeshWorldTransform, ref convexInverseWorldTransform, out fromMeshLocalToConvexLocal); }
AffineTransform GetAnchor(AffineTransform rootTransform, float distance, Camera camera) { return(AffineTransform.Create(rootTransform.t + (float3)camera.transform.right * distance, rootTransform.q)); }
/// <summary> /// Sets the transform of the specified glyph within this /// <code>GlyphVector</code>. /// </summary> abstract public void setGlyphTransform(int @glyphIndex, AffineTransform @newTX);
public void DrawRenderedImage(RenderedImage renderedimage, AffineTransform affinetransform) { BufferedImage bufferedimage = new BufferedImage(renderedimage.GetColorModel(), renderedimage.GetData().CreateCompatibleWritableRaster(), false, null); bufferedimage.SetData(renderedimage.GetData()); DrawImage(bufferedimage, affinetransform, null); }
///<summary> /// Constructs a new Terrain. ///</summary> ///<param name="heights">Height data to use to create the TerrainShape.</param> ///<param name="worldTransform">Transform to use for the terrain.</param> public Terrain(float[,] heights, AffineTransform worldTransform) : this(new TerrainShape(heights), worldTransform) { }
///<summary> /// Transforms a vector by an affine transform's inverse. ///</summary> ///<param name="position">Position to transform.</param> ///<param name="transform">Transform to invert and apply.</param> ///<param name="transformed">Transformed position.</param> public static void TransformInverse(ref Vector3 position, ref AffineTransform transform, out Vector3 transformed) { Vector3.Subtract(ref position, ref transform.Translation, out transformed); Matrix3x3 inverse; Matrix3x3.Invert(ref transform.LinearTransform, out inverse); Matrix3x3.TransformTranspose(ref transformed, ref inverse, out transformed); }
///<summary> /// Tests a ray against the terrain shape. ///</summary> ///<param name="ray">Ray to test against the shape.</param> ///<param name="maximumLength">Maximum length of the ray in units of the ray direction's length.</param> ///<param name="transform">Transform to apply to the terrain shape during the test.</param> ///<param name="hit">Hit data of the ray cast, if any.</param> ///<returns>Whether or not the ray hit the transformed terrain shape.</returns> public bool RayCast(ref Ray ray, float maximumLength, ref AffineTransform transform, out RayHit hit) { return(RayCast(ref ray, maximumLength, ref transform, TriangleSidedness.Counterclockwise, out hit)); }
public AffineTransform InverseMul(AffineTransform transform) { var invR = Quaternion.Inverse(rotation); return(new AffineTransform(invR * (transform.translation - translation), invR * transform.rotation)); }
///<summary> /// Tests a ray against the terrain shape. ///</summary> ///<param name="ray">Ray to test against the shape.</param> ///<param name="maximumLength">Maximum length of the ray in units of the ray direction's length.</param> ///<param name="transform">Transform to apply to the terrain shape during the test.</param> ///<param name="sidedness">Sidedness of the triangles to use when raycasting.</param> ///<param name="hit">Hit data of the ray cast, if any.</param> ///<returns>Whether or not the ray hit the transformed terrain shape.</returns> public bool RayCast(ref Ray ray, float maximumLength, ref AffineTransform transform, TriangleSidedness sidedness, out RayHit hit) { hit = new RayHit(); //Put the ray into local space. Ray localRay; AffineTransform inverse; AffineTransform.Invert(ref transform, out inverse); Matrix3x3.Transform(ref ray.Direction, ref inverse.LinearTransform, out localRay.Direction); AffineTransform.Transform(ref ray.Position, ref inverse, out localRay.Position); //Use rasterizey traversal. //The origin is at 0,0,0 and the map goes +X, +Y, +Z. //if it's before the origin and facing away, or outside the max and facing out, early out. float maxX = heights.GetLength(0) - 1; float maxZ = heights.GetLength(1) - 1; Vector3 progressingOrigin = localRay.Position; float distance = 0; //Check the outside cases first. if (progressingOrigin.X < 0) { if (localRay.Direction.X > 0) { //Off the left side. float timeToMinX = -progressingOrigin.X / localRay.Direction.X; distance += timeToMinX; Vector3 increment; Vector3.Multiply(ref localRay.Direction, timeToMinX, out increment); Vector3.Add(ref increment, ref progressingOrigin, out progressingOrigin); } else { return(false); //Outside and pointing away from the terrain. } } else if (progressingOrigin.X > maxX) { if (localRay.Direction.X < 0) { //Off the left side. float timeToMinX = -(progressingOrigin.X - maxX) / localRay.Direction.X; distance += timeToMinX; Vector3 increment; Vector3.Multiply(ref localRay.Direction, timeToMinX, out increment); Vector3.Add(ref increment, ref progressingOrigin, out progressingOrigin); } else { return(false); //Outside and pointing away from the terrain. } } if (progressingOrigin.Z < 0) { if (localRay.Direction.Z > 0) { float timeToMinZ = -progressingOrigin.Z / localRay.Direction.Z; distance += timeToMinZ; Vector3 increment; Vector3.Multiply(ref localRay.Direction, timeToMinZ, out increment); Vector3.Add(ref increment, ref progressingOrigin, out progressingOrigin); } else { return(false); } } else if (progressingOrigin.Z > maxZ) { if (localRay.Direction.Z < 0) { float timeToMinZ = -(progressingOrigin.Z - maxZ) / localRay.Direction.Z; distance += timeToMinZ; Vector3 increment; Vector3.Multiply(ref localRay.Direction, timeToMinZ, out increment); Vector3.Add(ref increment, ref progressingOrigin, out progressingOrigin); } else { return(false); } } if (distance > maximumLength) { return(false); } //By now, we should be entering the main body of the terrain. int xCell = (int)progressingOrigin.X; int zCell = (int)progressingOrigin.Z; //If it's hitting the border and going in, then correct the index //so that it will initially target a valid quad. //Without this, a quad beyond the border would be tried and failed. if (xCell == heights.GetLength(0) - 1 && localRay.Direction.X < 0) { xCell = heights.GetLength(0) - 2; } if (zCell == heights.GetLength(1) - 1 && localRay.Direction.Z < 0) { zCell = heights.GetLength(1) - 2; } while (true) { //Check for a miss. if (xCell < 0 || zCell < 0 || xCell >= heights.GetLength(0) - 1 || zCell >= heights.GetLength(1) - 1) { return(false); } //Test the triangles of this cell. Vector3 v1, v2, v3, v4; // v3 v4 // v1 v2 GetLocalPosition(xCell, zCell, out v1); GetLocalPosition(xCell + 1, zCell, out v2); GetLocalPosition(xCell, zCell + 1, out v3); GetLocalPosition(xCell + 1, zCell + 1, out v4); RayHit hit1, hit2; bool didHit1; bool didHit2; //Don't bother doing ray intersection tests if the ray can't intersect it. float highest = v1.Y; float lowest = v1.Y; if (v2.Y > highest) { highest = v2.Y; } else if (v2.Y < lowest) { lowest = v2.Y; } if (v3.Y > highest) { highest = v3.Y; } else if (v3.Y < lowest) { lowest = v3.Y; } if (v4.Y > highest) { highest = v4.Y; } else if (v4.Y < lowest) { lowest = v4.Y; } if (!(progressingOrigin.Y > highest && localRay.Direction.Y > 0 || progressingOrigin.Y < lowest && localRay.Direction.Y < 0)) { if (quadTriangleOrganization == QuadTriangleOrganization.BottomLeftUpperRight) { //Always perform the raycast as if Y+ in local space is the way the triangles are facing. didHit1 = Toolbox.FindRayTriangleIntersection(ref localRay, maximumLength, sidedness, ref v1, ref v2, ref v3, out hit1); didHit2 = Toolbox.FindRayTriangleIntersection(ref localRay, maximumLength, sidedness, ref v2, ref v4, ref v3, out hit2); } else //if (quadTriangleOrganization == CollisionShapes.QuadTriangleOrganization.BottomRightUpperLeft) { didHit1 = Toolbox.FindRayTriangleIntersection(ref localRay, maximumLength, sidedness, ref v1, ref v2, ref v4, out hit1); didHit2 = Toolbox.FindRayTriangleIntersection(ref localRay, maximumLength, sidedness, ref v1, ref v4, ref v3, out hit2); } if (didHit1 && didHit2) { if (hit1.T < hit2.T) { Vector3.Multiply(ref ray.Direction, hit1.T, out hit.Location); Vector3.Add(ref hit.Location, ref ray.Position, out hit.Location); Matrix3x3.TransformTranspose(ref hit1.Normal, ref inverse.LinearTransform, out hit.Normal); hit.T = hit1.T; return(true); } Vector3.Multiply(ref ray.Direction, hit2.T, out hit.Location); Vector3.Add(ref hit.Location, ref ray.Position, out hit.Location); Matrix3x3.TransformTranspose(ref hit2.Normal, ref inverse.LinearTransform, out hit.Normal); hit.T = hit2.T; return(true); } else if (didHit1) { Vector3.Multiply(ref ray.Direction, hit1.T, out hit.Location); Vector3.Add(ref hit.Location, ref ray.Position, out hit.Location); Matrix3x3.TransformTranspose(ref hit1.Normal, ref inverse.LinearTransform, out hit.Normal); hit.T = hit1.T; return(true); } else if (didHit2) { Vector3.Multiply(ref ray.Direction, hit2.T, out hit.Location); Vector3.Add(ref hit.Location, ref ray.Position, out hit.Location); Matrix3x3.TransformTranspose(ref hit2.Normal, ref inverse.LinearTransform, out hit.Normal); hit.T = hit2.T; return(true); } } //Move to the next cell. float timeToX; if (localRay.Direction.X < 0) { timeToX = -(progressingOrigin.X - xCell) / localRay.Direction.X; } else if (localRay.Direction.X > 0) { timeToX = (xCell + 1 - progressingOrigin.X) / localRay.Direction.X; } else { timeToX = float.MaxValue; } float timeToZ; if (localRay.Direction.Z < 0) { timeToZ = -(progressingOrigin.Z - zCell) / localRay.Direction.Z; } else if (localRay.Direction.Z > 0) { timeToZ = (zCell + 1 - progressingOrigin.Z) / localRay.Direction.Z; } else { timeToZ = float.MaxValue; } //Move to the next cell. if (timeToX < timeToZ) { if (localRay.Direction.X < 0) { xCell--; } else { xCell++; } distance += timeToX; if (distance > maximumLength) { return(false); } Vector3 increment; Vector3.Multiply(ref localRay.Direction, timeToX, out increment); Vector3.Add(ref increment, ref progressingOrigin, out progressingOrigin); } else { if (localRay.Direction.Z < 0) { zCell--; } else { zCell++; } distance += timeToZ; if (distance > maximumLength) { return(false); } Vector3 increment; Vector3.Multiply(ref localRay.Direction, timeToZ, out increment); Vector3.Add(ref increment, ref progressingOrigin, out progressingOrigin); } } }
/// <summary> /// Constructs a RenderContext with a given transform and area of interest. /// The area of interest is supplied as a Shape. /// No rendering hints are used. /// </summary> /// <param name="usr2dev"> an AffineTransform. </param> /// <param name="aoi"> a Shape representing the area of interest. </param> public RenderContext(AffineTransform usr2dev, Shape aoi) : this(usr2dev, aoi, null) { }
///<summary> /// Constructs the bounding box of the terrain given a transform. ///</summary> ///<param name="transform">Transform to apply to the terrain during the bounding box calculation.</param> ///<param name="boundingBox">Bounding box of the terrain shape when transformed.</param> public void GetBoundingBox(ref AffineTransform transform, out BoundingBox boundingBox) { #if !WINDOWS boundingBox = new BoundingBox(); #endif float minX = float.MaxValue, maxX = -float.MaxValue, minY = float.MaxValue, maxY = -float.MaxValue, minZ = float.MaxValue, maxZ = -float.MaxValue; Vector3 minXvertex = new Vector3(), maxXvertex = new Vector3(), minYvertex = new Vector3(), maxYvertex = new Vector3(), minZvertex = new Vector3(), maxZvertex = new Vector3(); //Find the extreme locations. for (int i = 0; i < heights.GetLength(0); i++) { for (int j = 0; j < heights.GetLength(1); j++) { var vertex = new Vector3(i, heights[i, j], j); Matrix3x3.Transform(ref vertex, ref transform.LinearTransform, out vertex); if (vertex.X < minX) { minX = vertex.X; minXvertex = vertex; } else if (vertex.X > maxX) { maxX = vertex.X; maxXvertex = vertex; } if (vertex.Y < minY) { minY = vertex.Y; minYvertex = vertex; } else if (vertex.Y > maxY) { maxY = vertex.Y; maxYvertex = vertex; } if (vertex.Z < minZ) { minZ = vertex.Z; minZvertex = vertex; } else if (vertex.Z > maxZ) { maxZ = vertex.Z; maxZvertex = vertex; } } } //Shift the bounding box. boundingBox.Min.X = minXvertex.X + transform.Translation.X; boundingBox.Min.Y = minYvertex.Y + transform.Translation.Y; boundingBox.Min.Z = minZvertex.Z + transform.Translation.Z; boundingBox.Max.X = maxXvertex.X + transform.Translation.X; boundingBox.Max.Y = maxYvertex.Y + transform.Translation.Y; boundingBox.Max.Z = maxZvertex.Z + transform.Translation.Z; }
public unsafe static void TestMultiplyCorrectness() { const int iterationCount = 100000; Random random = new Random(5); for (int iterationIndex = 0; iterationIndex < iterationCount; ++iterationIndex) { AffineTransform simdA, simdB; bAffineTransform scalarA, scalarB; var simdPointerA = (float *)&simdA; var scalarPointerA = (float *)&scalarA; var simdPointerB = (float *)&simdB; var scalarPointerB = (float *)&scalarB; for (int i = 0; i < 12; ++i) { scalarPointerA[i] = simdPointerA[i] = (float)(random.NextDouble() * 4 - 2); scalarPointerB[i] = simdPointerB[i] = (float)(random.NextDouble() * 4 - 2); } AffineTransform simdResult; AffineTransform.Multiply(ref simdA, ref simdB, out simdResult); bAffineTransform scalarResult; bAffineTransform.Multiply(ref scalarA, ref scalarB, out scalarResult); var simdPointerResult = (float *)&simdResult; var scalarPointerResult = (float *)&scalarResult; for (int i = 0; i < 12; ++i) { const float threshold = 1e-5f; var simdScalarError = Math.Abs(simdPointerResult[i] - scalarPointerResult[i]); if (simdScalarError > threshold) { Console.WriteLine($"Excess error for {i}"); } } } for (int iterationIndex = 0; iterationIndex < iterationCount; ++iterationIndex) { AffineTransform simdA, simdB; bAffineTransform scalarA, scalarB; var simdPointerA = (float *)&simdA; var scalarPointerA = (float *)&scalarA; var simdPointerB = (float *)&simdB; var scalarPointerB = (float *)&scalarB; for (int i = 0; i < 12; ++i) { scalarPointerA[i] = simdPointerA[i] = (float)(random.NextDouble() * 4 - 2); scalarPointerB[i] = simdPointerB[i] = (float)(random.NextDouble() * 4 - 2); } AffineTransform.Multiply(ref simdA, ref simdB, out simdA); bAffineTransform.Multiply(ref scalarA, ref scalarB, out scalarA); for (int i = 0; i < 12; ++i) { const float threshold = 1e-5f; var simdScalarError = Math.Abs(simdPointerA[i] - scalarPointerA[i]); if (simdScalarError > threshold) { Console.WriteLine($"Excess error for {i}"); } } } for (int iterationIndex = 0; iterationIndex < iterationCount; ++iterationIndex) { AffineTransform simdA, simdB; bAffineTransform scalarA, scalarB; var simdPointerA = (float *)&simdA; var scalarPointerA = (float *)&scalarA; var simdPointerB = (float *)&simdB; var scalarPointerB = (float *)&scalarB; for (int i = 0; i < 12; ++i) { scalarPointerA[i] = simdPointerA[i] = (float)(random.NextDouble() * 4 - 2); scalarPointerB[i] = simdPointerB[i] = (float)(random.NextDouble() * 4 - 2); } AffineTransform.Multiply(ref simdA, ref simdB, out simdB); bAffineTransform.Multiply(ref scalarA, ref scalarB, out scalarB); for (int i = 0; i < 12; ++i) { const float threshold = 1e-5f; var simdScalarError = Math.Abs(simdPointerB[i] - scalarPointerB[i]); if (simdScalarError > threshold) { Console.WriteLine($"Excess error for {i}"); } } } for (int iterationIndex = 0; iterationIndex < iterationCount; ++iterationIndex) { AffineTransform simd; bAffineTransform scalar; var simdPointer = (float *)&simd; var scalarPointer = (float *)&scalar; for (int i = 0; i < 12; ++i) { scalarPointer[i] = simdPointer[i] = (float)(random.NextDouble() * 4 - 2); } AffineTransform.Multiply(ref simd, ref simd, out simd); bAffineTransform.Multiply(ref scalar, ref scalar, out scalar); for (int i = 0; i < 12; ++i) { const float threshold = 1e-5f; var simdScalarError = Math.Abs(simdPointer[i] - scalarPointer[i]); if (simdScalarError > threshold) { Console.WriteLine($"Excess error for {i}"); } } } }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns an iterator object that iterates along the boundary of this * <code>Polygon</code> and provides access to the geometry * of the outline of this <code>Polygon</code>. An optional * {@link AffineTransform} can be specified so that the coordinates * returned in the iteration are transformed accordingly. * @param at an optional <code>AffineTransform</code> to be applied to the * coordinates as they are returned in the iteration, or * <code>null</code> if untransformed coordinates are desired * @return a {@link IPathIterator} object that provides access to the * geometry of this <code>Polygon</code>. */ public PathIterator GetPathIterator(AffineTransform at) { return(new PolygonPathIterator(this, at)); }
///<summary> /// Constructs a new static mesh. ///</summary> ///<param name="vertices">Vertex positions of the mesh.</param> ///<param name="indices">Index list of the mesh.</param> /// <param name="worldTransform">Transform to use to create the mesh initially.</param> public StaticMesh(Vector3[] vertices, int[] indices, AffineTransform worldTransform) { base.Shape = new StaticMeshShape(vertices, indices, worldTransform); Events = new ContactEventManager <StaticMesh>(); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns an iterator object that iterates along the boundary of * the <code>IShape</code> and provides access to the geometry of the * outline of the <code>IShape</code>. Only SEG_MOVETO, SEG_LINETO, and * SEG_CLOSE point types are returned by the iterator. * Since polygons are already flat, the <code>flatness</code> parameter * is ignored. An optional <code>AffineTransform</code> can be specified * in which case the coordinates returned in the iteration are transformed * accordingly. * @param at an optional <code>AffineTransform</code> to be applied to the * coordinates as they are returned in the iteration, or * <code>null</code> if untransformed coordinates are desired * @param flatness the maximum amount that the control points * for a given curve can vary from colinear before a subdivided * curve is replaced by a straight line connecting the * endpoints. Since polygons are already flat the * <code>flatness</code> parameter is ignored. * @return a <code>IPathIterator</code> object that provides access to the * <code>IShape</code> object's geometry. */ public PathIterator GetPathIterator(AffineTransform at, int flatness) { return(GetPathIterator(at)); }
///<summary> /// Transforms a vector by an affine transform. ///</summary> ///<param name="position">Position to transform.</param> ///<param name="transform">Transform to apply.</param> ///<param name="transformed">Transformed position.</param> public static void Transform(ref System.Numerics.Vector3 position, ref AffineTransform transform, out System.Numerics.Vector3 transformed) { Matrix3x3.Transform(ref position, ref transform.LinearTransform, out transformed); Vector3Ex.Add(ref transformed, ref transform.Translation, out transformed); }
public Rectangle2D GetLogicalAnchor2D() { Rectangle anchor = GetAnchor2D(); //if it is a groupped shape see if we need to transform the coordinates if (_parent != null) { Shape top = _parent; while (top.GetParent() != null) top = top.GetParent(); Rectangle clientAnchor = top.GetAnchor2D(); Rectangle spgrAnchor = ((ShapeGroup)top).GetCoordinates(); double scalex = spgrAnchor.Width / clientAnchor.Width; double scaley = spgrAnchor.Height / clientAnchor.Height; double x = clientAnchor.X + (anchor.X - spgrAnchor.X) / scalex; double y = clientAnchor.Y + (anchor.Y - spgrAnchor.Y) / scaley; double width = anchor.Width / scalex; double height = anchor.Height / scaley; anchor = new Rectangle2D.Double(x, y, width, height); } int angle = GetRotation(); if (angle != 0) { double centerX = anchor.X + anchor.Width / 2; double centerY = anchor.Y + anchor.Height / 2; AffineTransform trans = new AffineTransform(); trans.translate(centerX, centerY); trans.rotate(Math.ToRadians(angle)); trans.translate(-centerX, -centerY); Rectangle2D rect = trans.CreateTransformedShape(anchor).GetBounds2D(); if ((anchor.Width < anchor.Height && rect.Width > rect.Height) || (anchor.Width > anchor.Height && rect.Width < rect.Height)) { trans = new AffineTransform(); trans.translate(centerX, centerY); trans.rotate(Math.PI / 2); trans.translate(-centerX, -centerY); anchor = trans.CreateTransformedShape(anchor).GetBounds2D(); } } return anchor; }
public override void Render(Image im, BoundingBox clip, AffineTransform tx, string text, Vec2 loc, Pixel color) { if (text == null || text.Length == 0) return; int offset = 0, x = 0, y = 0, bdfFontDepth = bdfFont.getDepth(), x_min = int.MaxValue, y_min = int.MaxValue, x_max = int.MinValue, y_max = int.MinValue, charsCount = text.Length, fHeight, scan, fg_r, fg_g, fg_b, bx, by, offsetLine, fPixel, px, py, bg_r, bg_g, bg_b, r, g, b ; int[] fData; Vec2 src, dst; BDFParser.Rectangle glyph_box = new BDFParser.Rectangle(); BDFGlyph glyph; Image img; if ((bdfFont != null) && (charsCount > 0)) { char[] chrs = text.ToCharArray(); int mH = 0; int mY = 0; int mxY = 0; int tW = 0; int tH = 0; for (uint m = 0; m < text.Length; m++) { glyph = bdfFont.getGlyph(chrs[m]); glyph_box = glyph.getBbx(glyph_box); if (glyph_box.height > mH) { mH = glyph_box.height + 2; } if (glyph_box.y < mY) { mY = glyph_box.y; } if (glyph_box.y > mxY) { mxY = glyph_box.y; } tW += glyph_box.width + glyph_box.x + 2; } tH = mH + (mxY - mY); y = mH + -mY; img = new Image(tW, tH); float f_max = (1 << bdfFontDepth) - 1; if (f_max == 0) f_max = 1; glyph_box = new BDFParser.Rectangle(); src = new Vec2(); dst = new Vec2(); for (int i = 0; i < charsCount; i++) { glyph = bdfFont.getGlyph(chrs[i]); if (glyph == null) { continue; } glyph_box = glyph.getBbx(glyph_box); fHeight = glyph_box.height; fData = glyph.getData(); scan = fData.Length / fHeight; fg_r = color.R; fg_g = color.G; fg_b = color.B; //box location bx = x + offset + glyph_box.x; by = y - fHeight - glyph_box.y; for (int k = 0; k < fHeight; k++) { offsetLine = k * scan; for (int j = 0; j < scan; j++) { fPixel = fData[offsetLine + j]; if (fPixel != 0) { //pixel location px = bx + j; py = by + k; if (tx != null) { //src.setLocation(px, py); //tx.transform(src, dst); #warning TODO: Add support for this. //px = dst.X; //py = dst.Y; } //clip if (clip == null || clip.Contains(px, py)) { //compute color Pixel bg_color = img.GetPixel((uint)px, (uint)py); bg_r = bg_color.R; bg_g = bg_color.G; bg_b = bg_color.B; //todo improve this pixel composition float alpha = fPixel / f_max; r = bg_r + ((int)((fg_r - bg_r) * alpha)) & 0xFF; g = bg_g + ((int)((fg_g - bg_g) * alpha)) & 0xFF; b = bg_b + ((int)((fg_b - bg_b) * alpha)) & 0xFF; Pixel nw = new Pixel((byte)r, (byte)g, (byte)b, 255); img.SetPixel((uint)px, (uint)py, nw); if (x_min > px) x_min = px; if (y_min > py) y_min = py; if (x_max < px) x_max = px; if (y_max < py) y_max = py; } } } } offset += glyph.getDWidth().width; } //img = ImageManipulator.Resize(img, new Vec2(img.Width * 8, img.Height * 8), ImageManipulator.ScalingAlgorithm.Bicubic); //img = ImageManipulator.Resize(img, Vec2.Zero, ImageManipulator.ScalingAlgorithm.Hq2x); //img = ImageManipulator.Resize(img, Vec2.Zero, ImageManipulator.ScalingAlgorithm.Hq4x); im.DrawImage(loc, img); } }
public override void Render(Image i, BoundingBox clip, AffineTransform trans, string text, Vec2 loc, Pixel color) { GetTextRenderer().Render(i,clip,trans,text,loc,color); }
/** * Renders an image, Applying a transform from image space into user space * before Drawing. * The transformation from user space into device space is done with * the current <code>Transform</code> in the <code>Graphics2D</code>. * The specified transformation is applied to the image before the * transform attribute in the <code>Graphics2D</code> context is applied. * The rendering attributes applied include the <code>Clip</code>, * <code>Transform</code>, and <code>Composite</code> attributes. * Note that no rendering is done if the specified transform is * noninvertible. * @param img the <code>Image</code> to be rendered * @param xform the transformation from image space into user space * @param obs the {@link ImageObserver} * to be notified as more of the <code>Image</code> * is Converted * @return <code>true</code> if the <code>Image</code> is * fully loaded and completely rendered; * <code>false</code> if the <code>Image</code> is still being loaded. * @see #_transform * @see #setTransform * @see #setComposite * @see #clip * @see #setClip(Shape) */ public bool DrawImage(Image img, AffineTransform xform, ImageObserver obs) { log.log(POILogger.WARN, "Not implemented"); return false; }
private void CalculateImageDimensions(Rectangle layoutBox, AffineTransform t, PdfXObject xObject) { width = this.GetProperty <UnitValue>(Property.WIDTH) != null?RetrieveWidth(layoutBox.GetWidth()) : null; float?declaredHeight = RetrieveHeight(); height = declaredHeight; if (width == null && height == null) { width = imageWidth; height = (float)width / imageWidth * imageHeight; } else { if (width == null) { width = (float)height / imageHeight * imageWidth; } else { if (height == null) { height = (float)width / imageWidth * imageHeight; } } } float?horizontalScaling = this.GetPropertyAsFloat(Property.HORIZONTAL_SCALING, 1f); float?verticalScaling = this.GetPropertyAsFloat(Property.VERTICAL_SCALING, 1f); if (xObject is PdfFormXObject && width != imageWidth) { horizontalScaling *= width / imageWidth; verticalScaling *= height / imageHeight; } if (horizontalScaling != 1) { if (xObject is PdfFormXObject) { t.Scale((float)horizontalScaling, 1); width = imageWidth * (float)horizontalScaling; } else { width *= (float)horizontalScaling; } } if (verticalScaling != 1) { if (xObject is PdfFormXObject) { t.Scale(1, (float)verticalScaling); height = imageHeight * (float)verticalScaling; } else { height *= (float)verticalScaling; } } // Constrain width and height according to min/max width float?minWidth = RetrieveMinWidth(layoutBox.GetWidth()); float?maxWidth = RetrieveMaxWidth(layoutBox.GetWidth()); if (null != minWidth && width < minWidth) { height *= minWidth / width; width = minWidth; } else { if (null != maxWidth && width > maxWidth) { height *= maxWidth / width; width = maxWidth; } } // Constrain width and height according to min/max height, which has precedence over width settings float?minHeight = RetrieveMinHeight(); float?maxHeight = RetrieveMaxHeight(); if (null != minHeight && height < minHeight) { width *= minHeight / height; height = minHeight; } else { if (null != maxHeight && height > maxHeight) { width *= maxHeight / height; this.height = maxHeight; } else { if (null != declaredHeight && !height.Equals(declaredHeight)) { width *= declaredHeight / height; height = declaredHeight; } } } }
/** * Sets the <code>Transform</code> in the <code>Graphics2D</code> * context. * @param Tx the <code>AffineTransform</code> object to be used in the * rendering process * @see #_transform * @see AffineTransform */ public void SetTransform(AffineTransform Tx) { _transform = new AffineTransform(Tx); }
private float AdjustPositionAfterRotation(float angle, float maxWidth, float maxHeight) { if (angle != 0) { AffineTransform t = AffineTransform.GetRotateInstance(angle); Point p00 = t.Transform(new Point(0, 0), new Point()); Point p01 = t.Transform(new Point(0, (float)height), new Point()); Point p10 = t.Transform(new Point((float)width, 0), new Point()); Point p11 = t.Transform(new Point((float)width, (float)height), new Point()); double[] xValues = new double[] { p01.GetX(), p10.GetX(), p11.GetX() }; double[] yValues = new double[] { p01.GetY(), p10.GetY(), p11.GetY() }; double minX = p00.GetX(); double minY = p00.GetY(); double maxX = minX; double maxY = minY; foreach (double x in xValues) { minX = Math.Min(minX, x); maxX = Math.Max(maxX, x); } foreach (double y in yValues) { minY = Math.Min(minY, y); maxY = Math.Max(maxY, y); } height = (float)(maxY - minY); width = (float)(maxX - minX); pivotY = (float)(p00.GetY() - minY); deltaX = -(float)minX; } // Rotating image can cause fitting into area problems. // So let's find scaling coefficient float scaleCoeff = 1; if (true.Equals(GetPropertyAsBoolean(Property.AUTO_SCALE))) { if (maxWidth / (float)width < maxHeight / (float)height) { scaleCoeff = maxWidth / (float)width; height *= maxWidth / (float)width; width = maxWidth; } else { scaleCoeff = maxHeight / (float)height; width *= maxHeight / (float)height; height = maxHeight; } } else { if (true.Equals(GetPropertyAsBoolean(Property.AUTO_SCALE_WIDTH))) { scaleCoeff = maxWidth / (float)width; height *= scaleCoeff; width = maxWidth; } else { if (true.Equals(GetPropertyAsBoolean(Property.AUTO_SCALE_HEIGHT))) { scaleCoeff = maxHeight / (float)height; height = maxHeight; width *= scaleCoeff; } } } pivotY *= scaleCoeff; deltaX *= scaleCoeff; return(scaleCoeff); }
public void InverseAffineTransformationTest () { //Local coordinate system MNAU (Kraftwerk Mäuserich) (based on Gau?Krüger using affine transformation) // affine transform // 1) Offset: X=-3454886,640m Y=-5479481,278m; // 2)Rotation: 332,0657, Rotation point X=3456926,640m Y=5481071,278m; // 3) Scale: 1.0 //TODO MathTransformFactory fac = new MathTransformFactory (); double[,] matrix = new double[,] {{0.883485346527455, -0.468458794848877, 3455869.17937689}, {0.468458794848877, 0.883485346527455, 5478710.88035753}, {0.0 , 0.0, 1},}; IMathTransform mt = new AffineTransform (matrix); Assert.IsNotNull (mt); Assert.AreEqual (2, mt.DimSource); Assert.AreEqual (2, mt.DimTarget); //Transformation example (MNAU -> GK) // Start point (MNAU) X=2040,000m Y=1590,000m] // Target point (GK): X=3456926,640m Y=5481071,278m; //check source transform double[] outPt = mt.Transform (new double[] { 2040.0, 1590.0 }); Assert.AreEqual (2, outPt.Length); Assert.AreEqual (3456926.640, outPt[0], 0.00000001); Assert.AreEqual (5481071.278, outPt[1], 0.00000001); IMathTransform invMt = mt.Inverse (); double[] inPt = invMt.Transform (new double[] { 3456926.640, 5481071.278 }); Assert.AreEqual (2, inPt.Length); Assert.AreEqual (2040.0, inPt[0], 0.00000001); Assert.AreEqual (1590.0, inPt[1], 0.00000001); //check source transform - once more double[] outPt2 = mt.Transform (new double[] { 2040.0, 1590.0 }); Assert.AreEqual (2, outPt2.Length); Assert.AreEqual (3456926.640, outPt2[0], 0.00000001); Assert.AreEqual (5481071.278, outPt2[1], 0.00000001); }
public override LayoutResult Layout(LayoutContext layoutContext) { LayoutArea area = layoutContext.GetArea().Clone(); Rectangle layoutBox = area.GetBBox().Clone(); AffineTransform t = new AffineTransform(); Image modelElement = (Image)(GetModelElement()); PdfXObject xObject = modelElement.GetXObject(); imageWidth = modelElement.GetImageWidth(); imageHeight = modelElement.GetImageHeight(); CalculateImageDimensions(layoutBox, t, xObject); OverflowPropertyValue?overflowX = null != parent?parent.GetProperty <OverflowPropertyValue?>(Property.OVERFLOW_X ) : OverflowPropertyValue.FIT; bool nowrap = false; if (parent is LineRenderer) { nowrap = true.Equals(this.parent.GetOwnProperty <bool?>(Property.NO_SOFT_WRAP_INLINE)); } IList <Rectangle> floatRendererAreas = layoutContext.GetFloatRendererAreas(); float clearHeightCorrection = FloatingHelper.CalculateClearHeightCorrection(this, floatRendererAreas, layoutBox ); FloatPropertyValue?floatPropertyValue = this.GetProperty <FloatPropertyValue?>(Property.FLOAT); if (FloatingHelper.IsRendererFloating(this, floatPropertyValue)) { layoutBox.DecreaseHeight(clearHeightCorrection); FloatingHelper.AdjustFloatedBlockLayoutBox(this, layoutBox, width, floatRendererAreas, floatPropertyValue, overflowX); } else { clearHeightCorrection = FloatingHelper.AdjustLayoutBoxAccordingToFloats(floatRendererAreas, layoutBox, width , clearHeightCorrection, null); } ApplyMargins(layoutBox, false); Border[] borders = GetBorders(); ApplyBorderBox(layoutBox, borders, false); float?declaredMaxHeight = RetrieveMaxHeight(); OverflowPropertyValue?overflowY = null == parent || ((null == declaredMaxHeight || declaredMaxHeight > layoutBox .GetHeight()) && !layoutContext.IsClippedHeight()) ? OverflowPropertyValue.FIT : parent.GetProperty <OverflowPropertyValue? >(Property.OVERFLOW_Y); bool processOverflowX = !IsOverflowFit(overflowX) || nowrap; bool processOverflowY = !IsOverflowFit(overflowY); if (IsAbsolutePosition()) { ApplyAbsolutePosition(layoutBox); } occupiedArea = new LayoutArea(area.GetPageNumber(), new Rectangle(layoutBox.GetX(), layoutBox.GetY() + layoutBox .GetHeight(), 0, 0)); float imageItselfScaledWidth = (float)width; float imageItselfScaledHeight = (float)height; if (IsFixedLayout()) { fixedXPosition = this.GetPropertyAsFloat(Property.LEFT); fixedYPosition = this.GetPropertyAsFloat(Property.BOTTOM); } float?angle = this.GetPropertyAsFloat(Property.ROTATION_ANGLE); // See in adjustPositionAfterRotation why angle = 0 is necessary if (null == angle) { angle = 0f; } t.Rotate((float)angle); initialOccupiedAreaBBox = GetOccupiedAreaBBox().Clone(); float scaleCoef = AdjustPositionAfterRotation((float)angle, layoutBox.GetWidth(), layoutBox.GetHeight()); imageItselfScaledHeight *= scaleCoef; imageItselfScaledWidth *= scaleCoef; initialOccupiedAreaBBox.MoveDown(imageItselfScaledHeight); initialOccupiedAreaBBox.SetHeight(imageItselfScaledHeight); initialOccupiedAreaBBox.SetWidth(imageItselfScaledWidth); if (xObject is PdfFormXObject) { t.Scale(scaleCoef, scaleCoef); } GetMatrix(t, imageItselfScaledWidth, imageItselfScaledHeight); // indicates whether the placement is forced bool isPlacingForced = false; if (width > layoutBox.GetWidth() || height > layoutBox.GetHeight()) { if (true.Equals(GetPropertyAsBoolean(Property.FORCED_PLACEMENT)) || (width > layoutBox.GetWidth() && processOverflowX ) || (height > layoutBox.GetHeight() && processOverflowY)) { isPlacingForced = true; } else { ApplyMargins(initialOccupiedAreaBBox, true); ApplyBorderBox(initialOccupiedAreaBBox, true); occupiedArea.GetBBox().SetHeight(initialOccupiedAreaBBox.GetHeight()); return(new MinMaxWidthLayoutResult(LayoutResult.NOTHING, occupiedArea, null, this, this)); } } occupiedArea.GetBBox().MoveDown((float)height); if (borders[3] != null) { height += (float)Math.Sin((float)angle) * borders[3].GetWidth(); } occupiedArea.GetBBox().SetHeight((float)height); occupiedArea.GetBBox().SetWidth((float)width); UnitValue leftMargin = this.GetPropertyAsUnitValue(Property.MARGIN_LEFT); if (!leftMargin.IsPointValue()) { ILog logger = LogManager.GetLogger(typeof(iText.Layout.Renderer.ImageRenderer)); logger.Error(MessageFormatUtil.Format(iText.IO.LogMessageConstant.PROPERTY_IN_PERCENTS_NOT_SUPPORTED, Property .MARGIN_LEFT)); } UnitValue topMargin = this.GetPropertyAsUnitValue(Property.MARGIN_TOP); if (!topMargin.IsPointValue()) { ILog logger = LogManager.GetLogger(typeof(iText.Layout.Renderer.ImageRenderer)); logger.Error(MessageFormatUtil.Format(iText.IO.LogMessageConstant.PROPERTY_IN_PERCENTS_NOT_SUPPORTED, Property .MARGIN_TOP)); } if (0 != leftMargin.GetValue() || 0 != topMargin.GetValue()) { TranslateImage(leftMargin.GetValue(), topMargin.GetValue(), t); GetMatrix(t, imageItselfScaledWidth, imageItselfScaledHeight); } ApplyBorderBox(occupiedArea.GetBBox(), borders, true); ApplyMargins(occupiedArea.GetBBox(), true); if (angle != 0) { ApplyRotationLayout((float)angle); } float unscaledWidth = occupiedArea.GetBBox().GetWidth() / scaleCoef; MinMaxWidth minMaxWidth = new MinMaxWidth(unscaledWidth, unscaledWidth, 0); UnitValue rendererWidth = this.GetProperty <UnitValue>(Property.WIDTH); if (rendererWidth != null && rendererWidth.IsPercentValue()) { minMaxWidth.SetChildrenMinWidth(0); float coeff = imageWidth / (float)RetrieveWidth(area.GetBBox().GetWidth()); minMaxWidth.SetChildrenMaxWidth(unscaledWidth * coeff); } else { bool autoScale = HasProperty(Property.AUTO_SCALE) && (bool)this.GetProperty <bool?>(Property.AUTO_SCALE); bool autoScaleWidth = HasProperty(Property.AUTO_SCALE_WIDTH) && (bool)this.GetProperty <bool?>(Property.AUTO_SCALE_WIDTH ); if (autoScale || autoScaleWidth) { minMaxWidth.SetChildrenMinWidth(0); } } FloatingHelper.RemoveFloatsAboveRendererBottom(floatRendererAreas, this); LayoutArea editedArea = FloatingHelper.AdjustResultOccupiedAreaForFloatAndClear(this, floatRendererAreas, layoutContext.GetArea().GetBBox(), clearHeightCorrection, false); ApplyAbsolutePositionIfNeeded(layoutContext); return(new MinMaxWidthLayoutResult(LayoutResult.FULL, editedArea, null, null, isPlacingForced ? this : null ).SetMinMaxWidth(minMaxWidth)); }
public void DrawRenderableImage(RenderableImage renderableimage, AffineTransform affinetransform) { DrawRenderedImage(renderableimage.CreateDefaultRendering(), affinetransform); }
/// <summary> /// Precomputes the transform to bring triangles from their native local space to the local space of the convex. /// </summary> /// <param name="convexInverseWorldTransform">Inverse of the world transform of the convex shape.</param> /// <param name="fromMeshLocalToConvexLocal">Transform to apply to native local triangles to bring them into the local space of the convex.</param> protected override void PrecomputeTriangleTransform(ref AffineTransform convexInverseWorldTransform, out AffineTransform fromMeshLocalToConvexLocal) { //StaticMeshes only have transformable mesh data. var data = ((TransformableMeshData)mesh.Mesh.Data); AffineTransform.Multiply(ref data.worldTransform, ref convexInverseWorldTransform, out fromMeshLocalToConvexLocal); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 13JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Returns an iteration object that defines the boundary of this * flattened <code>Line</code>. * The iterator for this class is not multi-threaded safe, * which means that this <code>Line</code> class does not * guarantee that modifications to the geometry of this * <code>Line</code> object do not affect any iterations of that * geometry that are already in process. * @param at the specified <code>AffineTransform</code> * @param flatness the maximum amount that the control points for a * given curve can vary from colinear before a subdivided * curve is replaced by a straight line connecting the * end points. Since a <code>Line</code> object is * always flat, this parameter is ignored. * @return a <code>PathIterator</code> that defines the boundary of the * flattened <code>Line</code> */ public PathIterator GetPathIterator(AffineTransform at, int flatness) { return new LineIterator(this, at); }
void ComputeShapeInformation(TransformableMeshData data, out ShapeDistributionInformation shapeInformation) { //Compute the surface vertices of the shape. surfaceVertices.Clear(); try { ConvexHullHelper.GetConvexHull(data.vertices, surfaceVertices); for (int i = 0; i < surfaceVertices.count; ++i) { AffineTransform.Transform(ref surfaceVertices.Elements[i], ref data.worldTransform, out surfaceVertices.Elements[i]); } } catch { surfaceVertices.Clear(); //If the convex hull failed, then the point set has no volume. A mobile mesh is allowed to have zero volume, however. //In this case, compute the bounding box of all points. BoundingBox box = new BoundingBox(); for (int i = 0; i < data.vertices.Length; ++i) { Vector3 v; data.GetVertexPosition(i, out v); if (v.X > box.Max.X) { box.Max.X = v.X; } if (v.X < box.Min.X) { box.Min.X = v.X; } if (v.Y > box.Max.Y) { box.Max.Y = v.Y; } if (v.Y < box.Min.Y) { box.Min.Y = v.Y; } if (v.Z > box.Max.Z) { box.Max.Z = v.Z; } if (v.Z < box.Min.Z) { box.Min.Z = v.Z; } } //Add the corners. This will overestimate the size of the surface a bit. surfaceVertices.Add(box.Min); surfaceVertices.Add(box.Max); surfaceVertices.Add(new Vector3(box.Min.X, box.Min.Y, box.Max.Z)); surfaceVertices.Add(new Vector3(box.Min.X, box.Max.Y, box.Min.Z)); surfaceVertices.Add(new Vector3(box.Max.X, box.Min.Y, box.Min.Z)); surfaceVertices.Add(new Vector3(box.Min.X, box.Max.Y, box.Max.Z)); surfaceVertices.Add(new Vector3(box.Max.X, box.Max.Y, box.Min.Z)); surfaceVertices.Add(new Vector3(box.Max.X, box.Min.Y, box.Max.Z)); } shapeInformation.Center = new Vector3(); if (solidity == MobileMeshSolidity.Solid) { //The following inertia tensor calculation assumes a closed mesh. shapeInformation.Volume = 0; for (int i = 0; i < data.indices.Length; i += 3) { Vector3 v2, v3, v4; data.GetTriangle(i, out v2, out v3, out v4); //Determinant is 6 * volume. It's signed, though; this is because the mesh isn't necessarily convex nor centered on the origin. float tetrahedronVolume = v2.X * (v3.Y * v4.Z - v3.Z * v4.Y) - v3.X * (v2.Y * v4.Z - v2.Z * v4.Y) + v4.X * (v2.Y * v3.Z - v2.Z * v3.Y); shapeInformation.Volume += tetrahedronVolume; shapeInformation.Center += tetrahedronVolume * (v2 + v3 + v4); } shapeInformation.Center /= shapeInformation.Volume * 4; shapeInformation.Volume /= 6; shapeInformation.Volume = Math.Abs(shapeInformation.Volume); data.worldTransform.Translation -= shapeInformation.Center; //Source: Explicit Exact Formulas for the 3-D Tetrahedron Inertia Tensor in Terms of its Vertex Coordinates //http://www.scipub.org/fulltext/jms2/jms2118-11.pdf //x1, x2, x3, x4 are origin, triangle1, triangle2, triangle3 //Looking to find inertia tensor matrix of the form // [ a -b' -c' ] // [ -b' b -a' ] // [ -c' -a' c ] float a = 0, b = 0, c = 0, ao = 0, bo = 0, co = 0; float totalWeight = 0; for (int i = 0; i < data.indices.Length; i += 3) { Vector3 v2, v3, v4; data.GetTriangle(i, out v2, out v3, out v4); //Determinant is 6 * volume. It's signed, though; this is because the mesh isn't necessarily convex nor centered on the origin. float tetrahedronVolume = v2.X * (v3.Y * v4.Z - v3.Z * v4.Y) - v3.X * (v2.Y * v4.Z - v2.Z * v4.Y) + v4.X * (v2.Y * v3.Z - v2.Z * v3.Y); totalWeight += tetrahedronVolume; a += tetrahedronVolume * (v2.Y * v2.Y + v2.Y * v3.Y + v3.Y * v3.Y + v2.Y * v4.Y + v3.Y * v4.Y + v4.Y * v4.Y + v2.Z * v2.Z + v2.Z * v3.Z + v3.Z * v3.Z + v2.Z * v4.Z + v3.Z * v4.Z + v4.Z * v4.Z); b += tetrahedronVolume * (v2.X * v2.X + v2.X * v3.X + v3.X * v3.X + v2.X * v4.X + v3.X * v4.X + v4.X * v4.X + v2.Z * v2.Z + v2.Z * v3.Z + v3.Z * v3.Z + v2.Z * v4.Z + v3.Z * v4.Z + v4.Z * v4.Z); c += tetrahedronVolume * (v2.X * v2.X + v2.X * v3.X + v3.X * v3.X + v2.X * v4.X + v3.X * v4.X + v4.X * v4.X + v2.Y * v2.Y + v2.Y * v3.Y + v3.Y * v3.Y + v2.Y * v4.Y + v3.Y * v4.Y + v4.Y * v4.Y); ao += tetrahedronVolume * (2 * v2.Y * v2.Z + v3.Y * v2.Z + v4.Y * v2.Z + v2.Y * v3.Z + 2 * v3.Y * v3.Z + v4.Y * v3.Z + v2.Y * v4.Z + v3.Y * v4.Z + 2 * v4.Y * v4.Z); bo += tetrahedronVolume * (2 * v2.X * v2.Z + v3.X * v2.Z + v4.X * v2.Z + v2.X * v3.Z + 2 * v3.X * v3.Z + v4.X * v3.Z + v2.X * v4.Z + v3.X * v4.Z + 2 * v4.X * v4.Z); co += tetrahedronVolume * (2 * v2.X * v2.Y + v3.X * v2.Y + v4.X * v2.Y + v2.X * v3.Y + 2 * v3.X * v3.Y + v4.X * v3.Y + v2.X * v4.Y + v3.X * v4.Y + 2 * v4.X * v4.Y); } float density = 1 / totalWeight; float diagonalFactor = density / 10; float offFactor = -density / 20; a *= diagonalFactor; b *= diagonalFactor; c *= diagonalFactor; ao *= offFactor; bo *= offFactor; co *= offFactor; shapeInformation.VolumeDistribution = new Matrix3X3(a, bo, co, bo, b, ao, co, ao, c); } else { shapeInformation.Center = new Vector3(); float totalWeight = 0; for (int i = 0; i < data.indices.Length; i += 3) { //Configure the inertia tensor to be local. Vector3 vA, vB, vC; data.GetTriangle(i, out vA, out vB, out vC); Vector3 vAvB; Vector3 vAvC; Vector3.Subtract(ref vB, ref vA, out vAvB); Vector3.Subtract(ref vC, ref vA, out vAvC); Vector3 cross; Vector3.Cross(ref vAvB, ref vAvC, out cross); float weight = cross.Length(); totalWeight += weight; shapeInformation.Center += weight * (vA + vB + vC) / 3; } shapeInformation.Center /= totalWeight; shapeInformation.Volume = 0; data.worldTransform.Translation -= shapeInformation.Center; shapeInformation.VolumeDistribution = new Matrix3X3(); for (int i = 0; i < data.indices.Length; i += 3) { //Configure the inertia tensor to be local. Vector3 vA, vB, vC; data.GetTriangle(i, out vA, out vB, out vC); Vector3 vAvB; Vector3 vAvC; Vector3.Subtract(ref vB, ref vA, out vAvB); Vector3.Subtract(ref vC, ref vA, out vAvC); Vector3 cross; Vector3.Cross(ref vAvB, ref vAvC, out cross); float weight = cross.Length(); totalWeight += weight; Matrix3X3 innerProduct; Matrix3X3.CreateScale(vA.LengthSquared(), out innerProduct); Matrix3X3 outerProduct; Matrix3X3.CreateOuterProduct(ref vA, ref vA, out outerProduct); Matrix3X3 contribution; Matrix3X3.Subtract(ref innerProduct, ref outerProduct, out contribution); Matrix3X3.Multiply(ref contribution, weight, out contribution); Matrix3X3.Add(ref shapeInformation.VolumeDistribution, ref contribution, out shapeInformation.VolumeDistribution); Matrix3X3.CreateScale(vB.LengthSquared(), out innerProduct); Matrix3X3.CreateOuterProduct(ref vB, ref vB, out outerProduct); Matrix3X3.Subtract(ref innerProduct, ref outerProduct, out outerProduct); Matrix3X3.Multiply(ref contribution, weight, out contribution); Matrix3X3.Add(ref shapeInformation.VolumeDistribution, ref contribution, out shapeInformation.VolumeDistribution); Matrix3X3.CreateScale(vC.LengthSquared(), out innerProduct); Matrix3X3.CreateOuterProduct(ref vC, ref vC, out outerProduct); Matrix3X3.Subtract(ref innerProduct, ref outerProduct, out contribution); Matrix3X3.Multiply(ref contribution, weight, out contribution); Matrix3X3.Add(ref shapeInformation.VolumeDistribution, ref contribution, out shapeInformation.VolumeDistribution); } Matrix3X3.Multiply(ref shapeInformation.VolumeDistribution, 1 / (6 * totalWeight), out shapeInformation.VolumeDistribution); } ////Configure the inertia tensor to be local. //Vector3 finalOffset = shapeInformation.Center; //Matrix3X3 finalInnerProduct; //Matrix3X3.CreateScale(finalOffset.LengthSquared(), out finalInnerProduct); //Matrix3X3 finalOuterProduct; //Matrix3X3.CreateOuterProduct(ref finalOffset, ref finalOffset, out finalOuterProduct); //Matrix3X3 finalContribution; //Matrix3X3.Subtract(ref finalInnerProduct, ref finalOuterProduct, out finalContribution); //Matrix3X3.Subtract(ref shapeInformation.VolumeDistribution, ref finalContribution, out shapeInformation.VolumeDistribution); }
///<summary> /// Transforms a vector by an affine transform. ///</summary> ///<param name="position">Position to transform.</param> ///<param name="transform">Transform to apply.</param> ///<param name="transformed">Transformed position.</param> public static void Transform(ref Vector3 position, ref AffineTransform transform, out Vector3 transformed) { Matrix3x3.Transform(ref position, ref transform.LinearTransform, out transformed); Vector3.Add(ref transformed, ref transform.Translation, out transformed); }
///<summary> /// Updates the time of impact for the pair. ///</summary> ///<param name="requester">Collidable requesting the update.</param> ///<param name="dt">Timestep duration.</param> public override void UpdateTimeOfImpact(Collidable requester, float dt) { //Notice that we don't test for convex entity null explicitly. The convex.IsActive property does that for us. if (convex.IsActive && convex.entity.PositionUpdateMode == PositionUpdateMode.Continuous) { //TODO: This system could be made more robust by using a similar region-based rejection of edges. //CCD events are awfully rare under normal circumstances, so this isn't usually an issue. //Only perform the test if the minimum radii are small enough relative to the size of the velocity. Vector3 velocity; Vector3.Multiply(ref convex.entity.linearVelocity, dt, out velocity); float velocitySquared = velocity.LengthSquared(); var minimumRadius = convex.Shape.minimumRadius * MotionSettings.CoreShapeScaling; timeOfImpact = 1; if (minimumRadius * minimumRadius < velocitySquared) { var triangle = PhysicsResources.GetTriangle(); triangle.collisionMargin = 0; //Spherecast against all triangles to find the earliest time. for (int i = 0; i < MeshManifold.overlappedTriangles.Count; i++) { MeshBoundingBoxTreeData data = instancedMesh.Shape.TriangleMesh.Data; int triangleIndex = MeshManifold.overlappedTriangles.Elements[i]; data.GetTriangle(triangleIndex, out triangle.vA, out triangle.vB, out triangle.vC); AffineTransform.Transform(ref triangle.vA, ref instancedMesh.worldTransform, out triangle.vA); AffineTransform.Transform(ref triangle.vB, ref instancedMesh.worldTransform, out triangle.vB); AffineTransform.Transform(ref triangle.vC, ref instancedMesh.worldTransform, out triangle.vC); //Put the triangle into 'localish' space of the convex. Vector3.Subtract(ref triangle.vA, ref convex.worldTransform.Position, out triangle.vA); Vector3.Subtract(ref triangle.vB, ref convex.worldTransform.Position, out triangle.vB); Vector3.Subtract(ref triangle.vC, ref convex.worldTransform.Position, out triangle.vC); RayHit rayHit; if (GJKToolbox.CCDSphereCast(new Ray(Toolbox.ZeroVector, velocity), minimumRadius, triangle, ref Toolbox.RigidIdentity, timeOfImpact, out rayHit) && rayHit.T > Toolbox.BigEpsilon) { if (instancedMesh.sidedness != TriangleSidedness.DoubleSided) { Vector3 AB, AC; Vector3.Subtract(ref triangle.vB, ref triangle.vA, out AB); Vector3.Subtract(ref triangle.vC, ref triangle.vA, out AC); Vector3 normal; Vector3.Cross(ref AB, ref AC, out normal); float dot; Vector3.Dot(ref normal, ref rayHit.Normal, out dot); //Only perform sweep if the object is in danger of hitting the object. //Triangles can be one sided, so check the impact normal against the triangle normal. if (instancedMesh.sidedness == TriangleSidedness.Counterclockwise && dot < 0 || instancedMesh.sidedness == TriangleSidedness.Clockwise && dot > 0) { timeOfImpact = rayHit.T; } } else { timeOfImpact = rayHit.T; } } } PhysicsResources.GiveBack(triangle); } } }
private static IMathTransform ReadAffineTransform (WktStreamTokenizer tokenizer) { /* PARAM_MT[ "Affine", PARAMETER["num_row",3], PARAMETER["num_col",3], PARAMETER["elt_0_0", 0.883485346527455], PARAMETER["elt_0_1", -0.468458794848877], PARAMETER["elt_0_2", 3455869.17937689], PARAMETER["elt_1_0", 0.468458794848877], PARAMETER["elt_1_1", 0.883485346527455], PARAMETER["elt_1_2", 5478710.88035753], PARAMETER["elt_2_2", 1] ] */ //tokenizer stands on the first PARAMETER if (tokenizer.GetStringValue () != "PARAMETER") tokenizer.ReadToken ("PARAMETER"); IParameterInfo paramInfo = ReadParameters (tokenizer); //manage required parameters - row, col var rowParam = paramInfo.GetParameterByName ("num_row"); var colParam = paramInfo.GetParameterByName ("num_col"); if (rowParam == null) { throw new ArgumentNullException ("Affine transform does not contain 'num_row' parameter"); } if (colParam == null) { throw new ArgumentNullException ("Affine transform does not contain 'num_col' parameter"); } int rowVal = (int)rowParam.Value; int colVal = (int)colParam.Value; if (rowVal <= 0) { throw new ArgumentException ("Affine transform contains invalid value of 'num_row' parameter"); } if (colVal <= 0) { throw new ArgumentException ("Affine transform contains invalid value of 'num_col' parameter"); } //creates working matrix; double[,] matrix = new double[rowVal, colVal]; //simply process matrix values - no elt_ROW_COL parsing foreach (var param in paramInfo.Parameters) { if (param == null || param.Name == null) { continue; } switch (param.Name) { case "num_row": case "num_col": break; case "elt_0_0": matrix[0, 0] = param.Value; break; case "elt_0_1": matrix[0, 1] = param.Value; break; case "elt_0_2": matrix[0, 2] = param.Value; break; case "elt_0_3": matrix[0, 3] = param.Value; break; case "elt_1_0": matrix[1, 0] = param.Value; break; case "elt_1_1": matrix[1, 1] = param.Value; break; case "elt_1_2": matrix[1, 2] = param.Value; break; case "elt_1_3": matrix[1, 3] = param.Value; break; case "elt_2_0": matrix[2, 0] = param.Value; break; case "elt_2_1": matrix[2, 1] = param.Value; break; case "elt_2_2": matrix[2, 2] = param.Value; break; case "elt_2_3": matrix[2, 3] = param.Value; break; case "elt_3_0": matrix[3, 0] = param.Value; break; case "elt_3_1": matrix[3, 1] = param.Value; break; case "elt_3_2": matrix[3, 2] = param.Value; break; case "elt_3_3": matrix[3, 3] = param.Value; break; default: //unknown parameter break; } } //read rest of WKT if (tokenizer.GetStringValue () != "]") tokenizer.ReadToken ("]"); //use "matrix" constructor to create transformation matrix IMathTransform affineTransform = new AffineTransform (matrix); return affineTransform; }
/// <summary> /// Creates an affine transform from a rigid transform. /// </summary> /// <param name="rigid">Rigid transform to base the affine transform on.</param> /// <param name="affine">Affine transform created from the rigid transform.</param> public static void CreateFromRigidTransform(ref RigidTransform rigid, out AffineTransform affine) { affine.Translation = rigid.Position; Matrix3x3.CreateFromQuaternion(ref rigid.Orientation, out affine.LinearTransform); }
///<summary> /// Transforms a vector using an affine transform. ///</summary> ///<param name="position">Position to transform.</param> ///<param name="affineTransform">Transform to apply.</param> ///<returns>Transformed position.</returns> public static Vector3 Transform(Vector3 position, AffineTransform affineTransform) { Vector3 toReturn; Transform(ref position, ref affineTransform, out toReturn); return toReturn; }
///<summary> /// Multiplies a rigid transform by an affine transform. ///</summary> ///<param name="a">Rigid transform.</param> ///<param name="b">Affine transform.</param> ///<param name="transform">Combined transform.</param> public static void Multiply(ref RigidTransform a, ref AffineTransform b, out AffineTransform transform) { Matrix3x3 linearTransform;//Have to use temporary variable just in case b reference is transform. Matrix3x3.CreateFromQuaternion(ref a.Orientation, out linearTransform); Matrix3x3.Multiply(ref linearTransform, ref b.LinearTransform, out linearTransform); Vector3 translation; Matrix3x3.Transform(ref a.Position, ref b.LinearTransform, out translation); Vector3.Add(ref translation, ref b.Translation, out transform.Translation); transform.LinearTransform = linearTransform; }
/// <summary> /// Multiplies a transform by another transform. /// </summary> /// <param name="a">First transform.</param> /// <param name="b">Second transform.</param> /// <param name="transform">Combined transform.</param> public static void Multiply(ref AffineTransform a, ref AffineTransform b, out AffineTransform transform) { Matrix3x3 linearTransform;//Have to use temporary variable just in case a or b reference is transform. Matrix3x3.Multiply(ref a.LinearTransform, ref b.LinearTransform, out linearTransform); Vector3 translation; Matrix3x3.Transform(ref a.Translation, ref b.LinearTransform, out translation); Vector3.Add(ref translation, ref b.Translation, out transform.Translation); transform.LinearTransform = linearTransform; }
///<summary> /// Inverts an affine transform. ///</summary> ///<param name="transform">Transform to invert.</param> /// <param name="inverse">Inverse of the transform.</param> public static void Invert(ref AffineTransform transform, out AffineTransform inverse) { Matrix3x3.Invert(ref transform.LinearTransform, out inverse.LinearTransform); Matrix3x3.Transform(ref transform.Translation, ref inverse.LinearTransform, out inverse.Translation); Vector3.Negate(ref inverse.Translation, out inverse.Translation); }
/** * Auto-shapes are defined in the [0,21600] coordinate system. * We need to transform it into normal slide coordinates * */ public static java.awt.Shape transform(java.awt.Shape outline, Rectangle2D anchor){ AffineTransform at = new AffineTransform(); at.translate(anchor.GetX(), anchor.GetY()); at.scale( 1.0f/21600*anchor.Width, 1.0f/21600*anchor.Height ); return at.CreateTransformedShape(outline); }