Imagine the surface of a triangle in cartesian space. How can I find the distance of a given point from the surface of that triangle?
Point 1: [ 30, 24, 22 ]
Point 2: [ 35, 13, 19 ]
Point 3: [ 21, 29, 85 ]
In this case, how far is the point [ 40, 25, 77 ] from the surface of the triangle defined above?
Or specifically - what would the formula be to determine that distance?
I will assume you mean minimal distance. Otherwise, the distance changes depending on which point on the triangle you pick. To see that, just draw a triangle on your table and hold a pen above it.
The short answer is, to find the minimal distance, you need to build a matrix with one point per column, like so:
[ 30 35 21 ]
A = [ 24 13 29 ]
[ 22 19 85 ]
And read about projections for the details. If it has been a while since you studied this kind of stuff, don't be intimidated. It isn't rocket science (actually, maybe it is in intro to rocket science), but it will take some investment to understand. To help you along, I'll mention a bit about the theory first, and then talk about implementation.
To give you some intuition, hold on to that pen.
Lets start with the easiest case: To get the minimal distance, hold the pen exactly perpendicular to the table, with the end of the pen in the triangle somewhere. Picture your point as the tip of the pen. You just proved that the point in the triangle closest to your point is the projection of that point onto the space defined by the three points in the triangle. In other words, the other end of the pen. Any other point in the triangle must have distance longer then the pen length.
Now lets look at a complication. Suppose that the point you want is not exactly "above" the triangle, but rather to the side somewhere. Say, off of the surface of the table altogether. In this case, the point in the triangle closest to the point will either be one of three points themselves, or a point on the three line segments connecting the three initial points.
Now for the implementation: the skinny is, if you can use a simple library for linear algebra, you will save yourself a lot of grief. The hardest step is inverting the matrix, and while inverting 3x3 matrices is usually easy, it can get complicated when points are co-linear (i.e., think about three points that are aligned), when magnitudes are very different (i.e., think of a very long skinny triangle), etc.
You could write a problem-specific algorithm for this problem, given that it is only 3x3, but at the end of the day you will need to solve a projection system, so your algorithm will be doing essentially the same math that is on the Wikipedia page. So you may end up rediscovering linear algebra, which is a sure way to waste A LOT of time.
My last implementation suggestion is to check the keyword "projection" in gaming or 3D libraries. If you are lucky there is a function you can just call. Otherwise get some decent CLR linear algebra library, build the matrix, and do the entire computation efficiently and in 100 lines of code or so.
It all depends on where abouts you want the distance to come from (Which part of the triangle?). If you know the point of the triangle to start from (centre maybe?) then, from a maths perspective, the formula is:
Point 1: [a1,b1,c1] (point on triangle)
Point 2: [a2,b2,c2] (point to find distance to)
distance vector = [a2-a1, b2-b1, c2-c1]
distance = the magnitude of above = sqrt((a2-a1)^2 + (b2-b1)^2 + (c2-c1)^2))
I don't know C#, but this would be the pseudo code for it (the maths behind it)
Edit: To find centre of triangle...
Point 1: [x1, y1, z1]
Point 2: [x2, y2, z2]
Point 3: [x3, y3, z3]
Centre = [(x1+x2+x3)/3, (y1+y2+y3)/3, (z1+z2+z3)/3]
Related
I am trying to find a way to get the line (two points in 3D space) of the intersection between two rectangles.
I ran into this question: Intersection between two rectangles in 3D
But this is not my issue. In that question, the rectangle is treated as only the bounds (the perimeter), while I am looking for the rectangle as a whole (think about a picture frame vs the picture itself).
I've figured out that, in every case, there will either be an intersection line (two points), or no intersection at all. If the intersection was just on the borders, therefore just a point, it can be treated as no intersection in my case.
My scenario is that one of these rectangle represents a "static" surface, which cannot move or change. The other one represents a "dynamic" surface, which I have to adapt to avoid crossing
Example:
Once I obtain p1 and p2, which are points in the 3D space, my goal is to modify the Dynamic rectangle into a 3d polygon, which will no longer cross the static rectangle, like this:
So you can see why "edge intersections" are irrelevant to my situation. I am turning "real" intersections into edge intersections, so any edge intersection doesn't require me to do anything with it.
I am only looking for a formula, starting with two sets of 4 points (the rectangles), that would give me the two points of the line of their intersection, or would tell me that there is no (relevant) intersection.
Every formula I've found on this site or others doesn't fit my needs, or doesn't let me input arbitrary rectangles (for example, I can't fix my problem with a formula that uses planes or that treats a rectangle as simply 4 lines)
I am, of course, trying to code it (in C#), therefore any code answer is a great help, but I am confident that even a math-only answer would suffice for me to produce the code from it, therefore I will accept an answer that is only composed of pseudo-code or straight up mathematical formulas, provided they are either simple enough or explained well enough for me to understand what is happening.
If you are OK with just algorithm rather than full code here is a sketch:
Build 2 planes from the rectangles (any 3 points will do as in this answer)
Find the intersection line I of those 2 planes as in this answer or find out that the planes are parallel so there is no intersection
Find the intersections of the I line with the lines containing all sides of the rectangles as in this answer
Check whether some points found in the previous step lie inside the corresponding sides of the rectangles (line segments). This step potentially can be merged with the previous one, but I put it separately for simplicity. Now you potentially have 0, 1 or 2 segments that represent the intersections of the I line with your two rectangles (note that here point is treated as an edge case of a segment where both ends are the same). If you don't have 2 segments, there is no intersection of the rectangles.
Assuming at the previous step you found 2 segments (one in each rectangle) on the line I, you just need to find their intersection and it will be your answer (again, empty means no intersection).
I have a 2D plan with integer coordinates.
On this plan, there are many points, separated in three categories.
The "Source". There is only a single point that is the source.
The Nice Group, containing an unknown (but reasonable) number of points
The Evil Group, containing an unknown (but reasonable) number of points
What I am trying to do first of all is to figure out (yes/no) if the two groups are in separated hemispheres.
If you could draw a line through the Source (Blue in the images) so that all nice are on one side, and all evil are on the other, then they are considered in different hemispheres. If so much as one of either group can't be put on the same side as the rest, it's false.
The second step is to figure out the angle of this hemisphere. In the first example (below), I've drawn a 180 degrees angle (straight line), but I would like to calculate the most unbalanced angle (close to 0) that would allow separating the groups perfectly. The line then would be two half-lines starting at the source going to infinity. I want to know the smallest angle (so, logically, the biggest angle if you measure the other side) that keeps the first test as true
Examples:
1:
2:
3:
Right now I am able, through code, to calculate the angle between every individual point and the source. I am stuck at figuring out how to test the "togetherness" of the groups, and most importantly, the absence of a member of the other group in between.
I am working in C#, but this question is really more about the algorithm (I can't think of a working one), so I will accept any answer that solves the problem in any (readable) language, including pseudo-code or straight up text explanation.
All of the points are, in context, complex objects that include a X and a Y coordinate. The other attributes are irrelevant to the question as they are already separated in the required groups (origin is alone and there are two lists for the rest).
You can sort and scan. Let's introduce polar coordinate system with its origin at the Origin and arbitrary axis.
Compute azimuth for each point (either nice or evil)
Order points by their azimuth, e.g.
Scan the sorted collection; if you have 2 or less transistion between nice to evil or evil to nice; return true, otherwise false
E.g. (let azimuthes be in degrees)
{nice, 12}
{nice, 13}
{nice, 15}
{nice, 21} // nice to evil transition
{evil, 47}
{evil, 121}
{evil, 133} // evil to nice transition
{nice, 211}
{nice, 354}
We have two transitions, answer is true.
{nice, 12}
{nice, 13}
{nice, 15} // nice to evil transition
{evil, 121}
{evil, 349}
One transition only, answer is yes
{nice, 12}
{nice, 13} // nice to evil transition
{evil, 121} // evil to nice transition
{nice, 15} // nice to evil transition
{evil, 121} // evil to nice transition
{nice, 349}
Four transitions, points can't be separated, answer is false
get the lowest current x, and lowest current y of on group. and get the highest... then compare the other group to see of there in between. if even one of the other dots is found between points (highx,highy) and (lowx,lowy) they are intermingled. if not they are seperated...
once you know they are seperated, draw a line from you lowest(x,y) to your highest(x,y) and transform that line to your origin point giving you two 'hemispheres'
note that this will only work if they are divided by a line, not an angle.
for angles
do a and y seperate
once you have the lowest(or highest) x that the other group does not cross, then do the same for y. with these two coordinates and your origin you should be able to determine your angle.
I am trying to write an algorithm (in c#) that will stitch two or more unrelated heightmaps together so there is no visible seam between the maps. Basically I want to mimic the functionality found on this page :
http://www.bundysoft.com/wiki/doku.php?id=tutorials:l3dt:stitching_heightmaps
(You can just look at the pictures to get the gist of what I'm talking about)
I also want to be able to take a single heightmap and alter it so it can be tiled, in order to create an endless world (All of this is for use in Unity3d). However, if I can stitch multiple heightmaps together, I should be able to easily modify the algorithm to act on a single heightmap, so I am not worried about this part.
Any kind of guidance would be appreciated, as I have searched and searched for a solution without success. Just a simple nudge in the right direction would be greatly appreciated! I understand that many image manipulation techniques can be applied to heightmaps, but have been unable to find a image processing algorithm that produces the results I'm looking for. For instance, image stitching appears to only work for images that have overlapping fields of view, which is not the case with unrelated heightmaps.
Would utilizing a FFT low pass filter in some way work, or would that only be useful in generating a single tileable heightmap?
Because the algorithm is to be used in Unit3d, any c# code will have to be confined to .Net 3.5, as I believe that's the latest version Unity uses.
Thanks for any help!
Okay, seems I was on the right track with my previous attempts at solving this problem. My initial attemp at stitching the heightmaps together involved the following steps for each point on the heightmap:
1) Find the average between a point on the heightmap and its opposite point. The opposite point is simply the first point reflected across either the x axis (if stitching horizontal edges) or the z axis (for the vertical edges).
2) Find the new height for the point using the following formula:
newHeight = oldHeight + (average - oldHeight)*((maxDistance-distance)/maxDistance);
Where distance is the distance from the point on the heightmap to the nearest horizontal or vertical edge (depending on which edge you want to stitch). Any point with a distance less than maxDistance (which is an adjustable value that effects how much of the terrain is altered) is adjusted based on this formula.
That was the old formula, and while it produced really nice results for most of the terrain, it was creating noticeable lines in the areas between the region of altered heightmap points and the region of unaltered heightmap points. I realized almost immediately that this was occurring because the slope of the altered regions was too steep in comparison to the unaltered regions, thus creating a noticeable contrast between the two. Unfortunately, I went about solving this issue the wrong way, looking for solutions on how to blur or smooth the contrasting regions together to remove the line.
After very little success with smoothing techniques, I decided to try and reduce the slope of the altered region, in the hope that it would better blend with the slope of the unaltered region. I am happy to report that this has improved my stitching algorithm greatly, removing 99% of the lines reported above.
The main culprit from the old formula was this part:
(maxDistance-distance)/maxDistance
which was producing a value between 0 and 1 linearly based on the distance of the point to the nearest edge. As the distance between the heightmap points and the edge increased, the heightmap points would utilize less and less of the average (as defined above), and shift more and more towards their original values. This linear interpolation was the cause of the too step slope, but luckily I found a built in method in the Mathf class of Unity's API that allows for quadratic (I believe cubic) interpolation. This is the SmoothStep Method.
Using this method (I believe a similar method can be found in the Xna framework found here), the change in how much of the average is used in determining a heightmap value becomes very severe in middle distances, but that severity lessens exponentially the closer the distance gets to maxDistance, creating a less severe slope that better blends with the slope of the unaltered region. The new forumla looks something like this:
//Using Mathf - Unity only?
float weight = Mathf.SmoothStep(1f, 0f, distance/maxDistance);
//Using XNA
float weight = MathHelper.SmoothStep(1f, 0f, distance/maxDistance);
//If you can't use either of the two methods above
float input = distance/maxDistance;
float weight = 1f + (-1f)*(3f*(float)Math.Pow(input, 2f) - 2f*(float)Math.Pow(input, 3f));
//Then calculate the new height using this weight
newHeight = oldHeight + (average - oldHeight)*weight;
There may be even better interpolation methods that produce better stitching. I will certainly update this question if I find such a method, so anyone else looking to do heightmap stitching can find the information they need. Kudos to rincewound for being on the right track with linear interpolation!
What is done in the images you posted looks a lot like simple linear interpolation to me.
So basically: You take two images (Left, Right) and define a stitching region. For linear interpolation you could take the leftmost pixel of the left image (in the stitching region) and the rightmost pixel of the right image (also in the stitching region). Then you fill the space in between with interpolated values.
Take this example - I'm using a single line here to show the idea:
Left = [11,11,11,10,10,10,10]
Right= [01,01,01,01,02,02,02]
Lets say our overlap is 4 pixels wide:
Left = [11,11,11,10,10,10,10]
Right= [01,01,01,01,02,02,02]
^ ^ ^ ^ overlap/stitiching region.
The leftmost value of the left image would be 10
The rightmost value of the right image would be 1.
Now we interpolate linearly between 10 and 1 in 2 steps, our new stitching region looks as follows
stitch = [10, 07, 04, 01]
We end up with the following stitched line:
line = [11,11,11,10,07,04,01,02,02,02]
If you apply this to two complete images you should get a result similar to what you posted before.
Wikipedia says that dodecahedron at the origin has vertices with this coordinates(x,y,z):
(±1, ±1, ±1)
(0, ±1/φ, ±φ)
(±1/φ, ±φ, 0)
(±φ, 0, ±1/φ)
where φ is golden ratio (φ = (1 + √5) / 2 ≈ 1.618 )
Let's say that I'll have this vertexes in vertexBuffer - which will be an array of Point3D.
I need prepare indexes of triangles for indexBuffer(which is an array of int). Dodecahedron has 12 faces, each face is pentagon and I will create each face from 3 triangles this way:
first triangle: a,e,b
second triangle: b,e,d
third triangle: d,c,b
For easier polyhedron I can draw it and then mark vertices and then easily get the indexes, but in this case it's not good way, cause after this Icosahedron, which has 20 faces, is waiting for me :/
So my question is: Is there any easier way how to get indexes for this vertices according requirements specified above?
Note:
I should also mentioned, that I couldn't use openGL or DirectX. We should practise 3D graphics without this libraries.
The first set of 8 vertices defines a cube.
The 3x4 remaining points come in 6 pairs that lie outside each of the 6 faces of the cube.
Each set of six points (four vertices of the cube face and the corresponding two points further away from the origin) form a pattern that repeats six times. You can get 6 triangles from each set.
An icosahedron is actually simpler: it has only 20 triangles instead of 36. It has a similar pattern, which you can see on its Wikipedia page.
I have to be able to set a random location for a waypoint for a flight sim. The maths challenge is straightforward:
"To find a single random location within a quadrangle, where there's an equal chance of the point being at any location."
Visually like this:
An example ABCD quadrangle is:
A:[21417.78 37105.97]
B:[38197.32 24009.74]
C:[1364.19 2455.54]
D:[1227.77 37378.81]
Thanks in advance for any help you can provide. :-)
EDIT
Thanks all for your replies. I'll be taking a look at this at the weekend and will award the accepted answer then. BTW I should have mentioned that the quadrangle can be CONVEX OR CONCAVE. Sry 'bout dat.
Split your quadrangle into two triangles and then use this excellent SO answer to quickly find a random point in one of them.
Update:
Borrowing this great link from Akusete on picking a random point in a triangle.
(from MathWorld - A Wolfram Web Resource: wolfram.com)
Given a triangle with one vertex at
the origin and the others at positions v1
and v2, pick
(from MathWorld - A Wolfram Web Resource: wolfram.com)
where A1
and A2 are uniform
variates in the interval [0,1] , which gives
points uniformly distributed in a
quadrilateral (left figure). The
points not in the triangle interior
can then either be discarded, or
transformed into the corresponding
point inside the triangle (right
figure).
I believe there are two suitable ways to solve this problem.
The first mentioned by other posters is to find the smallest bounding box that encloses the rectangle, then generate points in that box until you find a point which lies inside the rectangle.
Find Bounding box (x,y,width, height)
Pick Random Point x1,y1 with ranges [x to x+width] and [y to y+height]
while (x1 or y1 is no inside the quadrangle){
Select new x1,y1
}
Assuming your quadrangle area is Q and the bounding box is A, the probability that you would need to generate N pairs of points is 1-(Q/A)^N, which approaches 0 inverse exponentially.
I would reccommend the above approach, espesially in two dimensions. It is very fast to generate the points and test.
If you wanted a gaurentee of termination, then you can create an algorithm to only generate points within the quadrangle (easy) but you must ensure the probablity distribution of the points are even thoughout the quadrangle.
http://mathworld.wolfram.com/TrianglePointPicking.html
Gives a very good explination
The "brute force" approach is simply to loop through until you have a valid coordinate. In pseudocode:
left = min(pa.x, pb.x, pc.x, pd.x)
right = max(pa.x, pb.x, pc.x, pd.x)
bottom = min(pa.y, pb.y, pc.y, pd.y)
top = max(pa.y, pb.y, pc.y, pd.y)
do {
x = left + fmod(rand, right-left)
y = bottom + fmod(rand, top-bottom)
} while (!isin(x, y, pa, pb, pc, pd));
You can use a stock function pulled from the net for "isin". I realize that this isn't the fastest-executing thing in the world, but I think it'll work.
So, this time tackling how to figure out if a point is within the quad:
The four edges can be expressed as lines in y = mx + b form. Check if the point is above or below each of the four lines, and taken together you can figure out if it's inside or outside.
Are you allowed to just repeatedly try anywhere within the rectangle which bounds the quadrangle, until you get something within the quad? Might this even be faster than some fancy algorithm to ensure that you pick something within the quad?
Incidentally, in that problem statement, I think the use of the word "find" is confusing. You can't really find a random value that satisfies a condition; the randomizer just gives it to you. What you're trying to do is set parameters on the randomizer to give you values matching certain criteria.
I would divide your quadrangle into multiple figures, where each figure is a regular polygon with one side (or both sides) parallel to one of the axes. For eg, for the figure above, I would first find the maximum rectangle that fits inside the quadrangle, the rectangle has to be parallel to the X/Y axes. Then in the remaining area, I would fit triangles, such triangles will be adjacent to each side of the rectangle.
then it is simple to write a function:
1) get a figure at random.
2) find a random point in the figure.
If the figure chosen in #1 is a rectangle, it should be pretty easy to find a random point in it. The tricky part is to write a routine which can find a random point inside the triangle
You may randomly create points in a bound-in-box only stopping after you find one that it's inside your polygon.
So:
Find the box that contains all the points of your polygon.
Create a random point inside the bounds of the previously box found. Use random functions to generate x and y values.
Check if that point is inside the polygon (See how here or here)
If that point is inside the polygon stop, you're done, if not go to step 2
So, it depends on how you want your distribution.
If you want the points randomly sampled in your 2d view space, then Jacob's answer is great. If you want the points to be sort of like a perspective view (in your example image, more density in top right than bottom left), then you can use bilinear interpolation.
Bilinear interpolation is pretty easy. Generate two random numbers s and t in the range [0..1]. Then if your input points are p0,p1,p2,p3 the bilinear interpolation is:
bilerp(s,t) = t*(s*p3+(1-s)*p2) + (1-t)*(s*p1+(1-s)*p0)
The main difference is whether you want your distribution to be uniform in your 2d space (Jacob's method) or uniform in parameter space.
This is an interesting problem and there's probably as really interesting answer, but in case you just want it to work, let me offer you something simple.
Here's the algorithm:
Pick a random point that is within the rectangle that bounds the quadrangle.
If it is not within the quadrangle (or whatever shape), repeat.
Profit!
edit
I updated the first step to mention the bounding box, per Bart K.'s suggestion.