DisplayObject.getBounds in actionscript returns the bounds of the object with the strokes included. The left, top, width, height properties of a SymbolInstance in JSFL don't seem to include the strokes. That's the only way I've found to get the bounds of a symbol from JSFL. Is there another way?
You are looking for the Edge object on a Shape. The Edge has a Stroke object that has a thickness property.
// This will show the selected shape's first edge's thickness:
fl.trace(fl.getDocumentDOM().selection[0].edges[0].stroke.thickness );
You will have to loop over all the shapes and all of their edges to determine final bounds (if you are confident that all the edges have the same thickness, just check one).
Strokes have 0 width to JSFL, when it comes to getting the bounds of an object.
The only method I can think of is to edit the symbol, select the shape, and either
1.) get the stroke size and add 1/2 of its value to your calculation, or
2.) convert the stroke to a fill (unreliable for complex outlines)
If you only wish to include the strokes but exact sizing is not crucial, you can just arbitrarily add some pixels to the result of getBounds.
Related
In the attached Google charts Pie chart the labels fit well inside the segments. Determining the length of a bit of text in HTML5 canvas is easy enough - but how do you determine whether the label will fit into a particular segment (using trigonometry) ? As you can see on the image, two of the segments don't have labels inside the segment.
EDIT: Here's an example of what I have at the moment: https://www.rgraph.net/tests/canvas.pie/in-pie-labels.html
As you see the labels for the small segments overlap. What I'm after is a way to calculate whether there's enough space for the labels at the point where they're going to be rendered. If not, I can just not draw the label like in the example image above.
Could chord size be useful to do this?
Here's the forumulae for the chord size that I found via Google:
"Chord length using trigonometry = 2 × r × sin(θ/2); where 'r' is the radius of the circle and 'θ' is the angle subtended at the center by the chord."
I sorted it (in about one hour) after 3 days of trying to calculate it with trig by using the built-in context.isPointInPath() function...
Draw the text (transparent color) to get the coordinates (x/y/w/h) of it. You might be able to get away with measuring it to get the width and height.
Draw the segment in a transparent color and do not stroke or fill it. Also, do not close the path.
Test each corner of the text rectangle (formed the x/y/w/h that you got above) using the context.isPointInPath() function. If the function returns true for each corner of the rectangle formed by the coordinates of the text, then the text will fit into the segment.
Using the first photo below, let's say:
The red outline is the stage bounds
The gray box is a Sprite on the stage.
The green box is a child of the gray box and has a rotation set.
both display object are anchored at the top-left corner (0,0).
I'd like to rotate, scale, and position the gray box, so the green box fills the stage bounds (the green box and stage have the same aspect ratio).
I can negate the rotation easily enough
parent.rotation = -child.rotation
But the scale and position are proving tricky (because of the rotation). I could use some assistance with the Math involved to calculate the scale and position.
This is what I had tried but didn't produce the results I expected:
gray.scaleX = stage.stageWidth / green.width;
gray.scaleY = gray.scaleX;
gray.x = -green.x;
gray.y = -green.y;
gray.rotation = -green.rotation;
I'm not terribly experienced with Transformation matrices but assume I will need to go that route.
Here is an .fla sample what I'm working with:
SampleFile
You can use this answer: https://stackoverflow.com/a/15789937/1627055 to get some basics. First, you are in need to rotate around the top left corner of the green rectangle, so you use green.x and green.y as center point coordinates. But in between you also need to scale the gray rectangle so that the green rectangle's dimensions get equal to stage. With uniform scaling you don't have to worry about distortion, because if a gray rectangle is scaled uniformly, then a green rectangle will remain a rectangle. If the green rectangle's aspect ratio will be different than what you want it to be, you'd better scale the green rectangle prior to performing this trick. So, you need to first transpose the matrix to offset the center point, then you need to add rotation and scale, then you need to transpose it away. Try this set of code:
var green:Sprite; // your green rect. The code is executed within gray rect
var gr:Number=green.rotation*Math.PI/180; // radians
var gs:Number=stage.stageWidth/green.width; // get scale ratio
var alreadyTurned:Boolean; // if we have already applied the rotation+scale
function turn():void {
if (alreadyTurned) return;
var mat:flash.geom.Matrix=this.transform.matrix;
mat.scale(gs,gs);
mat.translate(-gs*green.x,-gs*green.y);
mat.rotate(-1*gr);
this.transform.matrix=mat;
alreadyTurned=true;
}
Sorry, didn't have time to test, so errors might exist. If yes, try swapping scale, translate and rotate, you pretty much need this set of operations to make it work.
For posterity, here is what I ended up using. I create a sprite/movieClip inside the child (green) box and gave it an instance name of "innerObj" (making it the actually content).
var tmpRectangle:Rectangle = new Rectangle(greenChild.x, greenChild.y, greenChild.innerObj.width * greenChild.scaleX, greenChild.innerObj.height * greenChild.scaleY);
//temporary reset
grayParent.transform.matrix = new Matrix();
var gs:Number=stage.stageHeight/(tmpRectangle.height); // get scale ratio
var mat:Matrix=grayParent.transform.matrix;
mat.scale(gs,gs);
mat.translate(-gs * tmpRectangle.x, -gs * tmpRectangle.y);
mat.rotate( -greenChild.rotation * Math.PI / 180);
grayParent.transform.matrix = mat;
If the registration point of the green box is at one of it's corners (let's say top left), and in order to be displayed this way it has a rotation increased, then the solution is very simple: apply this rotation with negative sign to the parent (if it's 56, add -56 to parent's). This way the child will be with rotation 0 and parent -> -56;
But if there is no rotation applied to the green box, there is almost no solution to your problem, because of wrong registration point. There is no true way to actually determine if the box is somehow rotated or not. And this is why - imagine you have rotated the green box at 90 degrees, but changed it's registration point and thus it has no property for rotation. How could the script understand that this is not it's normal position, but it's flipped? Even if you get the bounds, you will see that it's a regular rectangle, but nobody know which side is it's regular positioned one.
So the short answer is - make the registration point properly, and use rotation in order to display it like in the first image. Then add negative rotation to the parent, and its all good :)
Edit:
I'm uploading an image so I can explain my idea better:
As you can see, I've created a green object inside the grey one, and the graphics INSIDE are rotated. The green object itself, has rotation of 0, and origin point - top left.
#Vesper - I don't think that the matrix will fix anything in this situation (remember that the green object has rotation of 0).
Otherwise I agree, that the matrix will do a pretty job, but there are many ways to do it :)
Is there a way in pygame to detect if a rect is fully inside a mask?
I know that there is rect in rect collision and collidepoint (point in rect collision) but is there any way to detect if a rect is inside a mask?
Thanks
I don't believe there is any function supplied by pygame to do that. It would definitely be somewhat challenging, because of the "shapeless" possibilities of a mask. One possibility which might work for you would be to first get a list of the bounding rects of the mask (a list of rects which together "contain" all of the points of the mask) and check if your rect is inside any of these rects:
bounding_rects = mask.get_bounding_rects()
for b_rect in bounding_rects:
if b_rect.contains(test_rect):
print "Rect is inside mask"
Of course with this solution, if the rect is inside the mask, but not inside any one particular bounding rect, the test will fail. Here's an idea of how you might handle that, with the tradeoff of a little bit of lost precision:
bounding_rects = mask.get_bounding_rects()
mask_rect = bounding_rects[0].unionall(bounding_rects)
if mask_rect.contains(test_rect):
print "Rect is inside mask"
This solution unions all of the bounding rects of the mask into one rect, which has the possibility of covering area that none of the bounding rects covered (if two rects have a gap of 10 pixels between each other and are unioned together, the new rect will contain that gap)
I'm developing a simple a graphical editor for my flash-based app. In my editor there's a posibility of scaling, range of scaling is big (maximum scale is 16.0, minimum scale is 0.001 and default scale is 0.2). So it's quite possible that a user can draw a line with thickness 0.1 or 300.0, and it looks that line possible thickness (in Graphics.lineStyle()) has upper border. As I found out from livedocs maximum value is 255. So if thickness is greater then 255.0 there'is drawn a line of thickness 255.0. Whether mentioned upper border exists and how big is it. Here're my questions:
Right now I'm drawing lines with drawPath() or lineTo() methods. Natural walkarround if thickness is greater then 255.0 is to draw a rectange instead of segment and two circles on the ends of segment (instead of lineTo()). Or even to draw two thin segments and two half-circles and fill interior. Maybe there's more elegant/quick solution?
Another question is if the thickness of line is big but less then 255.0 (e.g. 100.0), what is faster drawing a line with lineTo() or drawing two thin segments and two half-circles and fill interior?
And finally, maybe someone knows a good article/book where I can read what's inside all methods of flash.display.Graphics class (or even not flash specific article/book on graphics)?
Any thoughts are appreciated. Thank you in advance!
I agree with f-a that putting the line in a container would probably be better and more efficient than drawing a rectangle and extra circles.
I don't think that the math would be too difficult to work out. For efficiency you should probably only do this if the line style is going to be over 255.
To setup the display object to hold your line I would start by halving the width of your line (the length can stay the same). Then create a new sprite and draw the line in the sprite at half size (e.g. if you wanted 300, just draw it at 150). It would be most simple to just start at (0,0) and draw the segment straight so that all of your transformations can be applied to the new sprite.
From here you can just double the scaleY of the sprite to get the desired line weight. It should keep the same length and the ends should also be rounded correctly.
Hope this helped out!
A cool resource for working with the graphics class is Flash and Math. This site has several cool effects and working examples and source code.
http://www.flashandmath.com/
I am trying to understand the method transition that falls in the Matrix Class. I am using it to copy pieces of a bitMapData. But I need to better understand what transitions do.
I have a tilesheet that has 3 images on it. all 30x30 pixels. the width of the total bitmap is 90pxs.
The first tile is green, the second is brown, and the third is yellow. If I move over 30pxs using the matrix that transitions, instead of getting brown, I get yellow, if I move over 60px, I get brown.
If I move -30 pixels, then the order is correct. I am confused on what is going on.
tileNum -= (tileNumber * tWidth);
theMatrix = new Matrix();
theMatrix.translate(tileNum,0);
this.graphics.beginBitmapFill(tileImage,theMatrix);
this.graphics.drawRect(0, 0,tWidth ,tHeight );
this.graphics.endFill();
Can someone tell me how transitions work, or some resources that show how they work. I ultimately want to know a good way to switch back and forth between each tile.
First of all, don't confuse translation with transition. The latter is a general English word for "change", whereas to translate in geometry and general math is to "move" or "offset" something.
A transformation matrix defines how to transform, i.e. scale, rotate and translate, an object, usually in a visual manner. By applying a transformation matrix to an object, all pixels of that object are rotated, moved and scaled/interpolated according to the values stored inside the matrix. If you'd rather not think about matrix math, just think of the matrix as a black box which contains a sequence of rotation, scaling, and translation commands.
The translate() method simply offsets the bitmap that you are about to draw a number of pixels in the X and Y dimensions. If you use the default ("identity") matrix, which contains no translation, the top left corner of your object/bitmap will be in the (0,0) position, known as the origin or registration point.
Consider the following matrix:
var mtx : Matrix = new Matrix; // No translation, no scale, no rotation
mtx.translate(100, 0); // translated 100px on X axis
If you use the above matrix with a BitmapData.draw() or Graphics.beginBitmapFill(), that means that the top left corner of the original bitmap should be at (x=100; y=0) in the target coordinate system. Sticking to your Graphics example, lets first consider drawing a rectangle without a matrix transformation.
var shape : Shape = new Shape;
shape.graphics.beginBitmapFill(myBitmap);
shape.graphics.drawRect(0, 0, 200, 200);
This will draw a 200x200 pixels rectangle. Since there is no transformation involved in the drawing method (we're not supplying a transformation matrix), the top left corner of the bitmap is in (x=0; y=0) of the shape coordinate system, i.e. aligned with the top left corner of the rectangle.
Lets look at a similar example using the matrix.
var shape : Shape = new Shape;
shape.graphics.beginBitmapFill(myBitmap, mtx);
shape.graphics.drawRect(0, 0, 200, 200);
This again draws a rectangle that is 200px wide and 200px high. But where inside this rectangle will the top left corner of myBitmap be? The answer is at (x=100, y=0) of the shape coordinate system. This is because the matrix defines such a translation.
But what then will be to the left of (x=100; y=0)? With the above code, the answer is that the bitmap repeats to fill the entire rectangle, and hence you will see the rightmost side of the bitmap, to the left of the leftmost side, as if there was another instance of the bitmap right next to it. If you want to disable the repeating image, set the third attribute of beginBitmapFill() to false:
shape.graphics.beginBitmpFill(myBitmap, mtx, false);
Lets take a look at one last example that might help your understanding. Remember that the translation matrix defines the position of the top left corner of an image, in the coordinate system of the shape. With this in mind, consider the following code, using the same matrix as before.
var shape : Shape = new Shape;
shape.graphics.beginBitmapFill(myBitmap, mtx);
shape.graphics.drawRect(100, 0, 100, 100);
Notice that this will draw the rectangle 100px in on the X axis. Not coincidentally, this is the same translation that we defined in our matrix, and hence the position of the top left corner of the bitmap. So even though repeating is enabled, we will not see a repeating image to the left of our rectangle, because we only start drawing at the point where the bitmap starts.
So the bottom line is, I guess, that you could think of the transform matrix as a series of transformation commands that you apply to your image as you draw it. This will offset, scale and rotate the image as it's drawn.
If you are curious about the inner workings of the matrix, Google transformation matrices, or read up on Linear Algebra!