Applying rotation to Graphics object - graphics

I have very little experience programming with graphics objects. I am currently tasked with exporting a document (.tiff image) with redacted annotations. The redacted annotation is just a black rectangle object. I am able to get the x coordinates, y coordinates, width and height properties through the .XMP data. There is also a property called rotatation. This is where I am getting stuck, applying the rotation.
So, imagine a document with a redaction on it blacking out the first paragraph. Then, using a tool in the editor the user rotates the document so that it is now laying on it's side. The client is able to render the redaction correctly because we are using the Atalasoft controls to get and display annotations. Now we have a web service that will go and retrieve that image with redactions. We are not able to use the Atalasoft controls in this service due to licensing issues so we just extract the .XMP data from the .tiff image and manually draw the redactions. The problem is, if the user rotates the document when the redaction is already on the document I am having a hard time getting the redaction to rotate correctly (due to my lack of knowledge on graphics programming). If I do not apply any rotation, the redaction is displayed where it was BEFORE the document had been rotated, thus redacting the wrong area of the document.
Here is what I have tried:
Dim rectangle As New Rectangle(xCoordinate, yCoordinate, width, height)
graphics.RotateTransform(rotation)
graphics.FillRectangle(Brushes.Black, rectangle)
When I do this, the redaction does not show up at all on the final document. I have read that I may need to call the following before applying the rotation:
graphics.TranslateTransform(x,y)
But I have no idea what I should be passing in as x and y. It seems like I just need to get the rotation to apply from the upper left corner of the rectangle, but I have yet to figure out a way to properly do this.
Thank you so much for any help or pushes in the right direction!
EDIT 1:
I have also tried this (taken from How can I rotate an RectangleF at a specific degree using Graphics object?).
Dim rectangle As New Rectangle(xCoordinate, yCoordinate, width, height)
Using rotationMatrix As New Matrix
rotationMatrix.RotateAt(rotation, New PointF(rectangle.Left + (rectangle.Width / 2), rectangle.Top + (rectangle.Height / 2)))
graphics.Transform = rotationMatrix
graphics.FillRectangle(Brushes.Black, rectangle)
graphics.ResetTransform()
End Using
Which does rotate the rectangle, but it ends up in the wrong spot so it is not redacting the correct portion of the document. Once again, when I display the document without any rotation transform, it looks like the redaction simply needs to be rotated using the upper left corner as an axis but I'm not quite sure how to accomplish that.

Figured it out. Here is how I am rotating a rectangle using the upper left-hand corner as the axis:
Dim rectangle As New Rectangle(xCoordinate, yCoordinate, width, height)
Using rotationMatrix As New Matrix
rotationMatrix.RotateAt(rotation, New PointF(rectangle.Left, rectangle.Top))
graphics.Transform = rotationMatrix
graphics.FillRectangle(Brushes.Black, rectangle)
graphics.ResetTransform()
End Using

Related

Recalculating path's array after modification - fabricjs

After moving, rescaling or rotating a path in fabricjs, I would like to recalculate the path's array coordinates in order to use them later to draw the exact same path on a plain HTML5 canvas.
I have gotten around rotation by storing the angle and then performing a transformation of the whole html canvas. For translation I tried recalculating the points like so:
point[1] = (point[1] + modifiedObject.left - oldState.left);
point[2] = (point[2] + modifiedObject.top - oldState.top);
but this messes up with rescaling on fabric.
I also tried using the transformation matrix on the points, but this didn't work either and I think it's because I am missing some steps in between.
Any help would be appreciated.
Here's a simple demo of what I'm trying to do in essence: https://jsfiddle.net/1b68eLdr/86688/

Kivy rotation during movement

I'm struggling with how to properly implement simultaneous movement and rotation using Kivy (in python, not kv lang). My goal is to rotate an object so it's facing its destination then move it towards the destination using Animation. Using the code below I typically get movement in relation to the angle rotated instead of in relation to my general playing area. For example the animation without rotation might move an image to point [1,1] whereas with rotation of 180* the animation is moving the image to [-1,-1]. The image is properly rotated in this scenario, meaning it's facing the right way but going the wrong way.
My understanding is that the push/pop matrix functions should provide the appropriate context for the animation rather than the rotated element context. Because the PopMatrix function is happening in Canvas.after it seems like this has no effect - my animation is completed before the original Matrix is restored.
I'm lacking some key piece of information here that's causing a lot of headache. Can someone explain why the code below causes an image to move to (-1,-1) rather than the (1,1) indicated, and how to properly implement this?
I threw this code together as an example, my game code is far more complex. That's why I'm hoping for an explanation rather than a direct solution for my code. Thanks.
with self.image.canvas.before:
PushMatrix()
self.rot = Rotate()
self.rot.axis = (0, 0, 1)
self.rot.origin=self.center
self.rot.angle=180
with self.image.canvas.after:
PopMatrix()
self.anim = Animation(pos = (1,1), duration=1)
self.anim.start(self)
self.image.pos = self.pos
self.image.size = self.size
In case others are interested in how to make this work consistently - I've found that setting origin and angle on each frame, along with binding the image widget to any pos change on it's parent will ensure the widget moves with its parent and in the proper direction. I implemented that like this:
Instantiate the image like this:
with self.image.canvas.before:
PushMatrix()
self.rot = Rotate()
self.rot.axis = (0, 0, 1)
self.rot.origin=self.center
self.rot.angle = 0
with self.image.canvas.after:
PopMatrix()
Bind it like this:
self.bind(pos = self.binding)
def binding(self, *args):
self.image.center = self.center
self.image.size = self.size
On each frame call a function that does similar to the below.
self.rot.origin = self.center
self.rot.angle = getangle()#you can use a set angle or generate a new angle every frame
Rotate effectively changes the coordinate system used by the entire canvas, so after you've rotated by 180 degrees the position [1, 1] really is in the opposite direction to what it was before, as far as any canvas instruction is concerned.
I don't know what self.image is (maybe an Image widget?), but presumably whatever you see is something like a Rectangle drawn on its canvas, whose pos and size match those of the widget. When you update that pos and size, the Rectangle is positioned according to the current coordinate system, which is in the rotated frame.
Thinking about it, I'm not sure if there's a neat way to combine Rotate instructions with Kivy's high level widget coordinates in quite this way. Of course you can work around it in various ways, such as by accounting for the rotation when setting the position of the Rectangle, but that's kind of fiddly, and inconvenient when working with prebuilt widgets. You can also look at what the Scatter widget does to enable arbitrary transformations.
If you just want to rotate by 180 degrees, you can instead adjust the image being displayed, either before displaying it or by adjusting the tex_coords of the Rectangle to change the displayed orientation. However, this won't work for arbitrary rotations, which it looks like you may want.

Snap SVG - Check if one transformed rectangle is completely inside of another?

I'm using Snap SVG to manipulate SVGs within a web app that I'm making. In this web app I have two rectangles that start out with one being inside of the other, call them rectInner and rectOuter. The aim is to allow the user to transform rectOuter (scale, rotate, translate) such that rectInner is always strictly inside of rectOuter. To be clear, rectInner will never move or be transformed.
My approach to this problem is to get the bounding box of both rectInner and rectOuter, and check to see if the first is strictly contained within the second. Snap SVG provides a function isBBoxIntersect(rectInner, rectOuter), but it only tells me if parts of the bounding boxes intersect, not if one is contained within the other.
Is there a simple way of doing this?
EDIT:
It seems now that I somewhat misunderstood the concept of bounding boxes, but the problem should be simpler. If I can find a way of calculating the four vertices of rectOuter after all of the transformations, then so long as the corners of rectInner are inside the of the path constructed from those vertices, the entire rectangle is. I think.
##### coffeescript
el = Snap('rect#outer')
mat = el.attr('transform').totalMatrix
left = +el.attr('x')
top = +el.attr('y')
right = left + (+el.attr('width'))
bottom = top + (+el.attr('height'))
console.log(left, top, right, bottom)
points = {
x: mat.x(left, top)
y: mat.y(left, top)
x2:mat.x(right, top)
y2:mat.y(right, top)
x3:mat.x(right, bottom)
y3:mat.y(right, bottom )
x4:mat.x(left, bottom)
y4:mat.y(left, bottom)
}
use matrix!
you can find more matrix in mat variable.
if totalMatrix didn't work then try another.

How do I rotate or scale (transform) an SVG path relative to its center point?

I'm trying to rotate and scale shapes within an SVG around their center point. I've looked into several libraries, including Jquery, Greensock, D3, RaphaelJS, but I haven't been able to find any that provide a straightforward way to accomplish this. Each animates the shape from the origin point (which I understand is the default). I want to be able to spin a shape around its center point or scale it up or down from the center point.
Here are a couple examples using Greensock and D3 that illustrate the default behavior: http://jsbin.com/AHEXiPa/1/edit?html,js,output
Each of these examples bounce in and out from the top left as opposed to remaining stationary and expanding from the center of the triangle out in all directions.
Can one of the libraries I mentioned accomplish this, or is there another library or method I should consider?
Ideally, I need to be able to apply the animation/transform to an existing object in the DOM. D3 is good at this for instance, but Raphael seems to require converting an SVG to Raphael first prior to injecting it into the DOM.
Really its a case of pick the library that suits your needs, and then you will figure a way. As BigBadaboom says, if you do a search, there are lots of solutions.
To try and combine your questions, as sometimes the tricky bit is using an existing DOM object, I've included an example in Snap.svg. You can often do something similar in most libraries.
jsfiddle here Fiddle using your existing html.
s = Snap("#mySVGContainer1"); // create a canvas from existing svg
var triangle1 = s.select("#myShape1").transform("r90"); //select&transform existing object
p = Snap("#mySVGContainer2");
var triangle2 = p.select("#myShape2");
var bbox = triangle2.getBBox(); //bounding box, centre cx/cy
//rotate and scale with transform string (raphael/snap format)
triangle2.animate({ transform: "r180," + bbox.cx + ',' + bbox.cy + "s3,3," + bbox.cx + "," + bbox.cy }, 2000);
For rotations, as #Ian points out, you can specify the center of rotation. For other transformations, changes are defined relative to the path's (0,0) point.
The easiest way to get transformations to work relative to the path's center is to either:
Define the path so that it is centered around the (0,0) point; or
Wrap the path in a <g> element, and then translate it so it is centered on the (0,0) point of the <g> element's coordinate system.
Then, you can apply rotations, scales and transforms (on the <g> element, if using) and they will all be nicely centred.
The trickiest part is figuring out the "center" of an arbitrary shape. #Ian's approach of using the center of the bounding box will usually give decent results. If your shape is a polygon there are d3 functions you could use.
Example showing a shape moving with the mouse, rotating and changing scale, all centered around the center of the bounding box:
http://fiddle.jshell.net/LgfE3/
Edit: simplier jsfiddle
I've been looking for a long time, and will settle for the following.
1. Design your svg shape at coordinate x:0,y:0.
2. Identify by hand the center of rotation, by example, center = [ x:50,y:100].
3. Build a spinIt() function such :
function spinIt() {
needle.transition()
.duration(2000)
.attrTween("transform", tween);
function tween() {
return d3.interpolateString("rotate(-180, 50, 100)", "rotate(90, 50, 100)");
}
}
4. Use it on a triger:
svg.on("click", spinIt);
http://jsfiddle.net/SHF2M/79/

Coordinate system and sprite transformation

I'm using andengine to create a physic simulation via box2d.
The bodies are created through PhysicsFactory using Sprites.
My idea is to procedurally position these sprites, following this pattern:
basically one central sprites which represent my world coordinates center, and a series of cloned sprites that are created by rotating the base sprite around myWorld center (the "X" inside the circle).
I've tried to use opengl way inside andengine (translate, rotate, back-translate)
super(stamiRadious, 0, image); //stamiDoadious is te distance from radix (world center) and "petal" attach point
this.setRotationCenter(0, 0);
this.setRotation((float) Math.toDegrees(angleRad));
this.setPosition(this.getX()+radixX, this.getY()+radixY);
but i failed: results are not right (wrong final position, and wrong box2d body property as if the sprite is much larger than the image)
I belive part of the problem relies on my interpretation on setRotation and setRotationCenter, and in general on my understanding of andengine coordinates system + box2d cordinates system.
Any thoughts/links to doc/explanation?
Once you created a Physics representation (Body) of a Sprite, you should be very careful on how you modify the Sprite! Usually you don't modify the Sprite anymore at all, but instead modify the Body, by calling
someBody.setTransform(); // Note that positions must be divided by PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT!
Hope that helped :)

Resources