Java 3D Box and Cylinder inconstency with parameters - java-3d

I have created a Box(1,1,1) and a cylinder (0.5,1) at the same scene. But when I look in the fig the size of the box is twice the size of the cylinder. Does box (1,1,1) means the length width and height of the cube?? When i draw a sphere or cone the measures are consistent with the cylinder?

the javadoc of Box is a bit dubious. The constructor's parameters 'float xdim, float ydim, float zdim' are NOT width, height, and depth. A Box is centered at the origin (0, 0, 0). The three parameters define the upper corner on the positive axes X, Y, and Z. The corresponding lower corner is (-xdim, -ydim, -zdim) on the negative axes. So, the size of a Box is: width = xdim x 2, height = ydim x 2, and depth = zdim x 2.
August

Related

How do 'normalized figure coordinates' work?

In matplotlib, I recently came across the term 'normalized figure coordinates', which is apparently a specification of a rectangle by four parameters.
It is evident that a rectangle can be described by four numbers, and I'm guessing these four numbers somehow describe the dimensions as well as the location of the rectangle. However, I haven't managed to find an answer as to which of these parameters specifies which value.
Additionally, I'm not sure whether this is a matplotlib-specific term or one of general meaning, as the matplotlib documentation does not cite or link any sources with respect to this term.
Can anyone shed some light on this issue, please?
There are several functions where normalized figure coordinates are used.
In general possibilities are
(left, bottom, width, height) (this is called "bounds" in matplotlib); or
(left, bottom, right, top) (called "extent").
Hopefully the documentation will make it clear which 4 tuple is expected in the respective case.
Here you seem to be interested in the GridSpec's tight_layout parameter rect. From its documentation
rect : tuple of 4 floats, optional
(left, bottom, right, top) rectangle in normalized figure coordinates that the whole subplots area (including labels) will fit into. Default is (0, 0, 1, 1).
To answer your last question, the term normalization is not matplotlib-specific you can get a very short intro from wikipedia.
As for Matplotlib: you can have different coordinate systems relative to different objects (e.g. the axis, the figure).
Each of these systems is normalized, in the sense that the 4 corners of the chosen reference object will always have the following coordinates:
(0,1) Top left corner
(1,1) Top right corner
(1,0) Bottom right corner
(0,0) Bottom left corner
Where the first element of each pair refers to x-axis and the second element refers to the y-axis.
This makes, among other things, annotation or placements of artist objects easier as you can specify the position of the element you wish to add using any of the available coordinate systems.
All you need to do is select an appropriate coordinate system by passing a transformation object to the transform parameter.
Some example:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([5.], [2.], 'o')
circle=plt.Circle((0, 0), 0.1, color="g",transform=ax.transAxes) #bottom (y=0) left (x=0) green circle of radius 0.1 (expressed in coord system)
ax.add_artist(circle)
ax.annotate('I am the top (y=1.0) right (x=1.0) Figure corner',
xy=(1, 1), xycoords=fig.transFigure,
xytext=(0.2, 0.2), textcoords='offset points',
)
plt.text( # position text relative to data
5., 2., 'I am the (5,2) data point', # x, y, text,
ha='center', va='bottom', # text alignment
transform=ax.transData # coordinate system transformation
)
plt.text( # position text relative to Axes
1.0, 0.0, 'I am the bottom (y=0.0) right (x=1.0) axis corner',
ha='right', va='bottom',
transform=ax.transAxes
)
plt.text( # position text relative to Figure
0.0, 1.0, 'I am the top (y=1.0) left (x=0.0) figure corner',
ha='left', va='top',
transform=fig.transFigure
)
plt.show()

Relation between horizontal, vertical and diagonal Field-of-View

Is there a mathematical relation between those values? If I know hFOV and vFOV can I calculate the diagonal FOV without involving other values like focal lengths etc?
My first thought was to use Pythagorean theorem but maybe it's wrong.
The physical quantities of interest are the sensor size and the focal length. The latter, in the pinhole camera model, is the the distance between the camera center and the image plane. Therefore, if you denote with f the focal length (in mm), W and H respectively the image sensor width and height (in mm), and assume the focal axis is orthogonal to the image plane, by simple trigonometry it is:
FOV_Horizontal = 2 * atan(W/2/f) = 2 * atan2(W/2, f) radians
FOV_Vertical = 2 * atan(H/2/f) = 2 * atan2(H/2, f) radians
FOV_Diagonal = 2 * atan2(sqrt(W^2 + H^2)/2, f) radians
Note that, if you have the sensor size and horizontal or vertical fov's, you can solve one of the first two equations for f and plug it into the third one to get the diagonal fov.
When, as is usual, the focal length is estimated through camera calibration, and is expressed in pixels, the above expressions need some adapting.
Denote with K the 3x3 camera matrix, with the camera frame having its origin at the camera center (focal point), X axis oriented left-to-right, Y axis top-to-bottom and Z axis toward the scene. Let Wp and Hp respectively be the width and height of the image in pixels.
In the simplest case the focal axis is orthogonal to the image plane (K12 = 0), the pixels are square (K11 = K22), and the principal point is at the image center (K13 = Wp/2; K23 = Hp/2). Then the same equations as above apply, replacing W with Wp, H with Hp and f with K11.
A lil more complex is the case just as above, but with the principal point off-center. Then one simply adds the two sides of each FOV angle. So, for example:
FOV_Horizontal = atan2(Wp/2 - K13, K11) + atan2(Wp/2 + K13, K11)
If the pixels are not square the same expressions apply for FOV_vertical, but using K22 and Hp, etc. The diagonal is a tad trickier, since you need to "convert" the image height into the same units as the width. Use the "pixel aspect ratio" PAR=K22/K11 for this purpose, so that:
FOV_Diagonal = 2 * atan2(sqrt(Wp^2 + (Hp/PAR)^2) / 2, K11)

How does PDF line width interact with the CTM in both horizontal and vertical dimensions?

I'm trying to figure out exactly how line width affects a stroked line in PDF, given the current transformation matrix (CTM). Two questions...
First: how do I convert the line width to device space using the CTM? Page 208 in the PDF 1.7 Reference, which describes how to convert points using the CTM, assumes the input data is an (x, y) point. Line width is just a single value, so how do I convert it? Do I create a "dummy" point from it like (lineWidth, lineWidth)?
Second: once I make that calculation, I'll get another (x, y) point. If the CTM has different scaling factors for horizontal vs. vertical, that gives me two different line widths. How are these line widths actually applied? Does the first one (x) get applied only when drawing horizontal lines?
A concrete example for the second question: if I draw/stroke a horizontal line from (0, 0) to (4, 4) with line width (2, 1), what are the coordinates of the bounding box of the resulting rectangle (i.e., the rectangle that contains the line width)?
This is from Page 215 in the Reference, but it doesn't actually explain how the thickness of stroked lines will vary:
The effect produced in device space depends on the current transformation matrix
(CTM) in effect at the time the path is stroked. If the CTM specifies scaling by
different factors in the horizontal and vertical dimensions, the thickness of
stroked lines in device space will vary according to their orientation.
how do I convert the line width to device space using the CTM?
The line width essentially is the line size perpendicular to its direction. Thus, to calculate the width after transformation using the CTM, you choose a planar vector perpendicular to the original line whose length is the line width from the current graphics state, apply the CTM (without translation, i.e. setting e and f to 0) to that vector (embedded in the three dimensional space by setting the third coordinate to 1) and calculate the length of the resulting 2D vector (projecting on the first two coordinates).
E.g. you have a line from (0,0) to (1,4) in current user space coordinates with a width of 1. You have to find a vector perpendicular to it, e.g. (-4,1) by rotating 90° counter clockwise, and scale it to a length of 1, i.e. ( -4/sqrt(17), 1/sqrt(17) ) in that case.
If the CTM is the one from #Tikitu's answer
CTM has a horizontal scaling factor of 2 and a vertical scaling factor of 1
it would be
2 0 0
0 1 0
0 0 1
This matrix would make the line from the example above go from (0,0) to (2,4) and the "width vector" ( -4/sqrt(17), 1/sqrt(17) ) would be transformed to ( -8/sqrt(17), 1/sqrt(17) ) (the CTM already has no translation part) with a length of sqrt(65/17) which is about 1.955. I.e. the width of the resulting line (its size perpendicular to its direction) is nearly 2.
If the original line would instead have been (0,0) to (4,1) with width 1, a width vector choice would have been ( -1/sqrt(17), 4/sqrt(17) ). In that case the transformed line would go from (0,0) to (8,1) and the width vector would be transformed to ( -2/sqrt(17), 4/sqrt(17) ) with a length of sqrt(20/17) which is about 1.085. I.e. the width of the resulting line (perpendicular to its direction) is slightly more than 1.
You seem to be interested in the "corners" of the line. For this you have to take start and end of the transformed line and add or subtract half the transformed width vector. In the samples above:
(original line from (0,0) to (1,4)): ( -4/sqrt(17), 1/(2*sqrt(17)) ), ( 4/sqrt(17), -1/(2*sqrt(17)) ), ( 2-4/sqrt(17), 4+1/(2*sqrt(17)) ), ( 2+4/sqrt(17), 4-1/(2*sqrt(17)) );
(original line from (0,0) to (4,1)): ( -1/sqrt(17), 2/sqrt(17) ), ( 1/sqrt(17), -2/sqrt(17) ), ( 8-1/sqrt(17), 1+2/sqrt(17) ), ( 8+1/sqrt(17), 1-2/sqrt(17) ).
Don't forget, though, that PDF lines often are not cut off at the end but instead have some cap. And furthermore remember the special meaning of line width 0.
I don't know anything about PDF internals, but I can make a guess at what that passage might mean, based on knowing a bit about using matrices to represent linear transformations.
If you imagine your stroked line as a rectangle (long and thin, but with a definite width) and apply the CTM to the four corner points, you'll see how the orientation of the line changes its width when the CTM has different horizontal and vertical scaling factors.
If your CTM has a horizontal scaling factor of 2 and a vertical scaling factor of 1, think about lines at various angles:
a horizontal line (a short-but-wide rectangle) gets its length doubled, and it's "height" (the width of the line) stays the same;
a vertical line (a tall-and-thin rectangle) gets it's width doubled (i.e., the line gets twice as thick), and it's length stays the same;
lines at various angles get thicker by different degrees, depending on the angle, because they get stretched horizontally but not verticallye.g.
the thickness of a line at 45 degrees is measured diagonally (45 degrees the other way), so it gets somewhat thicker (some horizontal stretching), but not twice as thick (the vertical component of the diagonal didn't get bigger). (You can figure out the thickness with two applications of the Pythagorean theorem; it's about 1.58 times greater, or sqrt(5)/sqrt(2).)
If this story is correct, you can't convert line width using the CTM: it is simply different case-by-case, depending on the orientation of the line. What you can convert is the width of a particular line, with a particular orientation, via the trick of thinking of the line as a solid area and running its corners individually through the CTM. (This also means that "the same" line, with the same thickness, will look different as you vary its orientation, if your CTM has different horizontal and vertical scaling factors.)

pyplot scatter plot marker size

In the pyplot document for scatter plot:
matplotlib.pyplot.scatter(x, y, s=20, c='b', marker='o', cmap=None, norm=None,
vmin=None, vmax=None, alpha=None, linewidths=None,
faceted=True, verts=None, hold=None, **kwargs)
The marker size
s:
size in points^2. It is a scalar or an array of the same length as x and y.
What kind of unit is points^2? What does it mean? Does s=100 mean 10 pixel x 10 pixel?
Basically I'm trying to make scatter plots with different marker sizes, and I want to figure out what does the s number mean.
This can be a somewhat confusing way of defining the size but you are basically specifying the area of the marker. This means, to double the width (or height) of the marker you need to increase s by a factor of 4. [because A = WH => (2W)(2H)=4A]
There is a reason, however, that the size of markers is defined in this way. Because of the scaling of area as the square of width, doubling the width actually appears to increase the size by more than a factor 2 (in fact it increases it by a factor of 4). To see this consider the following two examples and the output they produce.
# doubling the width of markers
x = [0,2,4,6,8,10]
y = [0]*len(x)
s = [20*4**n for n in range(len(x))]
plt.scatter(x,y,s=s)
plt.show()
gives
Notice how the size increases very quickly. If instead we have
# doubling the area of markers
x = [0,2,4,6,8,10]
y = [0]*len(x)
s = [20*2**n for n in range(len(x))]
plt.scatter(x,y,s=s)
plt.show()
gives
Now the apparent size of the markers increases roughly linearly in an intuitive fashion.
As for the exact meaning of what a 'point' is, it is fairly arbitrary for plotting purposes, you can just scale all of your sizes by a constant until they look reasonable.
Edit: (In response to comment from #Emma)
It's probably confusing wording on my part. The question asked about doubling the width of a circle so in the first picture for each circle (as we move from left to right) it's width is double the previous one so for the area this is an exponential with base 4. Similarly the second example each circle has area double the last one which gives an exponential with base 2.
However it is the second example (where we are scaling area) that doubling area appears to make the circle twice as big to the eye. Thus if we want a circle to appear a factor of n bigger we would increase the area by a factor n not the radius so the apparent size scales linearly with the area.
Edit to visualize the comment by #TomaszGandor:
This is what it looks like for different functions of the marker size:
x = [0,2,4,6,8,10,12,14,16,18]
s_exp = [20*2**n for n in range(len(x))]
s_square = [20*n**2 for n in range(len(x))]
s_linear = [20*n for n in range(len(x))]
plt.scatter(x,[1]*len(x),s=s_exp, label='$s=2^n$', lw=1)
plt.scatter(x,[0]*len(x),s=s_square, label='$s=n^2$')
plt.scatter(x,[-1]*len(x),s=s_linear, label='$s=n$')
plt.ylim(-1.5,1.5)
plt.legend(loc='center left', bbox_to_anchor=(1.1, 0.5), labelspacing=3)
plt.show()
Because other answers here claim that s denotes the area of the marker, I'm adding this answer to clearify that this is not necessarily the case.
Size in points^2
The argument s in plt.scatter denotes the markersize**2. As the documentation says
s : scalar or array_like, shape (n, ), optional
size in points^2. Default is rcParams['lines.markersize'] ** 2.
This can be taken literally. In order to obtain a marker which is x points large, you need to square that number and give it to the s argument.
So the relationship between the markersize of a line plot and the scatter size argument is the square. In order to produce a scatter marker of the same size as a plot marker of size 10 points you would hence call scatter( .., s=100).
import matplotlib.pyplot as plt
fig,ax = plt.subplots()
ax.plot([0],[0], marker="o", markersize=10)
ax.plot([0.07,0.93],[0,0], linewidth=10)
ax.scatter([1],[0], s=100)
ax.plot([0],[1], marker="o", markersize=22)
ax.plot([0.14,0.86],[1,1], linewidth=22)
ax.scatter([1],[1], s=22**2)
plt.show()
Connection to "area"
So why do other answers and even the documentation speak about "area" when it comes to the s parameter?
Of course the units of points**2 are area units.
For the special case of a square marker, marker="s", the area of the marker is indeed directly the value of the s parameter.
For a circle, the area of the circle is area = pi/4*s.
For other markers there may not even be any obvious relation to the area of the marker.
In all cases however the area of the marker is proportional to the s parameter. This is the motivation to call it "area" even though in most cases it isn't really.
Specifying the size of the scatter markers in terms of some quantity which is proportional to the area of the marker makes in thus far sense as it is the area of the marker that is perceived when comparing different patches rather than its side length or diameter. I.e. doubling the underlying quantity should double the area of the marker.
What are points?
So far the answer to what the size of a scatter marker means is given in units of points. Points are often used in typography, where fonts are specified in points. Also linewidths is often specified in points. The standard size of points in matplotlib is 72 points per inch (ppi) - 1 point is hence 1/72 inches.
It might be useful to be able to specify sizes in pixels instead of points. If the figure dpi is 72 as well, one point is one pixel. If the figure dpi is different (matplotlib default is fig.dpi=100),
1 point == fig.dpi/72. pixels
While the scatter marker's size in points would hence look different for different figure dpi, one could produce a 10 by 10 pixels^2 marker, which would always have the same number of pixels covered:
import matplotlib.pyplot as plt
for dpi in [72,100,144]:
fig,ax = plt.subplots(figsize=(1.5,2), dpi=dpi)
ax.set_title("fig.dpi={}".format(dpi))
ax.set_ylim(-3,3)
ax.set_xlim(-2,2)
ax.scatter([0],[1], s=10**2,
marker="s", linewidth=0, label="100 points^2")
ax.scatter([1],[1], s=(10*72./fig.dpi)**2,
marker="s", linewidth=0, label="100 pixels^2")
ax.legend(loc=8,framealpha=1, fontsize=8)
fig.savefig("fig{}.png".format(dpi), bbox_inches="tight")
plt.show()
If you are interested in a scatter in data units, check this answer.
You can use markersize to specify the size of the circle in plot method
import numpy as np
import matplotlib.pyplot as plt
x1 = np.random.randn(20)
x2 = np.random.randn(20)
plt.figure(1)
# you can specify the marker size two ways directly:
plt.plot(x1, 'bo', markersize=20) # blue circle with size 10
plt.plot(x2, 'ro', ms=10,) # ms is just an alias for markersize
plt.show()
From here
It is the area of the marker. I mean if you have s1 = 1000 and then s2 = 4000, the relation between the radius of each circle is: r_s2 = 2 * r_s1. See the following plot:
plt.scatter(2, 1, s=4000, c='r')
plt.scatter(2, 1, s=1000 ,c='b')
plt.scatter(2, 1, s=10, c='g')
I had the same doubt when I saw the post, so I did this example then I used a ruler on the screen to measure the radii.
I also attempted to use 'scatter' initially for this purpose. After quite a bit of wasted time - I settled on the following solution.
import matplotlib.pyplot as plt
input_list = [{'x':100,'y':200,'radius':50, 'color':(0.1,0.2,0.3)}]
output_list = []
for point in input_list:
output_list.append(plt.Circle((point['x'], point['y']), point['radius'], color=point['color'], fill=False))
ax = plt.gca(aspect='equal')
ax.cla()
ax.set_xlim((0, 1000))
ax.set_ylim((0, 1000))
for circle in output_list:
ax.add_artist(circle)
This is based on an answer to this question
If the size of the circles corresponds to the square of the parameter in s=parameter, then assign a square root to each element you append to your size array, like this: s=[1, 1.414, 1.73, 2.0, 2.24] such that when it takes these values and returns them, their relative size increase will be the square root of the squared progression, which returns a linear progression.
If I were to square each one as it gets output to the plot: output=[1, 2, 3, 4, 5]. Try list interpretation: s=[numpy.sqrt(i) for i in s]

Draw line at center of circle with angle in objective-c

I want to draw line at the center of circle with fixed size. Please check the image, it will explain everything. I have P1 center of the circle and P2 somewhere at the border of the circle. P1 will always remain fixed and P2 will keep changing with mouse move and it will be any point at circle's border. Now, I want to draw line with fixed length shown in green color. I want to find the (x1,y1) and (x2,y2) with fixed distance, every time P2 get changed, i want to draw green line facing towards P2.
Hope, image explains everything, in short i need following.
angle between P1 and P2.
Draw green line with fixed distance with angle at the center of the circle.
Thanks
Since you (apparently) want the green line to be perpendicular to the red line, you don't need to compute the angle between p1 and p2. Rotating a vector by 90˚ is quite trivial.
I assume you have p1 and p2 as CGPoint (or NSPoint) variables.
First let's compute the vector from p1 to p2:
CGPoint p1p2 = CGPointMake(p2.x - p1.x, p2.y - p1.y);
Next we'll compute a vector that is perpendicular to the p1->p2 vector:
CGPoint p1p2Perp = CGPointMake(p1p2.y, -p1p2.x);
Now let's find the length of the perpendicular vector:
CGFloat radius = hypot(p1p2Perp.x, p1p2Perp.y);
Note that if the radius of the circle is constant, you can just use that instead of computing it. If you're on iOS, use hypotf instead of hypot.
So now we can “normalize” the perpendicular vector, making it have length 1, by dividing its coordinates by its length:
p1p2Perp.x /= radius;
p1p2Perp.y /= radius;
Next we can multiply it by half of the desired length of the green line. I assume you have the desired length of the green line in a constant or variable named greenLineLength.
p1p2Perp.x *= greenLineLength / 2;
p1p2Perp.y *= greenLineLength / 2;
Now we can create a path for the green line. I assume your CGContextRef is in a variable named gc:
CGContextBeginPath(gc);
CGContextMoveToPoint(gc, p1.x - p1p2Perp.x, p1.y - p1p2Perp.y);
CGContextAddLineToPoint(gc, p1.x + p1p2Perp.x, p1.y + p1p2Perp.y);
You can stroke the path however you like. For example:
CGContextSetRGBStrokeColor(gc, 0, 1, 0, 1);
CGContextSetLineWidth(gc, 2);
CGContextSetLineCap(gc, kCGLineCapRound);
CGContextStrokePath(gc);
The angle between the two, according to your question, is always perpendicular -- 90˚ or π/2 radians. You can get the angle of the red segment using atan2(); then subtract M_PI_2 for the angle of the green one.
From there, you are trying to find two points on the circumference of a circle whose diameter is the length of the segment. You can think about this in polar coordinates (r, theta) and convert to Cartesian (x, y):
x = (segment_length / 2) * cos(theta)
y = (segment_length / 2) * sin(theta)
Add M_PI to theta to get the other endpoint.