How to compute the vertices for a 3D polyline extrusion? - c#

I have a polyline composed of multiple line segments. The line is very complex and squiggles all over the place in 3D, so for simplicity's sake let's say it looks something like this
I want to render it in 3D. Currently, I do a very simple process where I just generate a cylinder for each segment:
This is decent, but looks bad where the line changes direction. It is also wasteful - each of the direction changes requires twices as many vertices as is strictly necessary. I would be much happier with an approach that generated shapes like this:
At first I didn't think it would be too hard, but the more I've worked on it the more I've found it to be surprisingly nontrivial. I'm working in C#, and if this were in 2D I would just use Clipper, but I can't find any libraries or resources for how to solve this problem in 3D. It's okay if the solution isn't always perfect or sometimes leads to self-intersections or things of that nature. Anyone have any guidance?

So in a mathematical sense, the intersection of two cylinders is an ellipse. If I give you where the semi-major axis point on the ellipse is and the semi-minor axis you could calculate any number (like numsides) nodes on the ellipse.
Take the node connecting two segments located at a point p and define the two vectors of the ellipse as follows. a is the semi-major axis and b is the semi-minor axis
Each joining line segment has unit directions vectors e_1 and e_2 and the cylinder has radius R.
Then the intersection ellipse would be defined from the vectors a and b:
Then find a point c around the ellipse use the following parameterization with t = 0..1
Here is some C# code that calculates numsides points around the ellipse
// Vectors p, a, b defined
for(int i=0; i<numsides; i++)
{
double t = (1.0*i)/numsides
Vector c = p + a*Math.Cos(2*Math.PI*t) + b*Math.Sin(2*Math.PI*t)
// use/store c as needed for the mesh generation
}

I found this site which had an elegant solution. Starting with some points around the first line segment making up your polyline, you compute the intersection of the line parallel to the current segment that passes through each point and the plane formed by the intersection of the two current line segments.

Related

How do I find the control points for a Bezier curve?

I need to implement connections in the form of curved lines in C# (Unity). I would like to get the result as similar as possible to the implementation in Miro.com (see screenshot).
After attaching the curve, I calculate the path of the cubic Bezier curve. For this first segment, the anchor points and offsets from the objects it connects are used. There are no problems at this stage.
Problem: When dividing the curve into segments by clicking and dragging one of the blue points of the segment (see screenshot), it is split in two in the middle. At the junction of two new curves, a new interactive (movable) point is formed for which the tangent and coordinates of the control points are unknown. I need to find the position of these control points every time the position of the interactive points changes (white points in the picture below). Moreover, the curve should not drastically change its position when dividing, not form loops, have different lengths of control point vectors (I'm not sure here) and behave as adequately as possible (like on the board in Miro).
By control points I mean 2 invisible guide points for the Bezier segment.
In black I painted the known control points, and in red those that I need to find. (Pn - interactive points, Cn - control points)
The algorithms I have tried to find them give incorrect distances and directions of control points.
The following algorithms were tested:
Interpolation from Tacent - jumps of the curve when separating, inappropriate direction and amount of indentation of control points;
Chaikin's algorithm - curve jumps during separation, creates loops;
"Custom" interpolation based on guesses (takes into account the distance to the center of the segment between the start and end points of the segment, as well as the direction between the start and end points) - has all the same problems, but looks slightly better than those above.
I suspect the solution is to chordally interpolate the points using a Catmull-Rom spline and translate the result to points for a Bezier curve. However, there are still problems with implementation.
The curves from 3DMax also look very similar. In their documentation, I found only a mention of the parametric curve.
Methods that I did not use (or did not work):
Catmull-Rom interpolation;
B-spline interpolation;
Hermitian interpolation;
De Casteljau's algorithm (although it seems not for this)
I would be immensely grateful for any help, but I ask for as much detail as possible.
Find helpful sources to understand bezier curves here and here.
To do what you want, I would give a try to the Catmull-Rom approach which I believe is much more simple than Bezier's, which is the one used in the itween asset, that is free, and you got plenty of funtionality implemented.
If you want to stick to the bezier curves and finding the control points, I will tell you what I would do to find them.
For the case of 2 control point bezier curve:
P = (1-t)P1 + tP2
To get to know the control points P1(x1,y1) and P2(x2,y2), you need to apply the equation in a known point of your curve. Take into account that the 2D equation is vectorial, so each points provides 2 equations one for x and one for y, and you got 4 unknows, x and y for each point.
So for the first node of the curve (t=0), you would have:
Px = (1-0)P1x + 0*P2x
Py = (1-0)P1y + 0*P2y
For the last point (t=1)
Px = (1-1)P1x + 1*P2x
Py = (1-1)P1y + 1*P2y
With these 4 equations I would try to achieve the control points P1 and P2. You can do it with t=0 and t=1 which are the supposed points you know of your curve and the ones that simplify the math due to the t values, but you should be able to use any as long as you know the points coords in the curve for determined t.
If the curve is a 3 control point bezier, you would need 6 equations for the 3 control points and so on.
I think that the best approach is to compound the curve of cuadratic curves composition, and calculate the control points for each chunk, but I am not sure about this.
Once maths are understood and control points achieved, In case that was successful I would try to implement that in the code.

Wall generator script

I have some trouble.
I need generate walls by path.
For example. I have vectors A, B, C. And I need to find vectors D, E, F for creating volumetric walls around ABC.
Firstly, I going on easiest way - scaling ABC (with finding a centroid).
But it's not a correct solution, b/c I need to set correct width of walls, and I need to find some additional points like this (point J and point K with JK perpendicular AB)
I will be gratefull for any help!
You will need to find out normals to the outer edge of the polygon.
There could be two approaches.
One is using edge normals, another is vertex normals.
On edge normals you will need to find out what direction is outside (depends on closed / open)
If you use vertex normals, you will only need to translate the vertex to the new position. Finding out a good vertex normal is the main problem.
This is known as offsetting. More details can be found below.
An algorithm for inflating/deflating (offsetting, buffering) polygons

Make a sphere with equidistant vertices

I'm trying to make a spherical burst of rays for the purpose of checking collision, but having specific interactions happen based upon what or where each ray hit. Hence why I'm using rays rather then something simpler such as OverlapSphere.
The reason I'm looking for how to make a sphere is because I can use the same math for my rays, by having them go to the vertices of where the sphere would be. But every way I can find for making a sphere has the lines get closer the near to the poles, which makes sense, as its pretty easy to do. But as you can imagine, its not that useful for my current project.
TL;DR:
How do I make a sphere with equidistant vertices? If its not perfectly equidistant its fine, it just needs to pretty close. If this happens, it would be great if you could give how much the difference would be, and where, if applicable.
Extra notes:
I've looked at this and this, but the math is way over my head, so what I've been looking for might've just been staring me in the face this whole time.
You could use an icosphere. As the vertices are distributed on equilateral triangles, your vertices are guaranteed to be equidistant.
To construct the icosphere, first you make an icosahedron and then split the faces recursively in smaller triangles as explained in this article.
Are you aware that the sphere given to you by Unity is in fact designed
with this exact goal in mind?
ie, the entire raison d'etre of the sphere built-in to Unity is that the points are fairly smoothly space ...... roughly equidistant, as you phrase it.
To bring up such a sphere in Unity, just do this:
You can then instantly get access to the verts, as you know
Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector3[] vv = mesh.vertices;
int kVerts=vv.Length
for (int i=0; i<kVerts; ++i)
Debug.Log ... vv[i]
Note you can easily check "which part of the sphere" they are on by (for example) checking how far they are from your "cities" (or whatever) or just check (for example) the z values to see which hemisphere they are in .. et cetera.
Furthermore...
Please note. Regarding your overall reason for wanting to do this:
but having specific interactions happen based upon what or where each ray hit
Note that it could not be easier to do this using PhysX. (The completely built-in game physics in Unity.) Indeed, I have never, ever, looked at a collision without doing something "specific" depending on "where it hit!"
You can for example get the point where the contact was with http://docs.unity3d.com/ScriptReference/RaycastHit-point.html
It's worth noting it is absolutely inconceivable one could write something approaching the performance of PhysX in casual programming.
I hope this makes things easier!
slice the sphere into N circles
compute perimeter of it
divide it by the same angle that create the slice
this gives you the number of vertexes
and also angle step inside circle
cast rays
This is how I coded it in C++ + OpenGL:
// draw unit sphere points (r=1 center=(0,0,0)) ... your rays directions
int ia,na,ib,nb;
double x,y,z,r;
double a,b,da,db;
na=16; // number of slices
da=M_PI/double(na-1); // latitude angle step
for (a=-0.5*M_PI,ia=0;ia<na;ia++,a+=da) // slice sphere to circles in xy planes
{
r=cos(a); // radius of actual circle in xy plane
z=sin(a); // height of actual circle in xy plane
nb=ceil(2.0*M_PI*r/da);
db=2.0*M_PI/double(nb); // longitude angle step
if ((ia==0)||(ia==na-1)) { nb=1; db=0.0; } // handle edge cases
for (b=0.0,ib=0;ib<nb;ib++,b+=db) // cut circle to vertexes
{
x=r*cos(b); // compute x,y of vertex
y=r*sin(b);
// this just draw the ray direction (x,y,z) as line in OpenGL
// so you can ignore this
// instead add the ray cast of yours
double w=1.2;
glBegin(GL_LINES);
glColor3f(1.0,1.0,1.0); glVertex3d(x,y,z);
glColor3f(0.0,0.0,0.0); glVertex3d(w*x,w*y,w*z);
glEnd();
}
}
This is how it looks like:
R,G,B lines are the sphere coordinate system axises X,Y,Z
White-ish lines are your Vertexes (White) + direction (Gray)
[Notes]
do not forget to include math.h
and replace the OpenGL stuff with yours
If you want 4, 6, 8, 12 or 20 vertices then you can have exactly equidistant vertices as the Platonic solid which all fit inside a sphere. The actual coordinates of these should be easy to get. For other numbers of vertices you can use other polyhedra and scale the verties so they lie on a sphere. If you need lots of points then a geodesic dome might be a good base. The C60 bucky-ball could be a good base with 60 points. For most of these you should be able to find 3D models from which you can extract coordinates.
I think the easiest way to control points on a sphere is by using spherical coordinates. Then you can control position of points around the sphere by using two angles (rho and phi) and the radius.
Example code for filling points uniformly around a rotating sphere (for fun):
var time = 1; // Increment this variable every frame to see the rotation
var count = 1000;
for (int i = 0; i < count; i++)
{
var rho = time + i;
var phi = 2 * Math.PI * i / count;
var x = (float)(radius * Math.Sin(phi) * Math.Cos(rho));
var z = (float)(radius * Math.Sin(phi) * Math.Sin(rho));
var y = (float)(radius * Math.Cos(phi));
Draw(x, y, z); // your drawing code for rendering the point
}
As some answers have already suggested, use an icosahedron based solution. The source for this is quite easy to come by (and I have written my own several times) but I find the excellent Primitives Pro plugin extremely handy under many other circumstances, and always use their sphere instead of the built-in Unity one.
Link to Primitives Pro component
Primitives Pro options

Algorithm to generate equally distributed points in a polygon

I am looking for an algorithm to generate equally distributed points inside a polygon.
Here is the scenario:
I have a polygon specified by the coordinates of the points at the corners (x, y) for each point. And I have the number of points to generate inside the polygon.
For example lets say I have a polygon containing 5 points: (1, 1) ; (1, 2) ; (2, 3) ; (3, 2) ; and (3, 1)
And I need to generate 20 equally distanced points inside that polygon.
Note: Some polygons may not support equally distributed points, but I'm looking to distribute the points in a way to cover all the region of the polygon with as much consistency as possible. (what i mean is I don't want a part with a lot more points than another)
Is there an algorithm to do so? or maybe a library
I am working on a C# application, but any language is ok, since I only need the algorithm and I can translate it.
Thanks a lot for any help
The simple approach I use is:
Triangulate the polygon. Ear clipping is entirely adequate, as all you need is a dissection of the polygon into a set of non-overlapping triangles.
Compute the area of each triangle. Sample from each triangle proportionally to the area of that triangle relative to the whole. This costs only a single uniform random number per sample.
Once a point is determined to have come from a given triangle, sample uniformly over the triangle. This is itself easier than you might think.
So really it all comes down to how do you sample within a triangle. This is easily enough done. A triangle is defined by 3 vertices. I'll call them P1, P2, P3.
Pick ANY edge of the triangle. Generate a point (P4) that lies uniformly along that edge. Thus if P1 and P2 are the coordinates of the corresponding end points, then P will be a uniformly sampled point along that edge, if r has uniform distribution on the interval [0,1].
P4 = (1-r)*P1 + r*P2
Next, sample along the line segment between P3 and P4, but do so non-uniformly. If s is a uniform random number on the interval [0,1], then
P5 = (1-sqrt(s))*P3 + sqrt(s)*P4
r and s are independent pseudo-random numbers of course. Then P5 will be randomly sampled, uniform over the triangle.
The nice thing is it needs no rejection scheme to implement, so long, thin polygons are not a problem. And for each sample, the cost is only in the need to generate three random numbers per event. Since ear clipping is rather simply done and an efficient task, the sampling will be efficient, even for nasty looking polygons or non-convex polygons.
An easy way to do this is this:
Calculate the bounding box
Generate points in that box
Discard all points not in the polygon of interest
This approach generates a certain amount of wasted points. For a triangle, it is never more than 50%. For arbitrary polygons this can be arbitrarily high so you need to see if it works for you.
For arbitrary polys you can decompose the polygon into triangles first which allows you to get to a guaranteed upper bound of wasted points: 50%.
For equally distanced points, generate points from a space-filling curve (and discard all points that are not in the polygon).
You can use Lloyd’s algorithm:
https://en.m.wikipedia.org/wiki/Lloyd%27s_algorithm
You can try the {spatialEco} package (https://cran.r-project.org/web/packages/spatialEco/index.html)
and apply the function sample.poly (https://www.rdocumentation.org/packages/spatialEco/versions/1.3-2/topics/sample.poly)
You can try this code:
library(rgeos)
library(spatialEco)
mypoly = readWKT("POLYGON((1 1,5 1,5 5,1 5,1 1))")
plot(mypoly)
points = sample.poly(mypoly, n= 20, type = "regular")
#points2 = sample.poly(mypoly, n= 20, type = "stratified")
#another type which may answer your problem
plot(points, col="red", add=T)
The easy answer comes from an easier question: How to generate a given number of randomly distributed points from the uniform distribution that will all fit inside a given polygon?
The easy answer is this: find the bounding box of your polygon (let's say it's [a,b] x [c,d]), then keep generating pairs of real numbers, one from U(a,b), the other from U(b,c), until you have n coordinate pairs that fit inside your polygon. This is simple to program, but, if your polygon is very jagged, or thin and skewed, very wasteful and slow.
For a better answer, find the smallest rotated rectangular bounding box, and do the above in transformed coordinates.
Genettic algorithms can do it rather quickly
Reffer to GENETIC ALGORITHMS FOR GRAPH LAYOUTS WITH GEOMETRIC CONSTRAINTS
You can use Force-Directed Graph for that...
Look at http://en.wikipedia.org/wiki/Force-based_algorithms_(graph_drawing)
it defiantly can throw you a bone.
I didn't try it ever,
but i remmember there is a possiblity to set a Fix for some Vertices in the Graph
Your Algorithm will eventually be like
Create a Graph G = Closed Path of the Vertices in V
Fix the Vertecies in place
Add N Verticies to the Graph and Fully connect them with Edges with equal tension value 1.0
Run_force_graph(G)
Scale Graph to bounded Box of
Though it wont be absolute because some convex shapes may produce wiered results (take a Star)
LASTLY: didn't read , but it seems relevant by the title and abstract
take a look at Consistent Graph Layout for Weighted Graphs
Hope this helps...
A better answer comes from a better question. Suppose you want to put a set of n watchtowers to cover a polygon. You could see this as an optimization problem: find the 2n coordinates of the n points that will minimize a cost function (or maximize a value function) that fits your goal. One possible cost function could calculate, for each point, the distance to its closest neighbor or the boundary of the polygon, whichever is less, and calculate the variance of this sequence as a measure of "non-uniformity". You could use a random set of n points, obtained as above, as your initial solution.
I've seen such a "watchtower problem" in some book. Algorithms, calculus, or optimization.
#Youssef: sorry about the delay; a friend came, and a network hiccuped.
#others: have some patience, don't be so trigger-happy.

Collision detecting custom sketched shape, represented as list of points

I have a set of points, drawn by the user. They will be drawing around some objects.
I need to somehow turn this set of points into a shape, so I can find the area to detect collisions.
An image will clarify:
Set of points represented as shape http://www.imagechicken.com/uploads/1277188630025178800.jpg
.
The best idea I have had so far involves iterating over every pixel determining if it is 'inside' or 'outside' the shape, but that would be horribly slow, and I'm not even sure how to do the determining 'inside'/'outside' bit...
Any hints? I am using .NET (C# and XNA) if that helps you help me!
You can think of your shape as an union of several shapes each of which is a simple closed polygon.
the check for every object if it is inside any of the polygons in the following manner:
All dots connected by lines - each line has an equation defining it.
For every object - build an equation for a line passing through this object.
now - for each object equation you need to check how many lines (those between the dots) intersects this object equation - but count only the intersection points that are in the rage between the two dots (and not in the rest of the line outside the two dots) and only the intersection points that are in one side of the object (pick a side - doesn't matter).
If the count is even - the object is outside the shape - otherwise it is inside.
Just a precursor to anything I will say, I have no experience in this field, this is just how I would go about the problem.
A tactic a lot of games use for this is known as Hit Boxes. It is much easier to detect if a point is inside a square than any other figure. But this doesn't give you an exact collision, it could be right outside your desired object.
I've seen Collision 'Bubbles' used before. Here is a link I found for you. This explains the use of Collision Bubbles in the console game Super Smash Brothers.
Given a point, the distance formula, and a radius, you can easily implement collision bubbles.
To take it even one step forward, I did a little bit of research, I saw a nifty little algorithm (more advanced that the top two suggestions), the "Gilbert-Johnson-Keerthi Collision detection algorithm for convex objects." Here is a link for ya. The implementation provided is written in D. If your working in C# it shouldn't be too hard to translate (I would highly suggest digesting the algorithm too).
Hope this gives you some direction.
Well I got it working thanks to some help on another forum.
I used the GraphicsPath class to do all the hard work for me.
This is what my method ended up looking like:
public bool IsColliding(Vector2 point)
{
GraphicsPath gp = new GraphicsPath();
Vector2 prevPoint = points[0];
for (int i = 1; i < points.Count; i++)
{
Vector2 currentPoint = points[i];
gp.AddLine(prevPoint.X, prevPoint.Y, currentPoint.X, currentPoint.Y);
prevPoint = currentPoint;
}
gp.CloseFigure(); //closing line segment
return gp.IsVisible(point.X, point.Y);
}
Thanks for your suggestions both of you

Categories