I'm trying to draw an ellipsoid in 3d space out of individual blocks.
I have no problem with 2D ellipses, but as far as 3D goes I'm having some trouble. I'm using Bresenham's circle algorithm to draw 2D ellipses. What I'm trying to do is draw 2D ellipses in layers with an increasing (starting from the bottom going up, using symmetry for the other half) radius on both the X radius and Y radius.
It all sounds like it would work, but when I go to implement it, I can't figure out how to alter the x radius and y radius to make the curve of the ellipsoid.
Your 2D slices should all have the same orientation and aspect ratio.
If your ellipsoid is axis-aligned, they should also have the same center.
Your slices should scale proportionally to:
scale = sqrt(1 - ((center-z)/half_vsize)^2)
where:
z = height of the current slice
center = height of the largest slice
half_vsize = half the vertical size of the ellipsoid
If (x0, y0) is the x- and y-width of the largest slice, (x, y) = (scale*x0, scale*y0) is the x- and y-width of the slice at height z.
Related
I was given width and height of two rectangles and have to determine if the first one has enough space to be inside the second one.
I checked the obvious horizontal and vertical cases, but what about rotation?
Can someone give me a little hint?
You can calculate dimensions of bounding box for rotated rectangle depending on rotation angle as shown here
H = w * Abs(Sin(Fi)) + h * Abs(Cos(Fi))
W = w * Abs(Cos(Fi)) + h * Abs(Sin(Fi))
where w, h are rotated rectangle dimensions and H, W are bounding box dimensions.
There might exist some intervals of angles where H<Height2 and some intervals with W<Width2. If these intervals do intersect, so rotated rectangle fits into the second one.
I am writing a mesh editor where I have manipulators with the help of which I change the vertices of the mesh. The task is to render the manipulators with constant dimensions, which would not change when changing the camera and viewport parameters. The projection matrix is perspective. I will be grateful for ideas how to implement the invariant scale geometry.
If I got it right you want to render some markers (for example vertex drag editation area) with the same visual size for any depth they are rendered to.
There are 2 approaches for this:
scale with depth
compute perpendicular distance to camera view (simple dot product) and scale the marker size so it has the same visual size invariant on the depth.
So if P0 is your camera position and Z is your camera view direction unit vector (usually Z axis). Then for any position P compute the scale like this:
depth = dot(P-P0,Z)
Now the scale depends on wanted visual size0 at some specified depth0. Now using triangle similarity we want:
size/dept = size0/depth0
size = size0*depth/depth0
so render your marker with size or scale depth/depth0. In case of using scaling you need to scale around your target position P otherwise your marker would shift to the sides (so translate, scale, translate back).
compute screen position and use non perspective rendering
so you transform target coordinates the same way as the graphic pipeline does until you got the screen x,y position. Remember it and in pass that will render your markers just use that instead of real position. For this rendering pass either use some constant depth (distance from camera) or use non perspective view matrix.
For more info see Understanding 4x4 homogenous transform matrices
[Edit1] pixel size
you need to use FOVx,FOVy projection angles and view/screen resolution (xs,ys) for that. That means if depth is znear and coordinate is at half of the angle then the projected coordinate will go to edge of screen:
tan(FOVx/2) = (xs/2)*pixelx/znear
tan(FOVy/2) = (ys/2)*pixely/znear
---------------------------------
pixelx = 2*znear*tan(FOVx/2)/xs
pixely = 2*znear*tan(FOVy/2)/ys
Where pixelx,pixely is size (per axis) representing single pixel visually at depth znear. In case booth sizes are the same (so pixel is square) you have all you need. In case they are not equal (pixel is not square) then you need to render markers in screen axis aligned coordinates so approach #2 is more suitable for such case.
So if you chose depth0=znear then you can set size0 as n*pixelx and/or n*pixely to get the visual size of n pixels. Or use any dept0 and rewrite the computation to:
pixelx = 2*depth0*tan(FOVx/2)/xs
pixely = 2*depth0*tan(FOVy/2)/ys
Just to be complete:
size0x = size_in_pixels*(2*depth0*tan(FOVx/2)/xs)
size0y = size_in_pixels*(2*depth0*tan(FOVy/2)/ys)
-------------------------------------------------
sizex = size_in_pixels*(2*depth0*tan(FOVx/2)/xs)*(depth/depth0)
sizey = size_in_pixels*(2*depth0*tan(FOVy/2)/ys)*(depth/depth0)
---------------------------------------------------------------
sizex = size_in_pixels*(2*tan(FOVx/2)/xs)*(depth)
sizey = size_in_pixels*(2*tan(FOVy/2)/ys)*(depth)
---------------------------------------------------------------
sizex = size_in_pixels*2*depth*tan(FOVx/2)/xs
sizey = size_in_pixels*2*depth*tan(FOVy/2)/ys
the background of my question is the following.
I have a picture and a crop rectangle which describes how the picture should be cropped to produce the resulting picture. The crop rectangle is always smaller or at maximum the size of the picture.
Now it should be possible to rotate the crop rectangle.
This means that when rotating the crop regtanle inside the picture, the crop must be scaled in order that its extends does not exceed the photo.
Can anybode help me with a formula of how to compute the scale of the crop rectanlge based on the axis aligned photo regtancle?
My first attempt was to compute a axis aligned bounding box of the crop rectanlge and than make this fit it the photo rectangle. But somehow i get stuck with this approach,
Edited:
One more think to note:
- The crop rectangle can have other dimension and another center point inside the surrounding rectangle. This means the crop rectangle can be much smaller but for example is located at the lower left bound of the picture rectangle. So when rotating the smaller crop it will also exceed its limits
Thanks in advance
Sebastian
When you rotate an axis-aligned rectangle of width w and height h by an angle φ, the width and height of the rotated rectangle's axis-aligned bounding box are:
W = w·|cos φ| + h·|sin φ|
H = w·|sin φ| + h·|cos φ|
(The notation |x| denotes an absolute value.) This is the bounding box of the rotated crop rectangle which you can scale to fit the original rectangle of width wo and height ho with the factor
a = min(wo / W, ho / H)
if a is less than 1, the rotated crop rectangle fits inside the original rectangle and you don't have to scale. Otherwise, reduce the crop rectangle to the scaled dimensions
W′ = a·W
H′ = a·H
You could start checking if the dimension of the cropped rectangle fit in the old rectangle:
bound_x = a * cos(theta) + b * sin(theta)
bound_y = b * cos(theta) + a * sin(theta)
Where a and b are the new dimensions, theta us the angle and bound_x and bound_y should be smaller of the original rectangle.
What we have is angle(0-360), our small object is in the center and we have width and height of each object. I have tried to do dividing widths and heights without success. Task is to place small object in the bottom of the big object, and when big object get rotated we need small object be on the bottom again, but that bottom could be up or left or right, that why i guessed we need the angle.
So basically we need to create circle movement of small object. Radius of that circle will be big object height/2. But how to calculate X and Y locations from the center to place the small object?
Represantation in images:
Here we have the default state with angle 0
Here we have angle 47
And here we have angle 227
Lets say you want to calculate your new coordinates r pixels away from the point (X,Y) for an angle a. And if your new coordinates would be (x1, y1),
x1 = X + r * COS(a)
y1 = Y + r * SIN(a)
Here is some more info and techniques
I have the need to determine the bounding rectangle for a polygon at an arbitrary angle. This picture illustrates what I need to do:
alt text http://kevlar.net/RotatedBoundingRectangle.png
The pink rectangle is what I need to determine at various angles for simple 2d polygons.
Any solutions are much appreciated!
Edit:
Thanks for the answers, I got it working once I got the center points correct. You guys are awesome!
To get a bounding box with a certain angle, rotate the polygon the other way round by that angle. Then you can use the min/max x/y coordinates to get a simple bounding box and rotate that by the angle to get your final result.
From your comment it seems you have problems with getting the center point of the polygon. The center of a polygon should be the average of the coordinate sums of each point. So for points P1,...,PN, calculate:
xsum = p1.x + ... + pn.x;
ysum = p1.y + ... + pn.y;
xcenter = xsum / n;
ycenter = ysum / n;
To make this complete, I also add some formulas for the rotation involved. To rotate a point (x,y) around a center point (cx, cy), do the following:
// Translate center to (0,0)
xt = x - cx;
yt = y - cy;
// Rotate by angle alpha (make sure to convert alpha to radians if needed)
xr = xt * cos(alpha) - yt * sin(alpha);
yr = xt * sin(alpha) + yt * cos(alpha);
// Translate back to (cx, cy)
result.x = xr + cx;
result.y = yr + cx;
To get the smallest rectangle you should get the right angle. This can acomplished by an algorithm used in collision detection: oriented bounding boxes.
The basic steps:
Get all vertices cordinates
Build a covariance matrix
Find the eigenvalues
Project all the vertices in the eigenvalue space
Find max and min in every eigenvalue space.
For more information just google OBB "colision detection"
Ps: If you just project all vertices and find maximum and minimum you're making AABB (axis aligned bounding box). Its easier and requires less computational effort, but doesn't guarantee the minimum box.
I'm interpreting your question to mean "For a given 2D polygon, how do you calculate the position of a bounding rectangle for which the angle of orientation is predetermined?"
And I would do it by rotating the polygon against the angle of orientation, then use a simple search for its maximum and minimum points in the two cardinal directions using whatever search algorithm is appropriate for the structure the points of the polygon are stored in. (Simply put, you need to find the highest and lowest X values, and highest and lowest Y values.)
Then the minima and maxima define your rectangle.
You can do the same thing without rotating the polygon first, but your search for minimum and maximum points has to be more sophisticated.
To get a rectangle with minimal area enclosing a polygon, you can use a rotating calipers algorithm.
The key insight is that (unlike in your sample image, so I assume you don't actually require minimal area?), any such minimal rectangle is collinear with at least one edge of (the convex hull of) the polygon.
Here is a python implementation for the answer by #schnaader.
Given a pointset with coordinates x and y and the degree of the rectangle to bound those points, the function returns a point set with the four corners (and a repetition of the first corner).
def BoundingRectangleAnglePoints(x,y, alphadeg):
#convert to radians and reverse direction
alpha = np.radians(alphadeg)
#calculate center
cx = np.mean(x)
cy = np.mean(y)
#Translate center to (0,0)
xt = x - cx
yt = y - cy
#Rotate by angle alpha (make sure to convert alpha to radians if needed)
xr = xt * np.cos(alpha) - yt * np.sin(alpha)
yr = xt * np.sin(alpha) + yt * np.cos(alpha)
#Find the min and max in rotated space
minx_r = np.min(xr)
miny_r = np.min(yr)
maxx_r = np.max(xr)
maxy_r = np.max(yr)
#Set up the minimum and maximum points of the bounding rectangle
xbound_r = np.asarray([minx_r, minx_r, maxx_r, maxx_r,minx_r])
ybound_r = np.asarray([miny_r, maxy_r, maxy_r, miny_r,miny_r])
#Rotate and Translate back to (cx, cy)
xbound = (xbound_r * np.cos(-alpha) - ybound_r * np.sin(-alpha))+cx
ybound = (xbound_r * np.sin(-alpha) + ybound_r * np.cos(-alpha))+cy
return xbound, ybound