Determine coordinates of rotated rectangle - javascript

I'm creating an utility application that should detect and report the coordinates of the corners of a transparent rectangle (alpha=0) within an image.
So far, I've set up a system with Javascript + Canvas that displays the image and starts a floodfill-like operation when I click inside the transparent rectangle in the image. It correctly determines the bounding box of the floodfill operation and as such can provide me the correct coordinates.
Here's my implementation so-far: http://www.scriptorama.nl/image/ (works in recent Firefox / Safari ).
However, the bounding box approach breaks down then the transparent rectangle is rotated (CW or CCW) as the resulting bounding box no longer properly represents the proper width and height. I've tried to come up with a few alternatives to detect to corners, but have not been able to think up a proper solution.
So, does anyone have any suggestions on how I might approach this so I can properly detect the coordinates of 4 corners of the rotated rectangle?

I think you can do this with a simple extension to your existing solution: walk along each of the 4 edges of the bounding box, looking for transparent pixels:
In the non-rotated case, all the pixels along each edge of the box will be transparent.
In the rotated case, there must be one corner touching each edge of the box. This will be at the transparent pixel furthest away from the middle of the edge (there may be more than one due to aliasing, e.g. if the rectangle is only very slightly rotated).

Related

Move and resize inner rectangle shapes as parent rectangle resizes

I have a scenario where a rectangle is drawn inside another rectangle.
Now the user is dragging, for example purposes, let's take the RIGHT border of the larger rectangle. I want to at the same time resize the inner rectangle as well, but it turns out it is not as trivial task as I thought so. In the image bellow is the expected result but if you look closely not only the rectangle expanded but it also moved for a certain distance to the right!
Now I tried and tried to find a formula how much to move the inner shape before expanding it to the right but continuously failed... Just scaling the inner rectangle is not a good solution because if there is another rectangle inside next to it, the first one will go over the second one if they do not move for a certain distance like bellow:
The question is valid only for one-sided drag and expand, not for all sides scale by keeping aspect ratio... Any input is appreciated.
You can scale both the coordinates and lengths, e.g. if you scale the width of the outer rectangle by 2, you can multiply the lengths and x-coordinates of the two inner rectangles by 2.

algorithm - hit detection of rectangle inside rotated rectangle

I am working on an image editor project, where you can rotate and crop an image.
The problem I'm currently facing is once I've rotated the image, I'd like to be able to drag the crop box anywhere inside the boundaries of the rotated image. So far I've been looking at the Liang-Barsky and Cohen-Sutherland line-clipping algorithms, and Separating Axis Theorem, but I'm struggling to see how I can implement these for my use case.
Can anyone point me in the right direction? Am I barking up the wrong tree?
Use the comment by Alain. To check insideness of the corners, it suffices to counter-rotate the image to make its edges axis-aligned. Then you have an easy point-in-axis-aligned-box problem.
(I don't mean that you really have to rotate the image, just the geometry.)
If the movement that the user tries to make is [dx,dy] then consider the line segments from the corners of the selection to those points translated by [dx,dy] (the yellow lines in the example below). These lines may intersect with the rotated image boundaries (green lines) at certain points (the red dots). If there are no intersections, then the movement is legal. If there are one or more intersections, these will tell you up to which point the movement was legal; the intersection point which is closest to its original position (checking either horizontal or vertical distance is enough to establish this) determines the maximum movement (the bottom right corner in the example). You can then limit the translation to this point.
Depending on which quadrant the direction of the movement is in (towards top right in the example) you can skip checking one of the corners (the bottom left corner in the example); the other corners will always bump into the boundaries first.
You can also skip checking two of the boundaries (bottom and left in the example), by comparing the direction of the movement with the rotation angle of the image.
So you need to check for intersections of 3 line segments with 2 line segments. For line segment intersection code, see e.g. this question.
If the user is dragging only one side, and extending the rectangle instead of moving it, then you only have to check the two corners that are moving.

Jagged edges on canvas shape when colours change

I currently have an issue whereby changing the fillStyle of a canvas is causing a smooth diagonal line to turn jagged and I don't know why.
I've created a JSBin where you can see the effect here: http://jsbin.com/fadeyiva/1/edit
I've set the background colour to black so you can more easily see the canvas and the jagged edge. The grey shape is the canvas, if you scroll down to the bottom of the page and then back up it should trigger the waypoint and change the canvas colour to orange.
However, if you look at the bottom diagonal line it starts off smooth when it's grey but when it changes colour the edge becomes very jagged. I don't know why this is happening because the code is only changing the fillStyle, it's not altering the shape of the canvas at all.
The reason is because your angled box is originally being drawn in your canvas with respect to dithering (this is taken care of natively). When you apply a fill change as you are, you throw out the idea of dithering and simply make every single pixel of the object the same color. The edges of the object need to blend with the background (thats what dithering means).
I suggest instead of just adjusting the fill value of the object, redraw the entire object as you did in your window.onload() function. Because you are calling a redraw, the browser will force the dithering on the object and adjust it for the new color.

Canvas - Sticking png images together without taking into account transparent pixels

I have big horizontal strip image in photoshop which is made of lots of smaller elements. The background is transparent and the strip goes from smaller elements (left) to bigger elements (right). My goal is to make this strip interactive to mouse events.
Each element is some kind of polygonal image which is trimmed left and right and then exported as a png. It is then imported into a canvas.
The problem is that I can put them side by side but since they are not rectangles I need a way to calculate the offset made up by the transparent pixels on each side of each element to make them stick together correctly... I am using KineticJs to get a precise hitarea for each element... So maybe there is a way to do it automatically with kineticjs,or there is some kind of operation I could do using each image data?
My problem illustrated:
Any ideas?
Also I am doing this simply because I would prefer precise mouseOver bounding box on each item (rather than a simple rectangle) and would rather avoid the solution to calculate each offset manually... But maybe that's not worth it?!
Ok, so you have yourself a custom shape you want to use, here is a tutorial for that: http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-shape-tutorial/ , the simplest thing you can do, and even that seems fairly long, is to calculate the bounding lines for that shape. (Two somewhat vertical lines, and two somewhat horizontal lines). Then you test if the right vertical line of shape one crosses with the left vertical line of shape two, if they do, then set the coordinates of the images to be the same coordinate.
http://www.mathopenref.com/coordintersection.html
line1 = ax + b ..... line2 = cx+d //see possible tests
if(...intersection test...){ // or just test if some coordinate is left of some other coordinate
shape2.setX(shape1.getX()+shape1.getWidth()); //account for image width, so they don't overlap
shape2.setY(shape1.getY()) // no need to account for height
}
UPDATE: This is a very rough solution to the workings of the problem. The next step would be to do more fine tuning dependent on each image.
http://jsfiddle.net/9jkr7/15/
If you want precise areas, use an image map. With some clever finagling and a blank image gif you should be able to have the background you want whenever you hover over any particular area of the image map (might require javascript).
The other option I can think of would be to use SVG itself or one of the many libraries in existance to build interactive vector graphics into your page.
You could also write a function that calculates the left most, top most, right most, and bottom most pixel by looking at all of the pixels in the image data. Here's a tutorial on that:
http://www.html5canvastutorials.com/advanced/html5-canvas-get-image-data-tutorial/

Why doesn't translate works for the canvas in a div?

I have 2 canvas in a div. I tried to translate one of the canvas, but it didn't work.
http://jsfiddle.net/VkbV5/ shows the case where i commented off the translation line:
this.innerElement2Ctx.translate(100,100);
But when I include the line, the small square disappeared. Why? If you run this page in browser and inspect the innerElement2, you will see that it didn't move at all, but the small square disappeared.
For your information, I need 2 canvas, because I am planning to attach mouse event to innerElement2.
Translating a context adjusts where the 0,0 point is for future drawing commands; scaling a context adjusts how large items draw on the canvas; rotating a context adjusts the direction that items are drawn. None of these context transformations adjust the size or position of the canvas box itself.
Here's an example I made of adjusting canvas transformation so that drawing the same commands allows the user to zoom and pan around a canvas drawing:
http://phrogz.net/tmp/canvas_zoom_to_cursor.html
If you want to move the placement of a canvas within your HTML page, use simple CSS placement as you would with any other element, e.g. a <div>.
If you want complex 2D or 3D transformations you can use cutting edge features of CSS for this (as supported by modern browsers). For example, see:
https://developer.mozilla.org/en/CSS/transform#CSS_transform_functions

Categories

Resources