I read how to keep points that are between two points (ie. : that are part of a segment, with some imprecision) here : How can I tell if a point is nearby a certain line?
Thus, I implemented this little algorithm in Java, and my code is (note that the variables' name should be clear for you ! :) ) :
List<Cupple> returned = new ArrayList<>(points_to_test);
for(Cupple c : points_to_test) {
/*if(c == segment_first_point || c == segment_last_point) {
continue;
}*/
if(Math.abs(Math.abs(
(segment_last_point.getNumber(0) - segment_first_point.getNumber(0))
*
(segment_first_point.getNumber(1) - c.getNumber(1))
-
(segment_first_point.getNumber(0) - c.getNumber(0))
*
(segment_last_point.getNumber(1) - segment_first_point.getNumber(1))
)
/
Math.sqrt(
Math.pow((segment_last_point.getNumber(0) - segment_first_point.getNumber(0)), 2)
+
Math.pow((segment_last_point.getNumber(1) - segment_first_point.getNumber(1)), 2)
)
) > maximal_allowed_distance) {
returned.remove(c);
}
}
return returned;
To be sure you understand :
returned is the list with points that are on the segment, or near the segment (and the "imprecision" / maximal distance that determine if a point is out of the segment is the variable : maximal_allowed_distance)
points_to_test are ALL the points that are present in my graph : the both of my segment + the points that are really on the segment + the points that are almost on the segment (<= maximal_allowed_distance) + the points that are far from the segment (> maximal_allowed_distance). The idea of my little algorithm is that I remove all the latter.
segment_[first|last]_point are the two segment's extremities
c is the current point of points_to_test and I want to know if it is far from the segment or in (according to the maximal_allowed_distance)
getNumber(0) returns the X coordinate of the point, getNumber(1) returns the Y one.
However, it does not work. It doesn't return the good points (ie. : the points that are in the segment, taking account of maximal_allowed_distance).
Do you know if I misunderstood the answer I gave you in the first line of this question ? Do you see any mistake in my own implementation of this algorithm ?
Note, that cited method determines distance from infinite line. If you need points near limited segment only, you would modify it.
In any case algorithm should find points far from the line. If it does not do this, check
a) whether it ever finds points to remove
b) whether it is able to remove object c that belongs to points_to_test list, from returned list
Edit
There is rather effective approach to find a distance between point and line segment using vector arithmetics
// Copyright 2001 softSurfer, 2012 Dan Sunday
// This code may be freely used, distributed and modified for any purpose
// providing that this copyright notice is included with it.
// SoftSurfer makes no warranty for this code, and cannot be held
// liable for any real or imagined damage resulting from its use.
// Users of this code must verify correctness for their application.
// Assume that classes are already given for the objects:
// Point and Vector with
// coordinates {float x, y, z;} (z=0 for 2D)
// appropriate operators for:
// Point = Point ± Vector
// Vector = Point - Point
// Vector = Scalar * Vector
// Line with defining endpoints {Point P0, P1;}
// Segment with defining endpoints {Point P0, P1;}
//===================================================================
// dot product (3D) which allows vector operations in arguments
#define dot(u,v) ((u).x * (v).x + (u).y * (v).y + (u).z * (v).z)
#define norm(v) sqrt(dot(v,v)) // norm = length of vector
#define d(u,v) norm(u-v) // distance = norm of difference
// dist_Point_to_Segment(): get the distance of a point to a segment
// Input: a Point P and a Segment S (in any dimension)
// Return: the shortest distance from P to S
float
dist_Point_to_Segment( Point P, Segment S)
{
Vector v = S.P1 - S.P0;
Vector w = P - S.P0;
double c1 = dot(w,v);
if ( c1 <= 0 )
return d(P, S.P0);
double c2 = dot(v,v);
if ( c2 <= c1 )
return d(P, S.P1);
double b = c1 / c2;
Point Pb = S.P0 + b * v;
return d(P, Pb);
}
Related
I have inputs height if first coordinate, height of last coordinate, and n where n is a number of points I need to create on the edge including first and last.
I created points that are at equal distance but they form a straight line. I want to have a sinusoidal wave-like curve instead of a straight line. That means points closer to the first coordinate and last coordinates and the rest of the points are gradually increasing.
final double heightOfFirstCoordinate = 0;
final double heightOfLastCoordinate = 6;
final int n = 4;
final double step = (heightOfLastCoordinate - heightOfFirstCoordinate) / (n - 1);
final List<Double> collect = IntStream.range(0, n)
.mapToObj(i -> heightOfFirstCoordinate + step * I)
.collect(Collectors.toList());
As you can see on the screenshot what I produced is the black line but I need to produce the brown line.
I can't think of any simple algorithm to do this thing without making it much complicated.
assumed the derivative of the start and end points are exactly 0, you can use a cubic function running from 0 to 1 and returning values from 0 to 1:
double cubic(double x)
{
return 3*x*x-2*x*x*x;
}
To transform from the actual coordinates, use
y = y0+dy*cubic((x-x0)/dx);
where x0,y0 is the starting point the dy,dx are the deltas between start and end points.
I've been trying to make a code that goes through all array elements that are between two specified points, but I am stuck.
Let's suppose it's an array like that:
int[][] new_array = new int[100][100];
And how do I get all elements that are in straight line between let's say
new_array[17][2];
and
new_array[5][90];
This is what I want to achieve:
Let's imagine that your array is a first quadrant of a cartesian coordinates system. With a first column lying on axis Y and last row lying on axis X.
Having that assumption you could find a function that describes a straight line between any of two points in your array.
You need to solve the function:
y = ax + b
It's a standard linear function. You have two points, solving that you'll find your equation (values of a and b).
When you know equation you need to evaluate points in the array for each x value. Doing that you'll find all y values that are below/on/above the line.
Following #Marcin Pietraszek's answer the function can be obtained this way:
Given the two points (a,b) and (c,d) the straight line that passes through both points is given by
a + K * (x - a) = c AND b + K (y - b) = d
where K is a scalar number.
And this resolves to:
y = ( (d - b) * x - (d - b) * a + (c - a) * b ) / (c - a)
So any point (x, y) that meets this condition will be on the straight line.
You will need go through the matrix, checking one by one to see which points meet the condition.
If you want only the point inside the segment, then aditionally you need to check the boundaries.
I'm trying to calculate the perimeter of the union of a n rectangles, of which I have the bottom left and top right points. Every rectangle sits on the x axis (bottom left corner of every rectangle is (x, 0)). I've been looking into different ways of doing this and it seems like the Sweep-Line algorithm is the best approach. I've looked at Graham Scan as well. I'm aiming for an O(n log n) algorithm. Honestly though I am lost in how to proceed, and I'm hoping someone here can do their best to dumb it down for me and try to help me understand exactly how to accomplish this.
Some things I've gathered from the research I've done:
We'll need to sort the points (I'm not sure the criteria in which we are sorting them).
We will be dividing and conquering something (to achieve the O (log n)).
We'll need to calculate intersections (What's the best way to do this?)
We'll need some sort of data structure to hold the points (Binary tree perhaps?)
I'll ultimately be implementing this algorithm in Java.
The algorithm is a lot of fiddly case analysis. Not super complicated, but difficult to get completely correct.
Say all the rectangles are stored in an array A by lower left and upper right corner (x0, y0, x1, y1). So we can represent any edge of a rectangle as a pair (e, i) where e \in {L, R, T, B} for left, right, top, and bottom edge and i denotes A[i]. Put all pairs (L, i) in a start list S and sort it on A[i].x0.
We'll also need a scan line C, which is a BST of triples (T, i, d) for top edges and (B, i, d) for bottom. Here i is a rectangle index, and d is an integer depth, described below. The key for the BST is the edges' y coordinates. Initially it's empty.
Note that at any time you can traverse C in order and determine which portions of the sweep line are hidden by a rectangle and not. Do this by keeping a depth counter, initially zero. From least y to greatest, when you encounter a bottom edge, add 1 to the counter. When you see a top edge, decrement 1. For regions where the counter is zero, the scan line is visible. Else it's hidden by a rectangle.
Now you never actually do that entire traversal. Rather you can be efficient by maintaining the depths incrementally. The d element of each triple in C is the depth of the region above it. (The region below the first edge in C is always of depth 0.)
Finally we need an output register P. It stores a set of polylines (doubly linked lists of edges are convenient for this) and allows queries of the form "Give me all the polylines whose ends' y coordinates fall in the range [y0..y1]. It's a property of the algorithm that these polylines always have two horizontal edges crossing the scan line as their ends, and all other edges are left of the scan line. Also, no two polylines intersect. They're segments of the output polygon "under construction." Note the output polygon may be non-simple, consisting of multiple "loops" and "holes." Another BST will do for P. It is also initially empty.
Now the algorithm looks roughly like this. I'm not going to steal all the fun of figuring out the details.
while there are still edges in S
Let V = leftmost vertical edge taken from S
Determine Vv, the intersection of V with the visible parts of C
if V is of the form (L, i) // a left edge
Update P with Vv (polylines may be added or joined)
add (R, i) to S
add (T, i) and (B, i) to C, incrementing depths as needed
else // V is of the form (R, i) // a right edge
Update P with Vv (polylines may be removed or joined)
remove (T, i) and (B, i) from C, decrementing depths as needed
As P is updated, you'll generate the complex polygon. The rightmost edge should close the last loop.
Finally, be aware that coincident edges can create some tricky special cases. When you run into those, post again, and we can discuss.
The run time for the sort is of course O(n log n), but the cost of updating the scan line depends on how many polygons can overlap: O(n) for degenerate cases or O(n^2) for the whole computation.
Good luck. I've implemented this algorithm (years ago) and a few others similar. They're tremendous exercises in rigorous logical case analysis. Extremely frustrating, but also rewarding when you win through.
The trick is to first find the max height at every segment along the x axis (see the picture above). Once you know this, then the perimeter is easy:
NOTE: I haven't tested the code so there might be typos.
// Calculate perimeter given the maxY at each line segment.
double calcPerimeter(List<Double> X, List<Double> maxY) {
double perimeter = 0;
for(int i = 1; i < X.size(); i++){
// Add the left side of the rect, maxY[0] == 0
perimeter += Math.abs(maxY.get(i) - maxY.get(i - 1))
// add the top of the rect
perimeter += X.get(i) - X.get(i-1);
}
// Add the right side and return total perimeter
return perimeter + maxY.get(maxY.size() - 1);
}
Putting it all together, you will need to first calculate X and maxY. The full code will look something like this:
double calcUnionPerimeter(Set<Rect> rects){
// list of x points, with reference to Rect
List<Entry<Double, Rect>> orderedList = new ArrayList<>();
// create list of all x points
for(Rect rect : rects){
orderedList.add(new Entry(rect.getX(), rect));
orderedList.add(new Entry(rect.getX() + rect.getW(), rect));
}
// sort list by x points
Collections.sort(orderedList, new Comparator<Entry<Double,Rect>>(){
#Override int compare(Entry<Double, Rect> p1, Entry<Double, Rect> p2) {
return Double.compare(p1.getKey(), p2.getKey());
}
});
// Max PriorityQueue based on Rect height
Queue<Rect> maxQ = new PriorityQueue<>(orderedList, new Comparator<Rect>(){
#Override int compare(Rect r1, Rect r2) {
return Double.compare(r1.getH(), r2.getH());
}
}
List<Double> X = new ArrayList<>();
List<Double> maxY = new ArrayList<>();
// loop through list, building up X and maxY
for(Entry<Double, Rect> e : orderedList) {
double x = e.getKey();
double rect = e.getValue();
double isRightEdge = x.equals(rect.getX() + rect.getW());
X.add(x);
maxY.add(maxQ.isEmpty() ? 0 : maxQ.peek().getY());
if(isRightEdge){
maxQ.dequeue(rect); // remove rect from queue
} else {
maxQ.enqueue(rect); // add rect to queue
}
}
return calcPerimeter(X, maxY);
}
I'm given a line segment with two endpoints: (x1,y1) (x2,y2) and a random point: (x3,y3).
If I convert the line segment to polar coordinates, I need to be able to figure out, programmatically, a point on the line segment that is the closest to point (x3,y3).
EDIT:
I made a mistake in my question. The problem isn't trying to find the closest point between the three. The problem is... given a line AB with a start and an end... find ANY point on the line that is closest to point (x3,y3).
I guess this is too late, just in case someone needs it, I just convert back to cartesian coordinates so the formula is easier to look at:
public static double distance(double r1,double t1,double r2,double t2,double r3,double t3)
{
double x1 = (r1*Math.cos(t1));
double x2 = (r1*Math.cos(t2));
double x3 = (r1*Math.cos(t3));
double y1 = (r1*Math.sin(t1));
double y2 = (r1*Math.sin(t2));
double y3 = (r1*Math.sin(t3));
return Math.abs((x2-x1)*(y1-y3)-(x1-x3)*(y2-y1))/Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}
This question involves elementary school level algebra:
There are only 3 options for the closest point:
one of the points (x1,y1) (x2,y2)
another point between them on the line segment
It's easy to find the distance between (x3,y3) to the two points using Pythagoras:
d1 = d(<x1,y1>,<x3,y3>) = sqrt( (x1-x3)^2 + (y1-y3)^2)
and
d2 = d(<x2,y2>,<x3,y3>) = sqrt( (x2-x3)^2 + (y2-y3)^2)
and now for the "more complicated" part: if there's another point on the segment which is closer to (x3,y3) - if we connect these points - we'll have a new segment that will be diagonal to the original segment - we have to use that together with a first degree equation (for a line) to find that third point and see if it's on the segment or outside (if it's outside of the segment then we'll take the minimum distance between (x3,y3) to the other two points.
The line equation (excuse my English - I learnt it in my native language so bear with me) is:
(I) y = mx + d
where m is easy to calculate:
m = (y1-y2)/(x1-x2)
and now that we know the value of m in order to find d we'll use the values of one of the first two points, for example:
y1 = mx1 +d => d = y1 - mx1
the diagonal line will have m' which is -1/m and if we'll use the values of (x3,y3) we'll find d'. So now we know both the values of (I) as well as the equation for the diagonal line:
(II) y=m'x + d'
and if we'll use these two equations we can find the point on the line through which the original segment goes through which is the closest to (x3,y3) - if this point lies on the segment - we're done, otherwise, like earlier mentioned - we'll take the minimum between d1 and d2
public static Location closest(double x1, double y1, double x2, double y2, double x3, double y3){
Location a = new Location("provider");
Location b = new Location("provider");
Location c = new Location("provider");
//I can't remember which one goes where, you may need to swap all the x/ys around
//Do conversion or something here.
a.setLongitude(x1);
a.setLatitude(y1);
b.setLongitude(x2);
b.setLatitude(y2);
c.setLongitude(x3);
c.setLongitude(y3);
return closest(a, b, c);
}
public static Location closest(Location a, Location b, Location c){
return a.distanceTo(c) < b.distanceTo(c) ? a : b;
}
http://introcs.cs.princeton.edu/java/13flow/Sqrt.java.html:
public class Sqrt {
public static void main(String[] args) {
// read in the command-line argument
double c = Double.parseDouble(args[0]);
double epsilon = 1e-15; // relative error tolerance
double t = c; // estimate of the square root of c
// repeatedly apply Newton update step until desired precision is achieved
while (Math.abs(t - c/t) > epsilon*t) {
t = (c/t + t) / 2.0;
}
// print out the estimate of the square root of c
System.out.println(t);
}
}
The thing is..I understand perfectly well how the program works itself. The problem I have is with the equation f(x) = x^2 - c and how that relates to the code above. Like, why divide it by x so that x(x - c/x)? There seems to be a missing mathematical explanation when it comes to some of these examples. In other words, I'm looking for an explanation from a simple mathematical stand point, NOT coding as so much.
You are given c and you want to solve
t = sqrt(c)
or equivalently,
c = t^2
or then again,
c - t^2 = 0.
I'll call the above equation f(t) = 0 (no mention of c since it is a given constant).
Newton method iterates over trial values of t, which I'll label t_i, t_{i+1}, ....
The Taylor expansion to 1st order is:
f(t_i + dt_i) = f(t_i) + dt_i * f'(t_i) + ...
So if you don't quite have f(t_i) = 0, you add a dt_i such that
f(t_i + dt_i) nearly = 0 = f(t_i) + dt_i * f'(t_i) + ...
So dt_i = -f(t_i) / f'(t_i), i.e. f(t_i + -f(t_i) / f'(t_i)) is closer to zero than f(t_i).
If you do the derivatives for f(t) = c - t^2, you'll see that the equation in the code t_{i+1} = (c / t_i + t_i) / 2 is just the iterative formula t_{i+1} = t_i + dt_i with the dt_i estimated above.
This is iterative method, so it does not give an exact solution. You need to decide when you want to stop (sufficient precision), otherwise the algorithm would go on forever. That's why you check f(t_i) < threshold instead of the true f(t_i) = 0. In their case they chose a threshold = epsilon * t^2; I think the multiplication by t^2 was used because if you used a fixed constant as a threshold, you might run into numerical accuracy problems (i.e. if you are playing with trillions, you could never get an fixed accuracy of 10^{-10} due to the finite precision of floating point representation.)
Based on the code, the following has already been explained on the Javadoc Comment:
* Computes the square root of a nonnegative number c using
* Newton's method:
* - initialize t = c
* - replace t with the average of c/t and t
* - repeat until desired accuracy reached
Ok, I'll give it a bash (see inline comments):
public class Sqrt {
public static void main(String[] args) {
// read in the command-line argument (i.e. this is the value that we want
// square root from.)
double c = Double.parseDouble(args[0]);
// Since the the square root of non-squares are irrational, we need some
// error tolerance. In other words, if the answer is less than epsilon wrong
// we'll take it.
double epsilon = 1e-15; // relative error tolerance
// t is our first guess (c / 2.0 works well too - in fact it tends to be
// better.)
double t = c; // estimate of the square root of c
// repeatedly apply Newton update step until desired precision is achieved
// The condition here is rather elegant and optimized... to see why it works,
// simply break it up. The absolute is there to cater for negative values, but
// for c >= 0:
// | c - c/t | > epsilon * t
// t * ( t - c / t ) > epsilon
// tt - c = > epsilon)
while (Math.abs(t - c/t) > epsilon*t) {
// Improve the guess by applying Newton's genius :-)
// Take the original number, divide by the guess add t and take the
// average.
t = ( c / t + t) / 2.0;
}
// print out the estimate of the square root of c
System.out.println(t);
}
}
ejlab.net jelmar
I believe the above mentioned code is from R.Sedgewick's book 'Introduction to Programming in Java', page 62. What he tries to say in the book is that you can use f(x)=x^2-c as a special case to find the square root of any positive number. So how it works:
Newton's method states X(n+1)=X(n)-(F(X(n))/F'(X(n))). Assume that in F(X)=X^2-C, where C=2 since we are looking for square root of 2 (if you want to find square root of 36 then C=36 etc). Then the first derivative of the function F(X) is F'(X)=2X. Applying the Newton's method we get
X(n+1)=X(n)-((X^2-C)/(2X))
for X(0)=2 we get
n=1, X(1)=2-(2^2-2)/(2*2) > X(1)=1.5;
n=2 X(2)=1.5 -(1.5^2-2)/(2*1.5) > X(2)=1.41666667
and so on...