I'm creating path tool programmaticaly and im stucked in one point.
I need to add loops to connections with acute angle. I have all data but still dont know how to determine when set CW or CCW angle direction for loop arc. Result below for fixed CW.
So if you're just trying to go for clockwise or counterclockwise, it may be easiest to think of it as just left or right. To think about it that way, suppose you have the points a, b, and c in your example above. As you have guessed, that vector with p that you have in there makes a difference; basically if you average b and c to find their mid point, that will always be left or right of a which gives you your answer. So, average b and c, and check to see if the x coordinate is bigger than a's x coordinate. Hope that makes sense.
Note that this simple model will likely break down in ways you don't want for edge cases with things like near vertical angles - I'm not sure how you've chosen to handle those but ultimately you may want a more robust model.
Related
I am looking for some information on how to "bend" an arbitrary list of points/vertices similar to the bend modifier you can find in typical 3D modelling programs.
I want to provide a list of points, a rotation focal point, and a "final angle." For my purposes, I will always be saying "points at minimum y of the set will not change, points at maximum y will be rotated at the maximum angle, everything in between is interpolated."
Example Image of starting configuration and desired result, given a 90 degree rotation:
Can anyone suggest a resource that would explain how to go about this? I'm prepared to code it (C++) but I'm wracking my brain on a concept that would make this work. It would be easy to generate the vertices, but the application I'm writing this for takes in user-created content and needs to bend it.
(Edited to add: I don't need a miracle matrix or deep equation solution... if you say something like "for each vertex, do this" that's good enough to get the green checkmark)
Thanks!
You seem to be transforming a straight line to a circular arc, preserving distances between adjacent points.
So, if the point A is the one you want to hold constant, pick another point B to be the center of that circle. (The nearer B is to A, the more severe the bending.) Now for any point C you want to transform, break the vector C-B into the component parallel to A-B (call that component R) and the component perpendicular to it (call that k). The magnitude of R will be the radius of the circle you map C to, and you can transform the magnitude of 'k' into distance along that circle:
theta = |k|/|R|
C` = B + R cos(theta) + k|R|/|k| sin(theta)
I'm trying to find an efficient algorithm that can check if a line between two vertices in a simple (edit: simple concave) polygon contains points that lie outside the domain of the polygon. The closest question I could find is this one: https://stackoverflow.com/a/36378838/12135804
But I'm not sure the answer is quite right. It might be, in which case if someone could clarify that would be great.
The basic idea is illustrated in the below picture:
Where I would like the red line to fail and the green line to succeed. I know one can't naively test the midpoint as that wont work in every case, but finding any point on the line outside the polygon's domain should disqualify it.
I appreciate any and all help!
Edit: Forgot to include cross-post link to mathematics stack exchange:
https://math.stackexchange.com/q/4040059/892519
Let's assume that the topmost point is A and the others are named B, C ... counter-clockwise, so we know what we're talking about.
If you take the red segment B-D, the one point in between is on the left. If you take the green segment D-F, the one point in between is on the right. Now, a more interesting segment would be B-E, where C is on the left while D is on the right.
In order to determine left and right, use the vector product. The length depends on the sin function, so if you get a value less than zero it's one side and more than zero is the other side.
After a lot of googling, I finally found this answer to a stackoverflow question from ~12 years ago: https://stackoverflow.com/a/693877/12135804
Assuming the edges in the polygon follow a certain order, a simple ccw test can be created using a line's starting point (p), the next ccw point in the polygon from that starting point as an inflection point (q), and the endpoint of the line (r). For the red line BD, the test would check if B,C,D is ccw (it's not). For the green line DF, test if D,E,F is ccw (it is!). This would work even if the points are non-consecutive. However, this would fail when the order of the red-green lines is reversed. For instance, if the red line became DB, the test would check D,E,B, which would pass the ccw test.
I think a more robust solution is to search for the pair of two edges in the concave polygon that share the endpoints of the line to test. For both pairs, calculate the angle between the two edges to the x-axis. Calculate the angle of the line to the x-axis as well. If the line is within the polygon, the line's angle should lie between the max and min of the polygon edges' angles for both endpoints.
Whether to test the obtuse or acute range of angles depends on some factors, I think. The red line's angle at B w.r.t. to the x axis would be in the obtuse bound between AB and BC, and the same is true at point C. Visually, it's plain to see the acute bound is what needs to be used for the max/min test at both points. If the baseline to compute the bounds from can be chosen logically, then it can be done.
Of course, this doesn't work if the line crosses outside the polygon on the way between both endpoints, but this does handle the degenerate case for a normal line-polygon intersection test. Assuming it works in every degenerate case, that is.
I won't mark this an answer because I can't prove it.
Edit: Well, I came back to thinking about this again and decided to search for questions similar to the angular bounding I posed above, and found this: https://stackoverflow.com/a/17497339/12135804
This answer satisfies not knowing the orientation of the lines! However, it assumes the minimum bound between A and B should be tested. This doesn't work for concave vertices, when AxB is < 0. In this case, a line attached to the vertex shared by lines A and B will return true if it's pointing outside the polygon, and conversely false if it's inside. I think flipping the result based on the sign of AxB should be enough to account for this, though. (a hunch that is verified in this related answer: https://stackoverflow.com/a/43384516/12135804)
Please take a look at pic1 above first.
2 points combine a line, let's call it LineAB, and we can get a normal from our eye sight direction, let's call it view-direction, vector(lineAB) X view-direction, we can get a normal named plane-normal. in the pic1, plane-normal is directed to the top (green arrow), and the plane with plane-normal cut the map into 2 parts.
As the point C is on the same direction of the plane-normal, we regard it as inside, let's return true. Point D is on the anti-direction of plane-normal, it is outside, return false.
My problem is in the pic2 as following:
Now, there are many points A,A1,A2...A5,... An, build many lines such as lineAA1, line A1A2, ... LineAn-1An (one condition is: every angle between 2 adjacent lines are equal to or more than 90 degree) and plus with view direction (the direction from our eye sight), we can get many planes PAA1, PA1P2, ... PAn-1An which also cut the map to 2 parts.
I need to check one point is inside or outside.
for example, point C is inside but point D is outside.
Regarding one plane separating the dim(3)-space isn't difficult, to consider a piecewise assembled dim(2)-plane we need to dive deeper:
The problem may be reduced to separating the dim(2)-space.
If only for the calculation of the normal the 3rd dimension is considered, then that can solved in a different way:
Let v = (a,b) be the vector of a lineAB. The normal is (b, -a) or (-b, a) respectively.
If you want to check only if a point is within a polygon, just use the ray-casting-algorithm.
When it comes to dividing the dim(2)-space into two separate spaced by your polygonal chain, it won't be enough to check if the point is on the positive directon of the normals on each part line(A[i-1])(A[i]):
Polygonal chain
Point P is positive with respect to normal N0, but negative w.r.t. normal N1.
Also, the upper angles are all above 90° (some counter angles are also displayed), but the polygon chain isn't convex either w.r.t. the upward y-axis.
To solve your issue, you can use the ray-casting-algorithm, going towards negative y-direction, i.e. "downwards", and see if the amount of intersections is odd.
If the line ends at a higher x-coordinate than the start point, an odd amount of intersections means "true"
If the line ends at a lower x-coordinate than the start point, an odd amount of intersections means "false"
You can find if a ray from point C (with view direction) intersects with one of the segments AiAi+1. It could be done with binary search by X-coordinate (to find potential segment quickly)
Given is a Cartesian coordiante system, a from-position A (X/Y), and a to-position B (X/Y). I want to move from A to B. However, I can only move on the eight directions N, NE, E, SE, S, SW, W, NW.
I know that I can calculate the "best" of these directions to take from the current position A via the dot product with the unit vectors of the axis (the eight directions), where the biggest dot product is the direction to take. But this approach leads to some kind of "oscillation" between two directions, if A is exactly in between these two.
So I am searching for an algorithm now that sovles this problem of getting from A to B with only one or max. two directions to use. Of course I am ignoring any obstalces now, so that theoretically I can always get from A to B with a maximum of two different directions. I could probably solve this problem with a bunch of if-statements, but I would prefer a more elegant solution...
I hope that was somewhat understandable :)
Thanks in advance for any ideas!
Kind regards, Matthias
the simplest solution is to head in a "diagonal" direction until you are on the same row/column as the target, and then to use the horizontal/vertical direction.
in other words:
check if you are horizontally / vertically aligned. if so, move in that direction and finish.
otherwise, find the closest diagonal direction using the method you have.
move along the diagonal until you are horizontally or vertically aligned. then move in that direction and finish.
For the case of two segments maximum, this seems relatively easy:
Project a line from A -> B and then from B -> A. Pick the cardinal closest to this line rounding in either a clockwise or counterclockwise direction. Be consistent. (Once the angle is determined from A -> B, it's likely best to just add Pi to minimize very odd edge-cases with math... not sure if it can actually occur.)
Re-project lines from A -> B and B -> A along the selected cardinal direction.
If the lines are parallel (requires movement in exactly one cardinal direction and can thus also be considered a termination in step #1) there is one segment A -> B.
If the lines are not parallel find the intersection of the lines, point C.
Then there are two segments A -> C and C -> B.
I think a smarter solution would give weights to each turn (relative to distance) -- then by configuring the weights the number of turns allowed could be increased or decreased.
Not sure if this made/makes sense, but happy coding!
You can start by computing the actual number of steps between any given point and your destination; this will probably be something like "taxicab geometry" but more complicated. If all 8 steps are the same "real"(i.e., Euclidean) distance, your step count should be something like:
dist(dx,dy) = |dx|+|dy| + sqrt(0.5)(|dx+dy|+|dx-dy|)
Then, in general, there will be two possible steps that have the same, smallest, distance-to-destination. You can then choose the direction which is the same as the last one (where possible).
Actually, if you do the math as shown above, you will probably encounter problems with floating point precision. You should still be able to make a robust decision, though, by giving a small "discount" (say 1% of a step) to the preferred direction.
It sounds like your problem stems from re-evaluating optimal route along the way. This will lead to ongoing switches between, for example, N and NE, then N, then NE, etc. This is the optimal route based on distance, but you want optimal route based on direction changes.
The resolution to this is to either
pre-plan the route, rather than re-evaluate along the way, and stick to the plan
compute a number of direction changes allowed / minimum number to take, and re-evaluate only when the target can be reached within that minimum number.
To explain my second suggestion, you should know that (without obstacles) any point can be reached in two 'moves'. Initial movement is a first move, and while travelling along that path only one more direction change is allowed. You algorithm would need to allow for this 'one more' - any possible route towards the goal should not be taken unless it can be reached within the remaining number of moves.
It appears that you algorithm is focused on minimum distance rather than minimum moves - or is it some combination of the two?
I am making a graphics application in which I can edit a polyline by dragging the control point of it.
However, I'd like to make it a bit easier to use by making it elastic; When dragging a control point, instead of moving a single point, I'd like the points within a certain distance of that point to be moved as well, depending on how hard the control point is 'pulled'.
Does anyone know a simple algorithm for this? It may be quite rudimentary, as the primary requirement is speed.
Actually, knowing how to call such behaviour would also be nice, so I can look it up on google. I tried 'snaking' line, but that seems to refer to active contours, which isn't what I'm looking for.
Thanks
At a simple level you could achieve this with a little help form Hooke's law. You can basically view your polyline as a string, made up of a load of vertices connected by springs:
o-o-o-o-o-o-o-o-o
Each vertex is connected to another vertex by a spring, which will contract if stretched and repel if squashed.
So, when a control point is moved, the connected springs will either expand (stretch) or contract (shrink). This, in turn applies a force to any vertex sharing that spring. So if I pulled the first vertex up and left, the spring would apply a force to the vertex to the right, drawing it closer. This continues to the next (with some energy dissipating) until all springs are 'comfortable'.
That's the basics of it, each time a control point moves you need to solve the equation to all vertices/springs and the points will 'snake' for you.
If you want further examples google for 'Rope Physics' or 'Cloth physics' (as a rope is a 1D cloth). Ignore gravity for your purposes though, obviously.
Basically you are looking for a method to move (deform/transform) multiple points.
Let's assume you have given the direction and strength of the move which would result in dx, dy for the point x, y.
Your transformation will at least two more parameters
The radius r in which the points will be affected
Since the points in the middle would be affected more and at the edge you should define how to interpolate the falloff (linear, normal distribution, etc...)
For linear interpolations the points that are affected would move according to the following formula:
r[i] = sqrt(sqr(x-x[i])+sqr(y-y[i]))
so if r[i] < r
x[i]' = x[i] + dx*(1-r[i]/r)
y[i]' = y[i] + dy*(1-r[i]/r)
this is for linear interpolation dx[i] = dx - r[i]/r