Can you tell me an easy way to draw graph(2+x, sin(x), cos(x+3)/3.....) in PS format?
For example, I want to draw f(x) = 2+x, with the following values:
Table of values:
Value of X = -5 | -4 | -3 | -2 | -1 | -0 | 1 .....
Value of Y = -3 | -2 | -1 | 0 | 1 | 2 | 3 .....
How to draw this graph? Draw lineto, draw polygon or use curve command?
What do you think is the best solution?
There are a number of different ways you can do this. If you have a set of coordinates to plot, you can put them in an array, and draw the points while iterating through the array.
/XValues [ -5 -4 -3 -2 -1 0 1 ] def % eg. XValues 0 get ==> -5
/YValues [ -3 -2 -1 0 1 2 3 ] def % YValues 0 get ==> -3
XValues 0 get YValues 0 get % X[0] Y[0]
moveto % move to first point
1 1 XValues length 1 sub { % i push integer i = 1 .. length(XValues)-1 on each iteration
XValues % i XVal push X array
1 index % i XVal i copy i from stack
get % i x get ith X value from array
YValues % i x YVal
2 index % i x YVal i i is 1 position deeper now, so 2 index instead of 1
get % i x y
lineto % i line to next point
pop % discard index variable
} for
Now, of course in Postscript the origin is at the bottom left corner by default, and 72 points make an inch. So these values (-5, -4, -2, etc) are not even going to be visible. So you usually want to start by translating to the center of where you want to draw the graph.
/Center { 300 400 } def % roughly the middle of US letter-size paper
Center translate
Then you want to scale the coordinate system so the graph features are visible. Scalefactor = DesiredSize / ExistingSize.
You could scan the dataset to find the existing size.
/Xmin 1000000 def % really high
/Xmax -1000000 def % really low
XValues { % x forall pushes each X value
dup Xmin lt { % x lower than Xmin?
dup /Xmin exch def % x set Xmin
} if % x
dup Xmax gt { % x higher than Xmax?
/Xmax exch def % set Xmax
}{ % x else (lower than Xmax)
pop % discard X value
} ifelse
} forall
/Datasize Xmax Xmin sub def % X size is (Xmax-Xmin)
6 72 mul DataSize div % scalefactor 6*72/(Xmax-Xmin)
dup % scalefactor scalefactor use same scaling for x and y
scale
But there's a snag when you're doing line-drawing. The width of the lines you draw also depend upon the current coordinate space, so if you scale up the space by a large factor, your lines will become undesirably wide. You can either unscale back to the normal space after you describe the path but before you call stroke. Or, fix the linewidth at the same time you scale.
Since we know how much we've increased the line width (it's the same scaling factor), we can adjust the linewidth graphics parameter in the inverse direction.
1 % push 1 for division
6 72 mul DataSize div % 1 scalefactor 6*72/(Xmax-Xmin)
dup dup % 1 scalefactor scalefactor scalefactor
scale % 1 scalefactor
div % 1/scalefactor
currentlinewidth mul setlinewidth % adjust line width
Now, since this is a graph of a function, we don't actually need the tables of values. We can calculate values on the fly by evaluating the function.
/func { 3 add cos 3 div } def % f(x) = cos(3+x)/3 define function y=f(x)
/Xini -5 def % named loop control parameters
/Xfin 1 def
/Xstep 1 def
Xini dup dup func moveto % moveto first point
Xstep add Xstep Xfin { % x
dup % x x
func % x f(x)
lineto % line to next point
} for
stroke
Finally, if you can take the derivative of the function (create a function which calculates the slope of the original function at each point), then you can use my answer over on TeX.SE to draw the graph with many curve segments instead of lines.
Related
7|8|9
6|5|4
1|2|3
1 -> (1,1)
2 -> (2,1)
3 -> (3,1)
4 -> (3,2)
5 -> (2,2)
6 -> (1,2)
7 -> (1,3)
8 -> (2,3)
9 -> (3,3)
In this grid, the mapping of the numbers to coordinates is shown above.
I'm struggling to come up with a formula where given the number of the grid and the number of rows and columns in the grid, it outputs the coordinates of the grid.
I tried following the logic in this question but in this question, the coordinate system starts from 0 and the rows are not alternating.
If there was no alternating and the numbers were all starting at 0 and not 1, then you could apply Euclidean division directly:
x = n % 3
y = n // 3
where // gives the quotient of the Euclidean division, and % gives the remainder of the Euclidean division.
If there was no alternating, but the numbers all start at 1 instead of 0, then you can fix the above formula by removing 1 from n to make it start at 0, then adding 1 to x and y to make them start at 1:
x = ((n - 1) % 3) + 1
y = ((n - 1) // 3) + 1
Now all we have to change to take the alternating into account is to flip the x values on the right-to-left rows.
y remains unchanged, and x remains unchanged on the left-to-right rows.
The right-to-left rows are the rows with an even y, and you can flip x symmetrically around 2 by removing it from 4:
if y % 2 == 0:
x = 4 - x
Putting it all together in a function and testing it, in python:
def coord(n):
y = ((n-1) // 3) + 1
x = ((n-1) % 3) + 1
if y % 2 == 0: # right-to-left row
x = 4 - x # flip horizontally
return (x, y)
for n in range(1, 9+1):
x, y = coord(n)
print(f'{n} -> ({x},{y})')
Output:
1 -> (1,1)
2 -> (2,1)
3 -> (3,1)
4 -> (3,2)
5 -> (2,2)
6 -> (1,2)
7 -> (1,3)
8 -> (2,3)
9 -> (3,3)
Inverse function
The inverse operation of a Euclidean division is a multiplication and an addition:
if y % 2 == 1:
n = 3 * (y-1) + x
else:
n = 3 * (y-1) + 4 - x
I need random points within an octahedron, uniformly distributed. I am defining an octahedron as the volume where all points satisfy abs(x) + abs(y) + abs(z) <= 1 where abs gives absolute value. IE: each of the six vertices would be on an axis, 1 away from 0,0,0. Maybe you could call it a unit octahedron.
With the definition in mind, I can naively generate a point like so:
val x: Double = nextDouble() // 0-1 range
val y = nextDouble(1.0 -x) // 1-x is upper bound, probably <1
val z = nextDouble(1.0 -(x+y))
The problem is that this leans toward small y values, and smaller z values. Clearly not an even distribution. Also clearly, all these points are in just one of eight quadrants.
I'm avoiding the discard method because this function will be called a lot, and it just seems like I should be able to do better than throwing out the majority of points.
Note that the dual of the octahedron is the cube. Because of this, I have an inkling that there might exist a simple function to translate any point within a cube to be within the octahedron, but that's just an intuition I'm still exploring.
Here is the idea - sample points from Dirichlet distribution in D+1, select D points such that you're uniform in the simplex
x0+x1+x2 <= 1, xi >= 0
To make octahedron, randomly select octant to put your point.
Code in Python
import math
import random
def Dirichlet():
"""sample 4d Dirichlet"""
x0 = -math.log(1.0 - random.random()) # exponential
x1 = -math.log(1.0 - random.random()) # exponential
x2 = -math.log(1.0 - random.random()) # exponential
x3 = -math.log(1.0 - random.random()) # exponential
s = 1.0/(x0+x1+x2+x3) # scaling
return (x0*s, x1*s, x2*s, x3*s)
def OctahedronSampling():
x0, x1, x2, _ = Dirichlet()
octant = random.randint(0, 7)
if octant == 0:
return (x0, x1, x2)
elif octant == 1:
return (x0, -x1, x2)
elif octant == 2:
return (x0, x1, -x2)
elif octant == 3:
return (x0, -x1, -x2)
elif octant == 4:
return (-x0, x1, x2)
elif octant == 5:
return (-x0, -x1, x2)
elif octant == 6:
return (-x0, x1, -x2)
elif octant == 7:
return (-x0, -x1, -x2)
return None
for _ in range(0, 2000):
x0, x1, x2 = OctahedronSampling()
print(f"{x0} {x1} {x2}")
And here is quick graph with 2K points
You know how to choose points in a cube with uniform distribution, and a cube can be dissected into eight square pyramids. (Sorry I can't provide graphics.)
I'd start with a cube: abs(x) <= 1; abs(y) <= 1; abs(z) <= 1
Pick a point in it (a column vector, (x, y, z)), then reflect to bring it into the "top and bottom" pyramids:
if abs(x) > abs(z), swap x and z. Equivalently, multiply by
0 0 1
0 1 0
1 0 0
if abs(y) > abs(z), swap y and z. Equivalently, multiply by
1 0 0
0 0 1
0 1 0
Then invert the two pyramids to make an octahedron:
if z>0
z = 1-z
if z<0
z = -1-z
Then rotate and scale:
multiply by
1/2 -1/2 0
1/2 1/2 0
0 0 1
First of all, I would like to tell You, I have really limited time.
So i would appricate every help with that task.
I have to draw a regular polygon with every diagonal.
( attached file: http://s30.postimg.org/5m6cvd7u9/polygon_with_all_diagonal.png )
Could someone help me with this?
Edit:
Please check scource code:
300 200 translate
/S 28 def
S S scale
4 S div setlinewidth
1 setlinecap
1 setlinejoin
/n 5 def
/r 5 def
newpath
r 0 moveto
1 1 n 1 sub
{
/i exch def
360 n div i mul cos r mul
360 n div i mul sin r mul lineto
} for
closepath
stroke
Thats all what i could do, i have no more idea, how to draw the diagonals.
Cutting and pasting from my other graph drawing routines I get something like this (there is a bit of redundant code but that's because one may want to make the adjacency list on your own):
% routines
/ngon{ [ exch 360 exch div
0 exch 359.9 {
[ exch dup cos 40 mul exch sin 40 mul ]
} for
]
} def
/fmtrx {[ 0 1 4 3 roll 1 sub { [ 1 1 4 3 roll {pop 1} for ] } for ]} def
/drawnodelist { % nodes drawnodelist
{
newpath aload pop 2.5 0 360 arc closepath fill
} forall
} def
/drawedges { % adjacency_matrix nodes drawedges
/drawnodes exch def
dup
/drawlist exch def
/row 0 def
{
/col 0 def
{
pop
drawlist row get col get 1 eq
{
newpath
drawnodes row get aload pop moveto
drawnodes col get aload pop lineto stroke
} if
/col col 1 add def
} forall
/row row 1 add def
} forall
} def
/drawngon {
dup /polygon exch ngon def
polygon drawnodelist % remove this line if you do not want dots
fmtrx polygon drawedges
} def
% call routines
90 rotate
6 drawngon
Here is a sample of different connected polygons produced:
Here is my take:
/n 7 def % number of sides
/R 100 def % radius of circumscribed circle
R 2 mul dup translate
/A 360 n div def
% point given index
/P {
A mul dup
cos R mul
exch
sin R mul
} bind def
0 1 n 1 sub {
dup P 3 2 roll
1 add 1 n 1 sub {
P moveto 2 copy lineto stroke
} for
pop pop
} for
showpage
Arguably a more fitting description of the problem is that you are trying to draw a fully connected graph.
The [Wikipedia-entry on PostScript][http://en.wikipedia.org/wiki/PostScript#Units_of_length] reveals a simple procedure that can be used to solve your problem:
For example, in order to draw a vertical line of 4 cm length, it is
sufficient to type:
0 0 moveto
0 113.385827 lineto stroke
Observe that the above sample can be easily adapted to draw any line; that is, it does not necessarily have to be a vertical line. Now, for each vertex of your polygon draw a line to every other vertex.
Knowing that the polar coordinates of the vertices of a n-polygon will be (rad,i(2π/n)) for i=0..n-1, you can generate the postscript code to describe a polygon path from another language, like C.
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void emitpoly (double x, double y, int n, double r, int up) {
int i;
double a;
printf("%f %f moveto\n", x+r*cos(up?M_PI/2.0:0.0), y+r*sin(up?M_PI/2.0:0.0));
for(i=1; i<n; i++){
a=(double)i*(2*M_PI)/n;
if (up) a += M_PI/2.0;
printf("%f %f lineto\n", x+r*cos(a), y+r*sin(a));
}
printf("stroke\n");
}
void emitpolyweb (double x, double y, int n, double r, int up) {
int i,j;
double a,b;
for(i=0; i<n; i++){
a=(double)i*(2*M_PI)/n;
if (up) a += M_PI/2.0;
printf("%f %f moveto\n", x+r*cos(a), y+r*sin(a));
for(j=0; j<n; j++){
b=(double)j*(2*M_PI)/n;
if (up) b += M_PI/2.0;
printf("%f %f lineto\n", x+r*cos(b), y+r*sin(b));
printf("closepath\n");
}
}
printf("stroke\n");
}
int main(int argc, char**argv) {
int up = 0, n = 3;
double x = 0.0, y = 0.0, r = 1.0;
if (argc>1) x = strtod(argv[1],NULL); // set x from 1st arg, if present
if (argc>2) y = strtod(argv[2],NULL); // set y from 2nd arg, if present
if (argc>3) n = strtol(argv[3],NULL,10); // set n from 3rd arg, if present
if (argc>4) r = strtod(argv[4],NULL); // set r from 4th arg, if present
if (argc>5) up = strcmp(argv[5],"up") == 0; // rotate 90-degrees if 5th arg is "up"
//emitpoly(x,y,n,r,up);
emitpolyweb(x,y,n,r,up);
printf("showpage\n");
return 0;
}
I came up with some results in this area while playing with venn diagrams, and further in geodesic flowers.
This code implements the polygon as a control structure which takes a radius and a repeat count (number of polygon points) and calls the user-defined procedure at each point (by scaling and rotating the CTM). So it's a loop, that makes the user point (1,0) map to successive points of the polygon for each iteration. Using this function, the figure itself is fairly simple. Being a control structure, it is not limited to drawing polygons but can also be used to position smaller drawings at the vertices of a polygon, or even to generate an array of vertex points.
Note also, that this code doesn't have to call sin or cos, because that is handled by rotating the coordinate system. The big trick here is using the scanner to produce an optimized loop body (procedure array).
After placing the init incr max control values on the stack for the for loop, it performs ({...}) token pop exch pop bind end exec which dynamically creates a procedure and executes the call to for. token called (successfully) on a string will yield several values on the stack: an empty string, the scanned-token itself (a ps object of the appropriate type), and the Boolean true. So the pop exch pop just trims the Boolean and the empty string. bind then replaces operator names with the operators themselves, so we perform fewer hash-lookups during the loop. Then end removes our temporary dictionary, before execing the procedure.
This works because all of the variables have been directly substituted by the token operator since they are written as //immediate-names and the temporary dictionary is available on the dict stack when token does this. Removing the dict makes this a true control structure that will not interfere with the meaning of any names used by the user-proc, even if it uses names like s, p, and m.
The generated procedure body {{//s setmatrix rotate //p exec} for //m setmatrix} has the user proc embedded //p and two matrices, //s a matrix pre-scaled by the rad argument and //m a matrix to restore at the end. The for loop body {//s setmatrix rotate //p exec} receives an angle argument as part of the loop control. It resets the CTM to our scaled, oriented matrix //s setmatrix, then rotates by the argument angle rotate, then executes the user-proc //p exec.
%rad n {proc} atpoly -
%call proc having rotated+scaled
%so (1,0) is each vertex of rad-radius n-polygon
/atpoly {
4 dict begin /p exch def /n exch def % rad
/m matrix currentmatrix def
dup scale
/s matrix currentmatrix def
0 360 n div 359.9 %0 dAng maxAng %{}for
({
{
//s setmatrix
rotate
//p exec
} for
//m setmatrix
}) token pop exch pop %instantiate code template
bind
end exec % run loop without dictionary
} bind def
300 400 translate
/rad 100 def
/n 9 def
rad n {
1 0 moveto
1 n {
1 0 lineto
closepath
} atpoly
} atpoly
stroke
To use atpoly, we have to translate to the desired center-point. Then the pseudo-code is:
for each point in poly
moveto point
for each point in poly
lineto point
line back to last moveto point (closepath)
stroke
The are at least two ways to draw just the polygon with atpoly. You can add a redundant moveto at the beginning and use lineto in the proc, or you can use a procedure which does moveto the first time and redefines itself to do lineto thereafter. Here's a variant of the script part that shows both ways, and the interconnected poly.
/rad 100 def
/n 9 def
gsave
400 200 translate
rad n {
1 0 moveto
1 n {
1 0 lineto
closepath
} atpoly
} atpoly
stroke
grestore
gsave
200 200 translate
rad 0 moveto
rad n {
1 0 lineto
} atpoly
closepath stroke
grestore
gsave
200 400 translate
/action { moveto /action { lineto } def } def
rad n {
1 0 action
} atpoly
closepath stroke
grestore
output:
I suppose these blocks could be wrapped up as procedures. These still require the atpoly function from above.
/drawpoly { % rad n x y
gsave
translate
1 index 0 moveto
{
1 0 lineto
} atpoly
closepath stroke
grestore
} def
% rad and n are needed in the outer call to atpoly,
% then n is needed for each iteration.
% To avoid adding a dictionary, duplicate n n-times.
% Once for each iteration.
/drawpolyweb { % rad n x y
gsave
translate % rad n
dup % rad n n
{ dup } repeat % rad n^(n+1)
1 add % rad n^n n+1
-1 roll % n^n rad
%pstack() =
1 index % n^n rad n
{
1 0 moveto % n^(n-i)
1 exch % n^(n-i-1) 1 n
{
1 0 lineto
closepath
} atpoly
} atpoly
stroke
grestore
} def
Then the usage becomes simpler:
%rad n x y
100 9 300 200 drawpoly
100 9 300 500 drawpolyweb
I got an image with a couple of diamond put side by side like on the image below
The only coordinates I know on the image are the top corners (green text).
When I click on the image I get the coordinates of that point, but I'm not able to get which diamond I'm on.
For example I click on the red dot, how do I know that x:260, y:179 = the top diamond ?
And the blue belongs to the left ? etc...
Thank you very much for your help.
EDIT:
I finally used Canvas, but I think SVG would have worked as well for what I needed to do.
I see two possible approaches: direct check whether a point is inside a diamond and using affine transformations. I will describe both.
Direct point position check
To determine whether a point is inside a diamond you have to check its deviation from the middle point of a diamond. You have to put the X and Y deviations in proportion with the X and Y extents of the diamond, you will get two factors. For all points inside the diamond the sum of the modulo values for these factors is smaller or equal 1. In code this looks like this:
var dx = Math.abs(coords[0] - middle[0]);
var dy = Math.abs(coords[1] - middle[1]);
if (dx / size[0] + dy / size[1] <= 1)
alert("Inside diamond");
else
alert("Outside diamond");
So all you have to do now is determining the middle point for each diamond (size is the same in all cases) and checking whether the point you are testing is located inside them.
Working example: http://jsfiddle.net/z98hr/
Affine transformations
Using affine transformations you can change the corner coordinates of your top diamond into (0,0), (1,0), (0,1) and (1,1). If you then apply the same transformation to the point you need to test, determining which diamond it belongs to becomes trivial.
First you will need a translation vector to move the (225,2) point into the origin of coordinates. Let's say that you have four coordinates determining your top diamond (left and right coordinate, top and bottom coordinate):
var topDiamond = [[113, 2], [337, 227]];
Then the translation vector to move the top point of the diamond to the zero coordinate would be:
var translationVector = [-(topDiamond[0][0] + topDiamond[1][0]) / 2,
-topDiamond[0][1]];
You can apply it to the original coordinates like this:
function add(vector1, vector2)
{
return [vector1[0] + vector2[0], vector1[1] + vector2[1]];
}
topDiamond = [add(topDiamond[0], translationVector),
add(topDiamond[1], translationVector)];
Then you will need a rotation matrix:
var angle = -Math.atan2(topDiamond[1][1] - topDiamond[0][1],
topDiamond[1][0] - topDiamond[0][0]);
var rotMatrix = [[Math.cos(angle), -Math.sin(angle)],
[Math.sin(angle), Math.cos(angle)]];
After the multiplication with this matrix the points (225,2) and (337,114.5) are aligned on the X axis. But what you have now is a trapeze, you now need a horizontal shear transformation to get the other side of the diamond aligned on the Y axis:
function multiply(matrix, vector)
{
return [matrix[0][0] * vector[0] + matrix[0][1] * vector[1],
matrix[1][0] * vector[0] + matrix[1][1] * vector[1]];
}
var point = [topDiamond[0][0], (topDiamond[0][1] + topDiamond[1][1]) / 2];
point = multiply(rotMatrix, point);
var shearMatrix = [[1, -point[0] / point[1]], [0, 1]];
After multiplication with this matrix you have a rectangle now. Now you only need a scaling matrix to make sure that the X and Y coordinates of the corners have the value 0 and 1:
point = multiply(shearMatrix, point);
var point2 = [topDiamond[1][0], (topDiamond[0][1] + topDiamond[1][1]) / 2];
point2 = multiply(rotMatrix, point2);
point2 = multiply(shearMatrix, point2);
var scaleMatrix = [[1/point2[0], 0], [0, 1/point[1]]];
And there you have it, now you can apply these transformations to any point:
alert(
multiply(scaleMatrix,
multiply(shearMatrix,
multiply(rotMatrix,
add(translationVector, [260, 179])
)
)
)
);
This gives you 0.94,0.63 - both values are in the (0..1) range meaning that it is the top diamond. With [420,230] as input you get 1.88,0.14 - X in (1..2) range and Y in 0..1 range means right diamond. And so on.
Working example: http://jsfiddle.net/FzWHe/
In the retrospective, this was probably too much work for a simple geometrical figure like a diamond.
Essentially, what you have there is possibly an isometric view of 4 tiles (based on your comment about the diamonds appearing as trapezoids).
One quick way of doing this is to create 2 lines that are parallel with the "axes" of the "diamonds" (but still are crossing with each other...this is important as well). In the example image given, that would mean two lines that are vertical to each other but rotated by 45 degrees. In the isometric case, the lines will not be vertical to each other but at some other angle depending on your view.
Once you have these two lines you can create a "hitTest()" function that will be taking the coordinates of the point that was clicked and will be evaluating the two line equations. You are not really interested on the actual number returned by the line equations but only the signs. The sign shows you which side of the line does your point resides.
This means that your "diamonds" will correspond to these sign pairs (one sign for each line equation) [-,-], [-,+], [+,-], [+,+].
(Please note that the sign depends on the way that the line was defined, in other words for a given point P, the sign from some line equation (L) will be different if the line was defined as running "from left to right" or "from right to left", or more generally the sign will be the reverse for reciprocal directions.)
A bit more information about the form of the line equation you need can be obtained from here
Using matrices, you can derive a quick formula for which diamond is selected.
You want a transformation from (x,y) into "diamond-space". That is, a coordinate system where (0,0) is the top diamond, (1,0) is the one below to the right, and (0,1) below to the left.
A * x = y
where A is the transformation, x is the image coordinates, and y is the diamond-coordinates. To deal with the translation ((0,0) not being the same point in both spaces), you can add another row to the vectors, which is always 1.
You can transform multiple vectors at the same time, by putting them beside each other, so they form a matrix.
[ a b dx ] [ 225 337 113 ] [ 0 1 0 ]
[ c d dy ] * [ 2 114 114 ] = [ 0 0 1 ]
[ 0 0 1 ] [ 1 1 1 ] [ 1 1 1 ]
^ ^ ^-left ^-^-^--- new coordinates for each point
| '-right
'-top diamond
To solve for the coefficients in the first matrix, you need to divide by the second matrix (or multiply by the inverse).
[ a b dx ] [ 0 1 0 ] [ 225 337 113 ]^-1
[ c d dy ] = [ 0 0 1 ] * [ 2 114 114 ]
[ 0 0 1 ] [ 1 1 1 ] [ 1 1 1 ]
The result is:
[ a b dx ] [ (1/224) (1/224) (-227/224) ]
[ c d dy ] = [ (-1/224) (1/224) (223/224) ]
[ 0 0 1 ] [ 0 0 1 ]
To put this into program code:
function getDiamond(x, y) {
return [(x + y - 227) / 224, (-x + y + 223) / 224];
}
Example:
> getDiamond(260,179); // red
[0.9464285714285714, 0.6339285714285714]
> getDiamond(250,230); // green
[1.1294642857142858, 0.90625]
> getDiamond(189,250); // blue
[0.9464285714285714, 1.2678571428571428]
> getDiamond(420,230); // yellow
[1.8883928571428572, 0.14732142857142858]
If you look at the integer parts, you can see which diamond the coordinate corresponds to. The red one is at (0.94, 0.63) which is in region (0,0) pretty close to the edge of (1,0).
NB. The blue and green points in OP is drawn in the wrong location (or given wrong coordinates), so the result of my function places them in a different relative location.
If you do the calculations symbolically, you end up with this:
[ a b dx ] [ (y2 - y0)/M -(x2 - x0)/M -(x0*y2 - y0*x2)/M ]
[ c d dy ] = [-(y1 - y0)/M (x1 - x0)/M (x0*y1 - y0*x1)/M ]
[ 0 0 1 ] [ 0 0 1 ]
where M = x1*y2 - x2*y1 - y0*x1 + y0*x2 + x0*y1 - x0*y2.
Point 0 being the position of top diamond, point 1 being the position of right diamond, and point 2 being the position of left diamond.
Here is a function to calculate this:
function DiamondMaker(topx,topy, leftx,lefty, rightx,righty)
{
var M = topx*lefty - topx*righty +
leftx*righty - leftx*topy +
rightx*topy - rightx*lefty;
var a = -(topy - righty)/M;
var b = (topx - rightx)/M;
var dx = -(topx*righty - topy*rightx)/M;
var c = (topy - lefty)/M;
var d = -(topx - leftx)/M;
var dy = (topx*lefty - topy*leftx)/M;
return function(x, y) {
return [a * x + b * y + dx, c * x + d * y + dy];
};
}
var getDiamond = DiamondMaker(225,2, 337,114, 113,114);
// (same example as before)
All you need - just stady what is roration. Here is link: http://en.wikipedia.org/wiki/Rotation_(mathematics)
You should rotate you point in order to make sides of squares in parrallel with coordinate's grid. Point of rotaion should be 1 corner of dimonds you will threat as 0,0 diamond. After rotaion you can easily define how many daimond you point away from 0,0
I have an opengl arbitrary rotation matrix and would like to remove the X & Y axis, leaving me with only the Z axis?
Is this possible? Any pointers on how to do it?
Just thinking out loud here, but can't you use the matrix to rotate a vector like (1,0,0), then do atan2(y,x) to see how much it's rotated and then build a new matrix to rotate through the Z axis by that much?
In a rotation that is only around the z-axis, the z axis should remain unchanged. So the above recommendation is sort of the reverse of what you want.
Let's assume you have an arbitrary OpenGL matrix:
| r_xx r_xy r_xz t_x |
| r_yx r_yy r_yz t_y |
M = | r_zx r_zy r_zz t_z |
| 0 0 0 1 |
Where the t_i elements are translations and the r_jk elements are components of rotation. You want a matrix that looks like this:
| cos(th) sin(th) 0 t_x |
|-sin(th) cos(th) 0 t_y |
| 0 0 1 t_z |
| 0 0 0 1 |
Unless the matrix has scaling factors or is close to a singularity, you should be able to get this by just zeroing out the z parts of the matrix and then re-normalizing the columns. Since an OpenGL matrix is column major order:
double xLen = sqrt(M[0]*M[0] + M[1]*M[1]); // Singularity if either of these
double yLen = sqrt(M[4]*M[4] + M[5]*M[5]); // is equal to zero.
M[0]/=xLen; M[1]/=xLen; M[2]=0; // Set the x column
M[4]/=yLen; M[5]/=yLen; M[6]=0; // Set the y column
M[8]=0; M[9]=0; M[10]=1; // Set the z column
//Don't change the translation column