I'm working on a problem out of Cracking The Coding Interview that asks: Given a 2-D graph with points on it, find a line which passes the most number of points.
The solution is to: Draw an infinite line between every two points and, using a hash table, track which line is most common. To find the most common line, we iterate through all line segments using a hash table to count the number of times we've seen each line.
The author goes on to say there's a complication: "we're definining two lines to be equal if the lines have the same slope and y-intercept. We are then, furthermore, hashing the lines based on these values (specifically based on the slope). The problem with floating point numbers cannot always be represented accurately in binary. We resolve this by checking if two floating point numbers are within an epsilon value of each other."
Here's where I'm confused. Even if the slope is a floating point, we can't use that as a hash key? If so, why not just hash the slope as a string instead? Why do we need to introduce into our code hashing based upon keys that are within epsilon of each other?
Have a look at the following example written in c++.
#include <stdio.h>
#include <stdlib.h>
int main() {
double a=10.0;
double b=a/3;
double c=(b-3)*3;
printf("a: %20.50lf\n", a);
printf("b: %20.50lf\n", b);
printf("c: %20.50lf\n", c);
return 0;
}
'c' should be equal to 1 but due to floating point rounding the above code produces the following.
a: 10.00000000000000000000000000000000000000000000000000
b: 3.33333333333333348136306995002087205648422241210938
c: 1.00000000000000044408920985006261616945266723632812
The algorithm you are describing does not need any hash table.
Use histogram instead. This Answer is exact example of this task in C++
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line
If you still want to use floats as keys
Then you need to truncate them so they can be compared as binary. For example let assume you got (assuming C++ syntax):
const float da=1.5*M_PI/180.0; // [rad] comparison precision
float a;
a=atan2(dy,dx); // [rad] your line angle from deltas
a=floor(a/da); // [da] truncated angle
Where dx,dy is your line delta and da is your comparison precision angle. Now to access float a as binary for hashing purposes you can simply do this:
union { float f32; DWORD u32; } b;
b.f32=a;
// here b.u32 is your hash key
Related
std::vector<int> v(6);
how to declare a two dimensional vector with limits like above code for one dimension
I'm a noob in c++. I tried like this:
`
std::vector<int> v(6)(2);
`
I expected a two dimensional vector with 6 rows and 2 columns to take input in.
I know how to declare 2d vector. I just wanted it with limit.
In C++, there's no direct type which exactly represents a 2D "vector"/"matrix"/"tensor".
What you can create, is a vector of vectors. You'd write that as std::vector<std::vector<int>> - each element of the outer vector is itself a vector. But there's an important difference here: each of the inner vectors has its own length, and those could be different.
vector has a constructor taking a second argument, the initial value. You can use that here to initialize the inner vectors:
std::vector<std::vector<int>> v(6, std::vector<int>(2));
Assume we have a 3D grid that spans some 3D space. This grid is made out of cubes, the cubes need not have integer length, they can have any possible floating point length.
Our goal is, given a point and a direction, to check linearly each cube in our path once and exactly once.
So if this was just a regular 3D array and the direction is say in the X direction, starting at position (1,2,0) the algorithm would be:
for(i in number of cubes)
{
grid[1+i][2][0]
}
But of course the origin and the direction are arbitrary and floating point numbers, so it's not as easy as iterating through only one dimension of a 3D array. And the fact the side lengths of the cubes are also arbitrary floats makes it slightly harder as well.
Assume that your cube side lengths are s = (sx, sy, sz), your ray direction is d = (dx, dy, dz), and your starting point is p = (px, py, pz). Then, the ray that you want to traverse is r(t) = p + t * d, where t is an arbitrary positive number.
Let's focus on a single dimension. If you are currently at the lower boundary of a cube, then the step length dt that you need to make on your ray in order to get to the upper boundary of the cube is: dt = s / d. And we can calculate this step length for each of the three dimensions, i.e. dt is also a 3D vector.
Now, the idea is as follows: Find the cell where the ray's starting point lies in and find the parameter values t where the first intersection with the grid occurs per dimension. Then, you can incrementally find the parameter values where you switch from one cube to the next for each dimension. Sort the changes by the respective t value and just iterate.
Some more details:
cell = floor(p - gridLowerBound) / s <-- the / is component-wise division
I will only cover the case where the direction is positive. There are some minor changes if you go in the negative direction but I am sure that you can do these.
Find the first intersections per dimension (nextIntersection is a 3D vector):
nextIntersection = ((cell + (1, 1, 1)) * s - p) / d
And calculate the step length:
dt = s / d
Now, just iterate:
if(nextIntersection.x < nextIntersection.y && nextIntersection.x < nextIntersection.z)
cell.x++
nextIntersection.x += dt.x
else if(nextIntersection.y < nextIntersection.z)
cell.y++
nextIntersection.y += dt.y
else
cell.z++
nextIntersection.z += dt.z
end if
if cell is outside of grid
terminate
I have omitted the case where two or three cells are changed at the same time. The above code will only change one at a time. If you need this, feel free to adapt the code accordingly.
Well if you are working with floats, you can make the equation for the line in direction specifiedd. Which is parameterized by t. Because in between any two floats there is a finite number of points, you can simply check each of these points which cube they are in easily cause you have point (x,y,z) whose components should be in, a respective interval defining a cube.
The issue gets a little bit harder if you consider intervals that are, dense.
The key here is even with floats this is a discrete problem of searching. The fact that the equation of a line between any two points is a discrete set of points means you merely need to check them all to the cube intervals. What's better is there is a symmetry (a line) allowing you to enumerate each point easily with arithmetic expression, one after another for checking.
Also perhaps consider integer case first as it is same but slightly simpler in determining the discrete points as it is a line in Z_2^8?
I have set P of point (3D) which are vertices of convex hull (every one). I looking for method for checking if given point p0 is NOT outside of this convex hull.
I'll have to repeat the checking it several times (for different p0). So if is possible to reuse part of computation it would be great.
On stackoverflow pages i found this:
Find if a point is inside a convex hull for a set of points without computing the hull itself
There are 2 aproche:
First based on convex hull property - set of linear equations.
Secound based on observation: "The point lies outside of the convex hull of the other points if and only if the direction of all the vectors from it to those other points are on less than one half of a circle/sphere/hypersphere around it."
Unfortunately I don't know how exactly can do it.
First give me insoluble system of equations - 3 equation with n unknown (n>3). How can I sovle it? Did I do some mistake?
In second approach I don't know how check this assumption.
CGAL can easily do this test. Not only you could build the convex hull with CGAL, but you can quickly and easily determine whether a specific point is inside, on the surface or outside of the polyhedron.
A code snippet is shown below:
#include <CGAL/Simple_cartesian.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
#include <CGAL/AABB_face_graph_triangle_primitive.h>
#include <CGAL/algorithm.h>
#include <CGAL/Side_of_triangle_mesh.h>
typedef CGAL::Simple_cartesian<double> K;
typedef K::Point_3 Point;
typedef CGAL::Polyhedron_3<K> Polyhedron;
typedef CGAL::AABB_face_graph_triangle_primitive<Polyhedron> Primitive;
typedef CGAL::AABB_traits<K, Primitive> Traits;
typedef CGAL::AABB_tree<Traits> Tree;
typedef CGAL::Side_of_triangle_mesh<Polyhedron, K> Point_inside;
bool pointInside(Polyhedron &polyhedron, Point &query) {
// Construct AABB tree with a KdTree
Tree tree(faces(polyhedron).first, faces(polyhedron).second, polyhedron);
tree.accelerate_distance_queries();
// Initialize the point-in-polyhedron tester
Point_inside inside_tester(tree);
// Determine the side and return true if inside!
return inside_tester(query) == CGAL::ON_BOUNDED_SIDE;
}
Assuming P is large and there are many p0, you should compute a 3D triangulation in which to do point location. This is a CGAL demo.
You can write down the points in the hull as columns in a matrix and then have a vector which tells you what combination of points to take:
(X1 X2) (a) (X1a + X2b)
(Y1 Y2) (b) = (Y1a + Y2b)
(Z1 Z2) (Z1a + Z2b)
To generate your target point you want to find a vector that solves this, subject to the constraints that the elements of the vector are between 0 and 1, and that the elements of the vector add up to 1. You can solve this sort of problem - if there is a solution - via linear programming, which might involve using the http://en.wikipedia.org/wiki/Simplex_algorithm.
There are a variety of tricks to get this into the strict form. Adding another row to the matrix will allow you to say a + b = 1. To force b <= 1 you could have b + q = 1 and q >= 0, although as pointed out by Ted Hopp below, in this case b <= 1 because a + b = 1, and both a and b are >= 0.
Generate a random point within a rectangle (uniformly)
This suppose to be a simple problem.
However, in RANDOM_DATA homepage I found the following note:
However, we will not achieve uniform distribution in the simple case
of a rectangle of nonequal sides [0,A] x [0,B], if we naively scale
the random values (u1,u2) to (A*u1,B*u2). In that case, the expected
point density of a wide, short region will differ from that of a
narrow tall region. The absence of uniformity is most obvious if the
points are plotted.
I found it quite of strange... I can't figure out why such scaling will affect the uniformity.
What am I missing?
Edit:
Thank you Patrick87 and missingno. I was searching for a theoretical reason for the statement. I now understand that the reason is not theoretical, but practical - the granularity of floating-point values.
If I'll generate two uniform floating-points between 0 and 1 (which is an issue by itself due to the nature of floating-point value representation. Look here for an algorithm) - the granularity will be limited.
Suppose that there are X different values between 0 and 1. By scaling (u1,u2) to (u1,2*u2) we'll have X different values in the range [0,u1] and X different values in the range [0,2*u2]. For area uniformity we should have twice as many different values in [0,2*u2] than in [0,u1].
Given that, Allow me to change my question:
How should I generate a random point within a rectangle (with uniform distribution by area)?
That statement is incorrect, direct product of two independent uniform measures is a uniform measure. This can be shown as follows:
A probability for a random point to hit a rectangle with sides a and b is equal to probability for the first coordinate to hit the segment with the length a and the second coordinate to hit the segment with the length b. (We are talking about projections of a rectangle to axes).
First probability is a / A, the second one is b / B.
As these variables are independent, the probabilities multiply, so the resulting probability is ab / AB, so we have a uniform 2D distribution as the probability is proportional to the area of the rectangle. This formula is symmetric with respect to a and b, so the observation in the quote is wrong about narrow and wide rectangles.
How should I generate a random point within a rectangle (with uniform distribution by area)?
This should work:
// given A, B, dimensions of rectangle
// given g, granularity of shorter side
if A > B then
bm := g
am := floor(g * A / B)
else then
am := g
bm := floor(g * B / A)
for i := 1 to n do
av := A * RandomInt(0..am) / am
bv := B * RandomInt(0..bm) / bm
print (av, bb)
EDIT: A simpler alternative would be to simply scale random floating point values by the same factor, choose points at random, and throw away points that fall outside your rectangle. However, you don't know how many trials you'd need before you got N points in the rectangle...
Ascii art:
Take a 3x3 rectangle:
***
***
***
And spread one of the sides by 3x:
*..*..*..*
*..*..*..*
*..*..*..*
You can kind of see here that the points are more densely packed vertically than they are horizontaly. What you actually want instead is uniform distribution by area
The most straightforward way to handle this is through rejection sampling:
http://en.wikipedia.org/wiki/Rejection_sampling
// Given dimensions of the rectangle A, B where A <= B
boolean flag = true
while (flag) do:
double a = NextRandomDouble(0,B)
double b = NextRandomDouble(0,B)
if (a <= A)
return(a, b)
else
next
You essentially generate uniform numbers from a square that fits the original rectangle (of length B, in this example). If the number falls in the rectangle, keep the pair. If it does not, throw it away and try again!
I am trying to implement Bezier Curves for an assignment. I am trying to move a ball (using bezier curves) by giving my function an array of key frames. The function should give me all the frames in between the key frames ... or control points ... but although I'm using the formula found on wikipedia... it is not really working :s
her's my code:
private void interpolate(){
float x,y,b, t = 0;
frames = new Frame[keyFrames.length];
for(int i =0;i<keyFrames.length;++i){
t+=0.001;
b = Bint(i,keyFrames.length,t);
x = b*keyFrames[i].x;
y = b*keyFrames[i].y;
frames[i] = new Frame(x,y);
}
}
private float Bint(int i, int n, float t){
float Cni = fact(n)/(fact(i) * fact(n-i));
return Cni * pow(1-t,n-i) * pow(t,i);
}
Also I've noticed that the frames[] array should be much bigger but I can't find any other text which is more programmer friendly
Thanks in advance.
There are lots of things that don't look quite right here.
Doing it this way, your interpolation will pass exactly through the first and last control points, but not through the others. Is that what you want?
If you have lots of key frames, you're using a very-high-degree polynomial for your interpolation. Polynomials of high degree are notoriously badly-behaved, you may get your position oscillating wildly in between the key frame positions. (This is one reason why the answer to question 1 should probably be no.)
Assuming for the sake of argument that you really do want to do this, your value of t should go from 0 at the start to 1 at the end. Do you happen to have exactly 1001 of these key frames? If not, you'll be doing the wrong thing.
Evaluating these polynomials with lots of calls to fact and pow is likely to be inefficient, especially if n is large.
I'm reluctant to go into much detail about what you should do without knowing more about the scope of your assignment -- it will do no one any good for Stack Overflow to do your homework for you! What have you already been told about Bezier curves? What exactly does your assignment ask you to do?
EDITED to add:
The simplest way to do interpolation using Bezier curves is probably this. Have one (cubic) Bezier curve between each pair of key-points. The endpoints (first and last control points) of each Bezier curve are those keypoints. You need two more control points. For motion to be smooth as you move through a given keypoint, you need (keypoint minus previous control point) = (next control point minus keypoint). So you're choosing a single vector at each keypoint, which will determine where the previous and subsequent control points go. As you move through each keypoint, you'll be moving in the direction of that vector, and the longer the vector is the faster you'll be moving. (If the vector is zero then your cubic Bezier degenerates into a simple straight-line path.)
Choosing that vector so that everything looks nice is highly nontrivial, but you probably aren't really being asked to do that at this stage. So something pretty simple will probably be good enough. You might, e.g., take the vector to be proportional to (next keypoint minus previous keypoint). You'll need to do something a bit different at the start and end of your path if you do that.
Finally got What I needed! Here's what I did:
private void interpolate() {
float t = 0;
float x,y,b;
for(int f =0;f<frames.length;f++) {
x=0;
y=0;
for(int i = 0; i<keyFrames.length; i++) {
b = Bint(i,keyFrames.length-1,map(t,0,time,0,1));
x += b*keyFrames[i].x;
y += b*keyFrames[i].y;
}
frames[f] = new Frame(x,y);
t+=partialTime;
}
}
private void createInterpolationData() {
time = keyFrames[keyFrames.length-1].time -
keyFrames[0].time;
noOfFrames = 60*time;
partialTime = time/noOfFrames;
frames = new Frame[ceil(noOfFrames)];
}