How can I generate mesh for a portion of level-set surface using CGAL? - mesh

This is a question about the 3D Surface Mesh Generation tool in CGAL.
According to the documentation, I need to provide the surface to be meshed in implicit-form as a zero level-set surface. This seems to place a restriction on the input surface to be manifold.
The Problem
In my use-case, I need to generate mesh for a small 'region' of an otherwise larger 'parent' manifold implicit surface. The 'region' itself is non-manifold because it does not enclose a volume.
A way I can think of for tackling this is :
Mesh the entire 'parent' surface, and then
Extract the mesh corresponding to the required 'region'.
However, I want to avoid this for performance reasons.
How should I proceed with this ?
Is any other module available in CGAL that can help me achieve this ?

As your surface is implicit, you can easily create function that represents the intersection of that implicit surface with an implicit volume, like a sphere, a bounding box, or a half-space.
Let's, for example, that you have the equation of a sphere:
auto sphere(double x, double, y, double z) {
return x*x + y*y + z*z - 1;
}
then you can compute the intersection with a half-space, like that:
auto half_space(double x, double y, double z) {
return y - x > 0 ? -1. : -1.;
}
auto intersection(double, x, double y, double z) {
if(half_space(x, y, z) > 0) return 1.
else return sphere(x, y, z);
}

Related

Code for Archimedean Spiral with equidistant points is inaccurate near center

I need to be able to find x, y coordinates at any length down an Archimedean spiral arm, given a specific distance between each loop of the arm.
I have researched previous questions on Stackoverflow, and across the Internet, and I have found three methods, which are each different, and each plot me a spiral. (I call them the first, second and third method, here.)
The first method, does plot equidistant points, with the pointdist variable = 1, but as this is increased, there is also an aberration of point distances (supposed to be equidistant) near the center of the spiral.
The third method and second method, do not correctly plot equidistant points near the center of the spiral. (See graphs below)
The third method, though, allows me to input any length down the arm and obtain x, y coordinates.
The first and second methods plot equidistant points by a process where they additively sum a variable, each cycle of a loop to plot the equidistant points. Because of how this value is built up instead of calculated from scratch using only the distance along the spiral arm variable, I can't use these two methods to find coordinates at any arbitrary length along the arm [Proofreading this, I just thought, perhaps if I initialize the length to calculate one point each time. However, all three methods have problems even with equidistant points.]
Here is output from the third method:
Here is the code of the "third method". This method uses what an answer to another sprial-related question on Stackoverflow (Placing points equidistantly along an Archimedean spiral) calls the "Clackson scroll formula", which is said to be possibly inaccurate in some ranges.
double thetamax = 10 * Math.PI;
double b = armbandwidth / (2 * Math.PI);
// "armbandwidth” value influences distance between the spiral arms, usually kept between 1 and 20
AddPoint(0,0); // Mark the origin of the spiral
// “pointdist” is the length between points to plot along the spiral, I use 0.1 to 2+
// but it doesn't reveal spiral shape with increasing values
for (double s = pointdist; s < spirallength; s += pointdist)
{
double thetai = Math.Sqrt(2 * s / b);
double xx = b * thetai * Math.Cos(thetai);
double yy = b * thetai * Math.Sin(thetai);
AddPoint(xx, yy);
}
I need to both:
Use a method that does not have aberrations in the equidistance of points along the spiral arm, given equally spaced values of lengths down the spiral arms.
Use a method that allows me to specify the width between the spiral arms (in terms of the same units used for the length along spiral arm between the points, as well).
In case it helps, and to be clear about what I've tried, here are the code and output from the other methods I've found and tested (here called "second method" and "first method") for calculating the coordinates of equidistant points along an Archimedean spiral:
Here is output from the second method (note the uneven distanced points near center):
Here is the code for the second method:
AddPoint(0,0); // Mark the origin of the spiral
double arclength = 0.8; // This value (kept between 0.1 and 20 or so) sets the distance between points to calculate coordinates for along the spiral curve
double r = arclength;
double b = armbandwidth / (2 * Math.PI); // "armbandwidth" value influences distance between the spiral arms, usually kept between 3.5 to 10
double phi = r / b;
double xx = r * Math.Cos(phi);
double yy = r * Math.Sin(phi);
AddPoint(xx, yy);
while( r <= spirallength ) // spirallength determines roughly how many iterations of points to draw
{
phi += arclength / r;
r = b * phi;
xx = r * Math.Cos(phi);
yy = r * Math.Sin(phi);
AddPoint(xx, yy);
}
Because the variable phi is additively increased each iteration, I can't pass in any length down the spiral arm to find coordinates for. (Maybe if I initialized the whole method only to a single arclength each time. - In any case, the points near center are not evenly spaced.)
Here is output from the first method (Equidistant points throughout with pointdist = 1):
Here is the code of the first method:
double separation = 4; // Value influences distance between the spiral arms, usually kept 3.5 to 10+
double angle = 0;
double r;
AddPoint(0,0); // Mark the origin of the spiral
for (double i=0; i <= spirallength; i+=pointdist) // spirallength determines pointdist spaced points to plot
{
r = Math.Sqrt(i+1);
angle += Math.Asin(1/r);
double xx = Math.Cos(angle) * r*separation;
double yy = Math.Sin(angle) * r*separation;
AddPoint(xx, yy);
}
However, when "pointdist" is increased above 1, there are aberrations in equidistance between points near the center of the spiral, even by this method. Here is the output of a graph using the "first method" and pointdist = 9:
Can anyone help me calculate x, y coordinates for any length down the spiral arm from center, for an Archimedes spiral defined by a specified width between loops of the arm?
(It should be able to have equidistant points, accurate even near the center, and be able to take a width between loops of the arm in units the same scale as those used for the distance to a point along the arm passed to the coordinates equation.)
Much appreciated!
I believe this last piece of code is the best (most simple and straightforward) approach:
constant angle variation
For a given angle
calculate the radius
convert Polar coordinates to Cartesian.
However, I understand the Archimedean spiral is defined by the formula: r = a + b * angle (where a=0 to simplify, and b controls the distance between loops.
In short, the position of particle is proportional to the angle θ as time elapses.
So what's up with that? That's not linear at all!
r = Math.Sqrt(i+1);
angle += Math.Asin(1/r);
Here's a simple way to make it.
It's not a running code. But I believe it's very easy to understand.
So just understand the logic and then code it with your own variables:
for (some incrementing t)
{
radius = t/100; //Start at radius = 0. When t = 100, radius=1.
angle = t*2*Pi/200; //It takes 200 points to make a full 360 (2Pi) turn
//Now converting from polar coordinates (r,angle) to (x,y):
x = cos(angle) * r;
y = sin(angle) * r;
AddPoint(x, y);
}
This code generates the following image:
This generates the right trajectory. However, as noticed, this does not produce equidistant points, because each angle increment is multiplied by the radius. So I suggest you to find a correction function and apply it to t. Like so:
function correction(i)
{
// I actually don't know the exact relationship between t and i
t = 1/i
// But I think it converges to t=1/i for very small increments
return t
}
for (some incrementing i)
{
t = correction(i)
...
}

How to convert relative GPS coordinates to a "local custom" x, y, z coordinate?

Let's say I know two persons are standing at GPS location A and B. A is looking at B.
I would like to know B's (x, y, z) coordinates based on A, where the +y axis is the direction to B (since A is looking at B), +z is the vertically to the sky. (therefore +x is right-hand side of A)
I know how to convert a GPS coordinate to UTM, but in this case, a coordinate system rotation and translation seem needed. I am going to come up with a calculation, but before that, will there be some codes to look at?
I think this must be handled by many applications, but I could not find so far.
Convert booth points to 3D Cartesian
GPS suggest WGS84 so see How to convert a spherical velocity coordinates into cartesian
Construct transform matrix with your desired axises
see Understanding 4x4 homogenous transform matrices. So you need 3 perpendicular unit vectors. The Y is view direction so
Y = normalize(B-A);
one of the axises will be most likely up vector so you can use approximation
Z = normalize(A);
and as origin you can use point A directly. Now just exploit cross product to create X perpendicular to both and make also Y perpendicular to X and Z (so up stays up). For more info see Representing Points on a Circular Radar Math approach
Transfrom B to B' by that matrix
Again in the QA linked in #1 is how to do it. It is simple matrix/vector multiplication.

How to place sprites along a curve in cocos2d

The set up of my game relies on placing several sprites along a curve that may look like a bow , ellipse, or be a bit more complex (assume it would be bezier curve then). I want to be able to place my sprites in somewhat equal distances apart.
Can anyone share how this could be done ?
Using cocos2d 2.1
I dont know if there is an easier method to do this ,but we could arrange the sprite along any curve by using the mathematical equation for that curve.
For a parabolic curve (advantage: symmetrical,so easy to place equidistant points)
Find out a equation that satisfies your start and EndPoints and obtain the y values for equidistant x points between start and end using the function below.
example: y = -x^2 + 20x - 1 (general equation : y = ax^2 + bx + c)
static inline parabolicYValue(float x, float a,float b, float c){
return (powf(a*x,2) + b*x + c);
}
You could come up with a similar function for Bezier curves :
(Bezier cubic curve)
static inline CGFloat bezierYValue( float a, float b, float c, float d, float x )
{
return (powf(1-x,3) * a +
3*x*(powf(1-x,2))*b +
3*powf(x,2)*(1-x)*c +
powf(x,3)*d );
}
However, obtaining equidistant points on a bezier curve is a bit of a chore. On the other hand if you by equidistant you mean , distance only along the x axis then this should not be problem.

How can I find the points in a line - Objective c?

Consider a line from point A (x,y) to B (p,q).
The method CGContextMoveToPoint(context, x, y); moves to the point x,y and the method CGContextAddLineToPoint(context, p, q); will draw the line from point A to B.
My question is, can I find the all points that the line cover?
Actually I need to know the exact point which is x points before the end point B.
Refer this image..
The line above is just for reference. This line may have in any angle. I needed the 5th point which is in the line before the point B.
Thank you
You should not think in terms of pixels. Coordinates are floating point values. The geometric point at (x,y) does not need to be a pixel at all. In fact you should think of pixels as being rectangles in your coordinate system.
This means that "x pixels before the end point" does not really makes sense. If a pixel is a rectangle, "x pixels" is a different quantity if you move horizontally than it is if you move vertically. And if you move in any other direction it's even harder to decide what it means.
Depending on what you are trying to do it may or may not be easy to translate your concepts in pixel terms. It's probably better, however, to do the opposite and stop thinking in terms of pixels and translate all you are currently expressing in pixel terms into non pixel terms.
Also remember that exactly what a pixel is is system dependent and you may or may not, in general, be able to query the system about it (especially if you take into consideration things like retina displays and all resolution independent functionality).
Edit:
I see you edited your question, but "points" is not more precise than "pixels".
However I'll try to give you a workable solution. At least it will be workable once you reformulate your problem in the right terms.
Your question, correctly formulated, should be:
Given two points A and B in a cartesian space and a distance delta, what are the coordinates of a point C such that C is on the line passing through A and B and the length of the segment BC is delta?
Here's a solution to that question:
// Assuming point A has coordinates (x,y) and point B has coordinates (p,q).
// Also assuming the distance from B to C is delta. We want to find the
// coordinates of C.
// I'll rename the coordinates for legibility.
double ax = x;
double ay = y;
double bx = p;
double by = q;
// this is what we want to find
double cx, cy;
// we need to establish a limit to acceptable computational precision
double epsilon = 0.000001;
if ( bx - ax < epsilon && by - ay < epsilon ) {
// the two points are too close to compute a reliable result
// this is an error condition. handle the error here (throw
// an exception or whatever).
} else {
// compute the vector from B to A and its length
double bax = bx - ax;
double bay = by - ay;
double balen = sqrt( pow(bax, 2) + pow(bay, 2) );
// compute the vector from B to C (same direction of the vector from
// B to A but with lenght delta)
double bcx = bax * delta / balen;
double bcy = bay * delta / balen;
// and now add that vector to the vector OB (with O being the origin)
// to find the solution
cx = bx + bcx;
cy = by + bcy;
}
You need to make sure that points A and B are not too close or the computations will be imprecise and the result will be different than you expect. That's what epsilon is supposed to do (you may or may not want to change the value of epsilon).
Ideally a suitable value for epsilon is not related to the smallest number representable in a double but to the level of precision that a double gives you for values in the order of magnitude of the coordinates.
I have hardcoded epsilon, which is a common way to define it's value as you generally know in advance the order of magnitude of your data, but there are also 'adaptive' techniques to compute an epsilon from the actual values of the arguments (the coordinates of A and B and the delta, in this case).
Also note that I have coded for legibility (the compiler should be able to optimize anyway). Feel free to recode if you wish.
It's not so hard, translate your segment into a math line expression, x pixels may be translated into radius of a circe with center in B, make a system to find where they intercept, you get two solutions, take the point that is closer to A.
This is the code you can use
float distanceFromPx2toP3 = 1300.0;
float mag = sqrt(pow((px2.x - px1.x),2) + pow((px2.y - px1.y),2));
float P3x = px2.x + distanceFromPx2toP3 * (px2.x - px1.x) / mag;
float P3y = px2.y + distanceFromPx2toP3 * (px2.y - px1.y) / mag;
CGPoint P3 = CGPointMake(P3x, P3y);
Either you can follow this link also it will give you the detail description -
How to find a third point using two other points and their angle.
You can find out number of points whichever you want to find.

Determining if a vertex is to the left or right of the camera

If you have a given vertex how could you determine whether that vertex is to the left or right (or possibly directly in line with) the camera?
All the info I find on this shows how to do it in 2D but I need 3D.
If I add the camera's look vector onto the camera's location I will have the ray that I need.
But the up vector also has to be thrown into the equation, so it seems a little tricky.
I think I have to find a transformation that makes the up vector = (0, 1, 0) and the look vector = (0, 0, 1) and then apply that transformation to the vertex. Then you can just say if the vertice's x coordinate is less than the camera's then it is to its left, else it is to the right.
It's as simple as multiplying the vector by the View-Projection matrix.
Here is what it boils down to though so you don't have to do a full matrix multiplication (you only need to check one section of the resulting matrix to see which side of the screen the vertex is on)
private bool left(Vector3 v)
{
if (viewProjection.M11 * v.X + viewProjection.M21 * v.Y + viewProjection.M31 * v.Z + viewProjection.M41 < 0)
return true;
return false;
}
viewProjection is obviously just the view matrix * projection matrix