Easiest mesh file format to write quads? - graphics

I have voxel maps of 1024 x 1024 x 1024, over a billion voxels, and i am traversing them from XYZ axes to find the outline of a scan within them.
Every time I hit a voxel boundary, I want to create a quad reference for the face encountered, which consists of 4 vertices and and a triangle/quad reference index.
Because the result is 50-60 million quads, I don't think that I can write arrays to memory and merge vertices using loops, it would be too much memory and I can use Meshlab to delete duplicate vertices.
So it's simple to just write 4 vertices and a reference to them every time i find I traverse a boundary.
A/ Can I use another methodology?
B/ What file format allows me to filestream lines like:
FORMAT= .EASY
vtxA: (2.0 , 5.0, 2,0) nml(-1,0,0)
vtxB: (2.0 , 6.0, 2,0) nml(-1,0,0)
vtxC: (2.0 , 5.0, 3,0) nml(-1,0,0)
vtxD: (2.0 , 6.0, 3,0) nml(-1,0,0)
QUAD: ABCD
vtxC: (1002.0 , 5.0, 2,0) nml(1,0,0)
vtxD: (1002.0 , 6.0, 2,0) nml(1,0,0)
vtxE: (1002.0 , 5.0, 3,0) nml(1,0,0)
vtxF: (1002.0 , 6.0, 3,0) nml(1,0,0)
QUAD: CDEF

I've been researching obj,ply and stl file formats, the easiest one to write quads straight to disk seems to be stl even though it's triangles, because you can write stram write to disk, no need for arrays, good for a fast fix at the lab.
here is a cube example:
solid cube
facet normal 0 0 0
outer loop
vertex 0 0 0
vertex 0 1 0
vertex 1 1 0
endloop
endfacet
facet normal 0 0 0
outer loop
vertex 0 0 0
vertex 1 1 0
vertex 1 0 0
endloop
endfacet
facet normal 0 0 0
outer loop
vertex 0 0 0
vertex 0 0 1
vertex 0 1 1
endloop
endfacet
facet normal 0 0 0
outer loop
vertex 0 0 0
vertex 0 1 1
vertex 0 1 0
endloop
endfacet
facet normal 0 0 0
outer loop
vertex 0 0 0
vertex 1 0 0
vertex 1 0 1
endloop
endfacet
facet normal 0 0 0
outer loop
vertex 0 0 0
vertex 1 0 1
vertex 0 0 1
endloop
endfacet
facet normal 0 0 0
outer loop
vertex 0 0 1
vertex 1 0 1
vertex 1 1 1
endloop
endfacet
facet normal 0 0 0
outer loop
vertex 0 0 1
vertex 1 1 1
vertex 0 1 1
endloop
endfacet
facet normal 0 0 0
outer loop
vertex 1 0 0
vertex 1 1 0
vertex 1 1 1
endloop
endfacet
facet normal 0 0 0
outer loop
vertex 1 0 0
vertex 1 1 1
vertex 1 0 1
endloop
endfacet
facet normal 0 0 0
outer loop
vertex 0 1 0
vertex 0 1 1
vertex 1 1 1
endloop
endfacet
facet normal 0 0 0
outer loop
vertex 0 1 0
vertex 1 1 1
vertex 1 1 0
endloop
endfacet
endsolid cube
c type code to write above code:
function Xquad( X:float , Y:float , Z:float , cnt:float){
//based on stl cube
qstr+="facet normal " +"0 0 0"+ "\n"+
"outer loop\n"+
"vertex "+st(X) +" "+ st(Y) +" "+ st(Z)+ "\n"+
"vertex "+st(X) +" "+ st(Y+1) +" "+ st(Z)+ "\n"+
"vertex "+st(X) +" "+ st(Y+1) +" "+ st(Z+1)+ "\n"+
"endloop\n" +
"endfacet\n"+
"facet normal " +"0 0 0"+ "\n"+
"outer loop\n"+
"vertex "+st(X) +" "+ st(Y) +" "+ st(Z)+ "\n"+
"vertex "+st(X) +" "+ st(Y+1)+" "+ st(Z+1)+ "\n"+
"vertex "+st(X) +" "+ st(Y) +" "+ st(Z+1)+ "\n"+
"endloop\n"+
"endfacet\n";
}
function Yquad( X:float , Y:float , Z:float , cnt:float){
qstr+="facet normal " +"0 0 0"+ "\n"+
"outer loop\n"+
"vertex "+st(X) +" "+ st(Y) +" "+ st(Z)+ "\n"+
"vertex "+st(X+1)+" "+ st(Y) +" "+ st(Z)+ "\n"+
"vertex "+st(X+1)+" "+ st(Y) +" "+ st(Z+1)+ "\n"+
"endloop\n" +
"endfacet\n"+
"facet normal " +"0 0 0"+ "\n"+
"outer loop\n"+
"vertex "+st(X) +" "+ st(Y) +" "+ st(Z)+ "\n"+
"vertex "+st(X+1)+" "+ st(Y) +" "+ st(Z+1)+ "\n"+
"vertex "+st(X) +" "+ st(Y) +" "+ st(Z+1)+ "\n"+
"endloop\n"+
"endfacet\n";
}
function Zquad( X:float , Y:float , Z:float , cnt:float){
qstr+="facet normal " +"0 0 0"+ "\n"+
"outer loop\n"+
"vertex "+st(X) +" "+ st(Y) +" "+ st(Z)+ "\n"+
"vertex "+st(X) +" "+ st(Y+1) +" "+ st(Z)+ "\n"+
"vertex "+st(X+1)+" "+ st(Y+1) +" "+ st(Z)+ "\n"+
"endloop\n" +
"endfacet\n"+
"facet normal " +"0 0 0"+ "\n"+
"outer loop\n"+
"vertex "+st(X) +" "+ st(Y) +" "+ st(Z)+ "\n"+
"vertex "+st(X+1) +" "+ st(Y+1) +" "+ st(Z)+ "\n"+
"vertex "+st(X+1) +" "+ st(Y) +" "+ st(Z)+ "\n"+
"endloop\n"+
"endfacet\n";
}

I would use binary STL, two tringles per quad. More info here: https://en.m.wikipedia.org/wiki/STL_(file_format)

Probably it is possible to store needed information. For your approach it is only needed to store info for vertices used in some previous quad. It is not needed to store quads in memory since they can be write in a file.
There are 1025x1025x1025 (~= 1G) vertices in a grid, and vertex can be identified with triplet of grid coordinates (x, y, z), where 0 <= x, y, z <= 1024. If vertex is used than it gets vertex index in array of vertices (which is written to a file.)
Standard ways to store info are:
map that maps vertex coordinate (x, y, z) to vertex index. Map pair requires 6 bytes of memory for coordinate (3 x int16), and 4 bytes for vertex index (<=1G). Map requires 'few pointers' per one mapping for storage. I think that map can be implemented to use less than 30 bytes for each vertex which is < 2GB memory for your need.
3D array of vertex grid size (1025^3) which stores vertex index for all possible vertices. If vertex was used than it is real vertex index, and -1 (or some other flag) if vertex wasn't used. Simpler implementation than a map. Requires ~4GB memory, which shouldn't be a problem.

Related

Use Kalman Filter to estimate position

I try to use Kalman filter in order to estimate the position. The input in the system is the velocity and this is also what I measure. The velocity is not stable, the system movement is like a cosine in general. So the equation is:
xnew = Ax + Bu + w, where:
x= [x y]'
A = [1 0; 0 1]
B= [dt 0; 0 dt]
u=[ux uy]
w noise
As I mentioned, what I measure is the velocity. My question is how would the matrix C look like in the equation:
y= Cx + v
Should I involve the velocity in the estimated states (matrix A)? Or should I change the equations to involve also the acceleration? I can't measure the acceleration.
One way would be to drop the velocities as inputs and put them in your state. This way, your state is both the position and velocity and your filter uses as observation both the measured speed of your vehicle and a noisy estimate of your position.
With this system your problem becomes:
x = [x_e y_e vx_e vy_e]'
A = [1 0 dt 0; 0 1 0 dt; 0 0 1 0; 0 0 0 1]
w noise
with x_e, y_e, vx_e, and vy_e the estimated values of the state
B is removed because u is 0. And then you have
y = Cx + v
with C = [1 0 0 0 ; 0 1 0 0 ; 0 0 1 0 ; 0 0 0 1]
With y = [x + dt*vx ; y + dt*vy ; vx ; vy] and x, y, vx, and vy the measured values of the velocities and x and y the position calculated with the measured velocities.
It is very similar to the example you will find here on Wikipedia

Determining the number of yellow pixels in land?

I have the below image. I want to determine how many yellow(ish) pixels there are and the percentage of pixels in within the country that are yellow.
So, i need to disregard the sea, france and southern ireland.
Here is my attempt, but I have no idea how to disregard the stuff outside of the country
Also, how can we determine the size in Miles of each Pixel?
from PIL import Image
im = Image.open('covvv.png')
fiveg = 0
other = 0
sea = 0
for p in im.getdata():
if p[0] > 150 and p[1] > 150 and p[2] < 150:
fiveg += 1
elif p[0] == 170 and p[1] > 218 and p[2] < 255:
sea += 1
else:
other += 1
print('5g=' + str(fiveg)+', other='+str(other) + ', sea = 0' + str(sea))
print('%coverage= ' + str((fiveg/other)*100))

How to output numbers to each iteration in a for loop?

for replay_data in raw_replay_data['data']['video_info']:
target.write("Coordinates: " + replay_data['lat'] + (',') + replay_data['lnt'] + "\n")
This for loop gives me fx. the output of:
Coordinates: 0,0
Coordinates: 0,0
Coordinates: 0,0
Coordinates: 0,0
I would like a number after each "Coordinates" string that increases for each new coordinates available.
How can I make it output:
Coordinates 1: 0,0
Coordinates 2: 0,0
Coordinates 3: 0,0
Coordinates 4: 0,0
Look up the enumerate() function, it's your best friend in for loops. Also you can use some str.format() function to make your output more readable:
for index, replay_data in enumerate(raw_replay_data['data']['video_info']):
target.write("Coordinates {0}: {1}, {2}\n".format(index+1, replay_data['lat'], replay_data['lnt'])
You create a counter and count up:
numbr = 1 # counter, starting at 1
for replay_data in raw_replay_data['data']['video_info']:
target.write("Coordinates " + str(numbr) + ": " + replay_data['lat'] + (',') + replay_data['lnt'] + "\n")
numbr += 1 # increment counter
You might want to look into string format methods: string.format
You can do things like:
replay_data = {}
replay_data['lat'] = 1
replay_data['lnt'] = 2
numbr = 22
print("Coordinates {n}: {lat},{lng}\n"
.format(n=numbr, lat = replay_data['lat'], lng = replay_data['lnt']))
Output:
Coordinates 22: 1,2

How to draw normal vectors to an ellipse

How do I draw an ellipse with lines of the same length coming out of it?
It's easy to do with a circle, I can just write something like
for (u = 0 ; u < 2*pi ; u += 0.001*pi) {
drawdot (cos(u), sin(u)) ;
drawline (cos(u), sin(u), 2*cos(u), 2*sin(u) ;
}
But if I did that for an ellipse, like below, the lines are different lengths.
for (u = 0 ; u < 2*pi ; u += 0.001*pi) {
drawdot (2*cos(u), sin(u)) ;
drawline (2*cos(u), sin(u), 4*cos(u), 2*sin(u) ;
}
How do I figure out how to make them the same length?
There are a few ways of thinking about this.
You can think of an ellipse as a circle that's been stretched in some direction. In this case, you've taken the circle x^2 + y^2 = 1 and applied the transformation to all points on that curve:
x' = 2x
y' = y
You can think of this as multiplying by the matrix:
[ 2 0 ]
[ 0 1 ]
To transform normals, you need to apply the inverse transpose of this matrix (i.e. the inverse of the transpose, or transpose of the inverse; it's the same thing):
[ 1/2 0 ]
[ 0 1 ]
(This, by the way, is known as the dual of the previous transformation. This is a very important operation in modern geometry.)
A normal to the circle at the point (x,y) goes in the direction (x,y). So a normal to the ellipse at the point (2x,y) goes in the direction (0.5*x,y). This suggests:
for (u = 0 ; u < 2*pi ; u += 0.001*pi) {
x = cos(u); y = sin(u);
drawdot (2*x, y) ;
drawline (2*x, y, 2*x + 0.5*x, y+y);
}
Or if you need a unit normal:
for (u = 0 ; u < 2*pi ; u += 0.001*pi) {
x = cos(u); y = sin(u);
drawdot (2*x, y) ;
dx = 0.5*x;
dy = y;
invm = 1 / sqrt(dx*dx + dy*dy);
drawline (2*x, y, 2*x + dx * invm, y + dy * invm);
}
Another way to think about it is in terms of an implicit contour. If you define the curve by a function:
f(x,y) = 0
then the normal vector points in the direction:
(df/dx, df/dy)
where the derivatives are partial derivatives. In your case:
f(x,y) = (x/2)^2 + y^2 = 0
df/dx = x/2
df/dy = y
which, you will note, is the same as the dual transformation.

How to center rotated text on page in PostScript

I put text Sample on every PDF page using the following PostScript code:
<<
/EndPage {
exch pop 2 lt {
gsave
/Arial-Bold 120 selectfont
.5 setgray 100 100 moveto 45 rotate (Sample) show
grestore
true}
{false}
ifelse
} bind
>> setpagedevice
This puts text on [100; 100] position. But I need to center this text (accounting text is rotated).
How do I align this 45° rotated text in the center of a page?
You can use false charpath flattenpath pathbbox to get the bounding box of the text.
If the currentpoint is 0 0 when you do this, then the lower-left coordinates will be pretty close to 0 0, so the upper-right coordinates describe the width and height of the text. So you just move to the desired center-point and back-up by making a relative move to (-width/2, -height/2).
Since the center of rotation is also the center-point, you need to translate there before rotating.
%!
/w 612 def
/h 792 def
/Helvetica-Bold 120 selectfont
w .5 mul h .5 mul translate
0 0 moveto
(Sample) false charpath flattenpath pathbbox % llX llY urX urY
4 2 roll pop pop % urX urY
0 0 moveto
45 rotate
-.5 mul exch -.5 mul exch % -wid/2 -ht/2
rmoveto
(Sample) show
For more accuracy, replace 4 2 roll pop pop with
exch % llX llY urY urX
4 1 roll % urX llX llY urY
exch sub % urX llX urY-llY
3 1 roll % urY-llY urX llX
sub exch % urX-llX urY-llY
And then the point can be anywhere (but there does need to be a currentpoint since charpath builds a path just like show does, even though pathbbox destroys it immediately; so you need some kind of moveto).

Resources