I am creating vertex array for a mesh with given points.So far I was able to create a continuous mesh with thickness.However there is a problem at the intersection of two line segments, the vectors between those segment's sizes needs to be bigger or smaller depending on the situation in order to have a continuous look.
What I have now:
With the given angles theta1 and theta2, how can I calculate the length of red vectors?
What I want:
How I structured my mesh:
You're probably making it more complicated than it needs to be.
Let's start by calculating the red arrows. For any line segment (p_i, p_j), we can calculate the segment's normal with:
dir = normalize(p_j - p_i)
normal = (-dir.y, dir.x) //negate if you want the other direction
At the connection point between two segments, we can just average (and re-normalize) the incident normals. This gives us the red arrows.
The only question that remains is how much you need to shift. The resulting offset for the line segment o_l given an offset of the vertex o_v is:
o_l = o_v * dot(normal_l, normal_v)
This means the following: Both normals are unit vectors. Hence, their dot product is at most one. This is the case when both line segments are parallel. Then, the entire offset of the vertex is transferred to the line. The smaller the angle becomes, the smaller becomes the transferred offset. E.g. if the angle between two consecutive line segments is 120°, then the dot product of normals is 0.5. If you shift the vertex by 1 unit along its normal, both line segment will have a thickness of 0.5.
So, in order to produce a specific line thickness (o_l), we need to shift the vertex by o_v:
o_v = o_l / dot(normal_l, normal_v)
The construction with averaging the line segments' normal for the vertex normal ensures that dot(normal_l1, normal_ v) = dot(normal_l2, normal_v), i.e. the resulting line thickness is equal for both lines in any case.
Related
I'm trying to split a generic Shape into list of Points so we can move a certain sprite along the path depending on a certain percentage.
Right now I can split the shape into multiple points:
This was produced by the following code:
shapeComp = system.gui.getParentWindow(event).getComponentForPath('Root Container.Path')
shape=shapeComp.getShape()
pathIterator = FlatteningPathIterator(shape.getPathIterator(AffineTransform()), 1)
graphics = system.gui.getParentWindow(event).graphics
segment = jarray.zeros(6,'d')
path = []
while not pathIterator.isDone():
pathIterator.currentSegment(segment)
path.append([segment[0], segment[1]])
graphics.fillOval(int(segment[0]), int(segment[1]), 5, 5)
pathIterator.next()
As you can see on the picture, the points are not evenly distributed along the path. Is there a way to make the distance between all points the same?
As you can find in the javadoc there is a additional attribute for flattness. So you should be able to just set the second argument to some specific value an get what you expect. However if this is true for all cases I don't know.
flatness - the maximum distance that the line segments used to approximate the curved segments are allowed to deviate from any point on the original curve
I need to check if two java.awt.Polygons overlap, but I don't know how.
Area area = new Area(poly1);
area.intersect(new Area(poly2));
return area.isEmpty();
From a geometry perspective, there are conditions that are fulfilled by overlapping polygons.
1) If a segment in A crosses a segment in B, the polygons overlap.
2) If all vertices in B are inside A, or vice-versa, the polygons overlap.
3) If all vertices in A are also vertices of B, the polygons overlap.
Testing for (1) is fairly simple. You just do a little algebra and brute force. If lines are parallel, they don't cross. If the lines are non-parallel, they intersect. If the point of intersection is within either segment, they cross. Maximum iterations is length of A * length of B.
Testing for (2) is a little more complex. One method to tell if a point is inside a poly is this: Pick a point that you know is outside of the poly, often a negative value for x,y works for this. Then, draw a line from the reference point to the test point. If it crosses an odd number of segments, it's inside. It if crosses an even number, or zero segments, it is outside.
Let us consider a 2-D (latitude, longitude) point set. The points in the set are equispaced (approx.) with mutual distance 0.1 degree \times 0.1 degree . Each point in the set is the centre of a square grid of side length 0.1 degree (i.e., intersect point of two diagonals of the square). Each square is adjacent to the neighbouring squares.
Our goal is to get the coordinates of the outline polygon formed by the bounding sides of the square grids with given direction (will be illustrated with a figure). This polygon has no hole inside.
Let us consider a sample data set of size 10 (point set).
lat_x <- c(21.00749, 21.02675, 21.00396, 21.04602, 21.02317,
21.06524, 21.00008, 21.04247, 21.08454, 21.0192)
and
lon_y <- c(88.21993, 88.25369, 88.31292, 88.28740, 88.34669,
88.32118, 88.40608, 88.38045, 88.35494, 88.43984)
Here is the rough plot of the above points followed by some illustration,
The black points are the (lat,lon) points in the above sample.
The blue square boxes are the square grid.
The given directions (\theta) of the squares are $theta$=50 degree.
Our goal is to get the ordered (clockwise or counter clockwise) co-ordinates of the outline polygon (in yellow colour).
Note: This question is very similar to this with a nice answer given by #laune. There the goal is to get the outline polygon without direction (or 0 degree direction). But in the the present set up I need to include the direction (non-zero) while drawing the square grids and the resulted polygon.
I would gratefully appreciate any suggestion, java or R codes or helpful reference given by anyone solving the above problem.
I would do it like this:
may be some 2D array point grouping to match the grid
that should speed up all the following operations.
compute average grid sizes (img1 from left)
as two vectors
create blue points (img2)
as: gray_point (+/-) 0.5*blue_vector
create red points (img3)
as: blue_point (+/-) 0.5*red_vector
create list of gray lines (img4)
take all 2 original (gray) points that have distance close to average grid distance and add line for them
create list of red lines (img4)
take all 2 original (gray) points that have distance close to average grid distance and add line for them if it is not intersecting any line from gray lines
reorder line points to match polygon winding ...
angle
compute angle of red vector (via atan2)
compute angle of blue vector (via atan2)
return the one with smaller absolute value
[edit1] response to comments
grid size
find few points that are closest to each other so pick any point and find all closest points to it. The possible distances should be near:
sqrt(1.0)*d,sqrt(1+1)*d,sqrt(1+2)*d,sqrt(2+2)*d,...
where d is the grid size so compute d for few picked points. Remember the first smallest d found and throw away all that are not similar to smallest one. Make average of them and let call it d
grid vectors
Take any point A and find closest point B to it with distance near d. For example +/-10% comparison: |(|A-B|-d)|<=0.1*d Now the grid vector is (B-A). Find few of them (picking different A,B) and group them by sign of x,y coordinates into 4 groups.
Then join negative direction groups together by negating one group vectors so you will have 2 list of vectors (red,blue direction) and make average vectors from them (red,blue vectors)
shifting points
You take any point A and add or substract half of red or blue vector to it (not its size!!!) for example:
A.x+=0.5*red_vector.x;
A.y+=0.5*red_vector.y;
line lists
Make 2 nested fors per each 2 point combination A,B (original for gray lines,shifted red ones for red outline lines) and add condition for distance
|(|A-B|-d)|<=0.1*d
if it is true add line (A,B) to the list. Here pseudo C++ example:
int i,j,N=?; // N is number of input points in pnt[]
double x,y,d=?,dd=d*d,de=0.1*d; // d is the avg grid size
double pnt[N][2]=?; // your 2D points
for (i=0;i<N;i++) // i - all points
for (j=i+1;j<N;j++) // j - just the rest no need to test already tested combinations
{
x=pnt[i][0]-pnt[j][0];
y=pnt[i][1]-pnt[j][1];
if (fabs((x*x)+(y*y)-dd)<=de) ... // add line pnt[i],pnt[j] to the list...
}
I have one 2d line (it can be a curved line, with loops and so on), and multiple similar paths. I want to compare the first path with the rest, and determine which one is the most similar (in percentage if possible).
I was thinking maybe transforming the paths into bitmaps and then using a library to compare the bitmaps, but that seems like overkill. In my case, I have only an uninterrupted path, made of points, and no different colors or anything.
Can anyone help me?
Edit:
So the first line is the black one. I compare all other lines to it. I want a library or algorithm that can say: the red line is 90% accurate (because it has almost the same shape, and is close to the black one); the blue line is 5% accurate - this percentage is made up for this example... - because it has a similar shape, but it's smaller and not close to the black path.
So the criterion of similarity would be:
how close the lines are one to another
what shape do they have
how big they are
(color doesn't matter)
I know it's impossible to find a library that considers all this. But the most important comparisons should be: are they the same shape and size? The distance I can calculate on my own.
I can think of two measures to express similarity between two lines N (defined as straight line segments between points p0, p1... pr)
M (with straight line segments between q0, q1, ...qs). I assume that p0 and q0 are always closer than p0 and qs.
1) Area
Use the sum of the areas enclosed between N and M, where N and M are more different as the area gets larger.
To get N and M to form a closed shape you should connect p0 and q0 and pr and qs with straight line segments.
To be able to calculate the surface of the enclosed areas, introduce new points at the intersections between segments of N and M, so that you get one or more simple polygons without holes or self-intersections. The area of such a polygon is relatively straightforward to compute (search for "polygon area calculation" around on the web), sum the areas and you have your measure of (dis)similarity.
2) Sampling
Take a predefined number (say, 1000) of sample points O that lie on N (either evenly spaced with respect to the entire line, or evenly spaced
over each line segment of N). For each sample point o in O, we'll calculate the distance to the closest corresponding point on M: the result is the sum of these distances.
Next, reverse the roles: take the sample points from M and calculate each closest corresponding point on N, and sum their distances.
Whichever of these two produces the smallest sum (they're likely not the same!) is the measure of (dis)similarity.
Note: To locate the closest corresponding point on M, locate the closest point for every straight line segment in M (which is simple algebra, google for "shortest distance between a point and a straight line segment"). Use the result from the segment that has the smallest distance to o.
Comparison
Method 1 requires several geometric primitives (point, line segment, polygon) and operations on them (such as calculating intersection points and polygon areas),
in order to implement. This is more work, but produces a more robust result and is easier to optimize for lines consisting of lots of line segments.
Method 2 requires picking a "correct" number of sample points, which can be hard if the lines have alternating parts with little detail
and parts with lots of detail (i.e. a lot of line segments close together), and its implementation is likely to quickly get (very) slow
with a large number of sample points (matching every sample point against every line segment is a quadratic operation).
On the upside, it doesn't require a lot of geometric operations and is relatively easy to implement.
I have a small contest problem in which is given a set of points, in 2D, that form a triangle. This triangle may be subject to an arbitrary rotation, may be subject to an arbitrary translation (both in the 2D plane) and may be subject to a reflection on a mirror, but its dimensions were kept unchanged.
Then, they give me a set of points in the plane, and I have to find 3 points that form my triangle after one or more of those geometric operations.
Example:
5 15
8 5
20 10
6
5 17
5 20
20 5
10 5
15 20
15 10
Output:
5 17
10 5
15 20
I bet it's supposed to apply some known algorithm, but I don't know which. The most common are: convex hull, sweep plane, triangulation, etc.
Can someone give a tip? I don't need the code, only a push, please!
A triangle is uniquely defined (ignoring rotations, flips, and translations) by the lengths of its three sides. Label the vertices of your original triangle A,B,C. You're looking
for points D,E,F such that |AB| = |DE|, |AC| = |DF|, and |BC| = |EF|. The length is given by Pythagoras' formula (but you can save a square root operation at each test by comparing
the squares of the line segment lengths...)
The given triangle is defined by three lengths. You want to find three points in the list separated by exactly those lengths.
Square the given lengths to avoid bothering with sqrt.
Find the square of the distance between every pair of points in the list and only note those that coincide with the given lengths: O(V^2), but with a low coefficient because most lengths will not match.
Now you have a sparse graph with O(V) edges. Find every cycle of size 3 in O(V) time, and prune the matches. (Not sure of the best way, but here is one way with proper big-O.)
Total complexity: O(V^2) but finding the cycles in O(V) may be the limiting factor, depending on the number of points. Spatially sorting the list of points to avoid looking at all pairs should improve the asymptotic behavior, otherwise.
This is generally done with matrix math. This Wikipedia article covers the rotation, translation, and reflection matrices. Here's another site (with pictures).
Since the transformations are just rotation, scaling and mirroring, then you can find the points that form the transformed triangle by checking the dot product of two sides of the triangle:
For the original triangle A, B, C, calculate the dot product of AB.AC, BA.BC and CA.CB
For each set of three points D, E, F, calculate dot product of DE.DF and compare against the three dot products found in 1.
This works since AB.AC = |AB| x |AC| x cos(a), and two lengths and an angle between them defines a triangle.
EDIT: Yes, Jim is right, just one dot product isn't enough, you'll need to do all three, including ED.EF and FD.FE. So in the end, there's the same number of calculations in this as there is in the square distances method.