Rotated 2d rectangle intersecting points or area - c++

Moving ahead from previous question.I have two rectangle and they look like this:
struct Rect
{
NSPoint topLeft;
NSPoint topRight;
NSPoint bottomLeft;
NSPoint bottomRight;
}
I use something similar code to check whether rectangles intersects(or collision) . In case If 2 rectangles intersects I want to calculate the area of intersection in the first rectangle or the points where the second rectangle intersects with first rectangle (i.e. intersection coordinates).
How do I calculate the intersecting points or the area of intersection.

You can determine the points of intersection by doing this:
foreach line in rectangle 1: line1
foreach line in rectangle 2: line2
find point of intersection for line1, line2
to find the intersection point of two lines:
http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
You can find the area of intersection by finding the points of intersection, and splitting the lines based off that to create new sides/delete sides. You could get up to 8 points in the resulting polygon, or as few as 3 (not counting degenerate cases).
No, I didn't say this is the most efficient method, but it will work :)

What you are asking seems to be a specific case of "polygon intersection". (since rectangles are polygons).
Here is a library that does this:
http://www.cs.man.ac.uk/aig/staff/alan/software/
Maybe it can help (they somehow talk about the algorithm). However, if you only need rectangle intersection, it can probably be simplified.
Also, perhaps you could take a look at this SO question:
Algorithm to detect intersection of two rectangles?

Related

OpenGL How to draw curves being part of circle depends of last point location with requirements: fixed radius, last point givig direction

I can not put questions in one line also here they are:
How to draw a curve which is part of the circle(depending on the end point)
Let:
p1=(x1,y1) be the first point
have to be line p2=(x2,y2) is the starting point of drawing the curve
p3=(x3,y3) be the end point (mouse location)
Requirements:
if P3 is going closer to p2, the larger the potential radius becomes
p3 describes the drawing direction
if p3 is pararel to p2 there nothing should be drawn (or drawn line p3>p2)
if p3 is equal to p1 it should draw a relatively large wheel,
EDIT:
I think i found solution how to draw that part of circle, please look at that gifs below:
Tangent A->B implies a normal-line Q that passes through the (as-yet unfound) circle center D
Find the midpoint M of chord R (i.e., segment B-C).
A line S perpendicular to R passing through M also passes through D
So: Construct lines Q and S and find their intersection D. The length of segment B-D is the radius of the circle. With the radius and center D you should be able to calculate the arc B->C.
in b4 9000 hours in mspaintpaint.net

CGAL Intersection Circle and Vertical Lines (not segments)

In CGAL I need to compute the exact intersection points between a set of lines and a set o circles. Starting from the circles (which can have irrational radius but rational squared_radius) I should compute the vertical line passing through the x_extremal_points of each circle (not segment but lines) and calculate the intersection point of each circle with each line.
I’m using CircularKernel and Circle_2 for the circles and Line_2 for the lines.
Here’s an example of how I compute the circles and the lines and how I check if they intersect.
int main()
{
Point_2 a = Point_2(250.5, 98.5);
Point_2 b = Point_2(156, 139);
//Radius is half distance ab
Circular_k::FT aRad = CGAL::squared_distance(a, b);
Circle_2 circle_a = Circle_2(a, aRad/4);
Circular_arc_point_2 a_left_point = CGAL::x_extremal_point(circle_a, false);
Circular_arc_point_2 a_right_point = CGAL::x_extremal_point(circle_a, true);
//for example use only left extremal point of circle a
CGAL::Bbox_2 a_left_point_bb = a_left_point.bbox();
Line_2 a_left_line = Line_2(Point_2(a_left_point_bb.xmin(), a_left_point_bb.ymin()),
Point_2(a_left_point_bb.xmin(), a_left_point_bb.ymax()));
if ( do_intersect(a_left_line, circle_a) ) {
std::cout << "intersect";
}
else {
std::cout << " do not intersect ";
}
return 0;
}
This flow rises this exception:
CGAL error: precondition violation!
Expression : y != 0
File : c:\dev\cgal-4.7\include\cgal\gmp\gmpq_type.h
Line : 371
Explanation:
Refer to the bug-reporting instructions at http://www.cgal.org/bug_report.html
I can’t figure out how I can calculate the intersection points.
Also, Is there a better way to compute the lines? I know abot the x_extremal_point function but it returns the Circular_arc_point point and I’m not able to construct a vertical line passing through them directly without using Bounding box.
In your code, you seem to compute the intersection of a circle with the vertical line that passes through the extremal point of the circle (I forget the bounding box). Well, then the (double) intersection is the extremal point itself...
More globally, you say in your text of introduction that you want to compute exact intersections. Then you should certainly not use bounding boxes, which by definition introduce some approximation.
If I understand your text correctly,
* for testing the intersection of your vertical lines with the other circles, you don't need to construct the lines, you only need to compare the abscissae of the extremal points of two circles, which you can do with the CGAL circular kernel.
* for computing the intersection of a vertical line that has non-rational coefficients (since its equation is of the form x= +-sqrt(r)) with another circle, then the CGAL circular kernel will not give you a pre-cooked solution. That kernel will help, but you must still compute a few things by hand.
If you don't want to bother, then you can also just take a standard CGAL kernel with Core::Expr as underlying number type. It can do "anything", but it will be slower.
For efficiency, you should look at the underlying 1D problem: projecting the lines and the circle on the X axis, you have a set of points and a set of intervals [Xc-R, Xc+R].
If the L points are sorted increasingly, you can locate the left bound of an interval in time Lg(L) by dichotomy, and scan the list of points until the right bound. This results in a O(Lg(L).C + I) behavior (C circle intervals), where I is the number of intersections reported.
I guess that with a merge-like process using an active list, if the interval bounds are also sorted you can lower to O(L + C + I).
The extension to 2D is elementary.

how to determine if points is on shape and in shape?

I have two of this:
bool isPointOnShape(int a, int b)
{
}
bool isPointInShape(int a, int b)
{
}
Say I have a square, first point (bottom left corner) is x,y (0,0) second point (top left) is (0,2), third is (2,2) and fourth is (0,2).
The Points on shape would be (0,1) (1,2) (2,1) (1,0) and Points in shape is (1,1)
How do I find out the points on shape / in shape and return a true value so that I can store it somewhere?
For a potentially non-convex shape you may use an algorithm like this:
Find how many shape edges intersect a ray starting at (a,b). You may choose any ray, but it is easier to calculate intersections if the ray is horizontal or vertical.
Point is inside if the number of intersections is odd.
Try going over this tutorial in openCV explaining how to use the point in polygon test. Also a good reference is this wiki page which covers several other methods.
If you don't want to use openCV - in general you can use the Ray casting algorithm:
take a line from the given point (x,y) in any direction you want, let's call it L
for each line in ((0,0),(0,2)), ((0,0),(2,0)), ((2,2),(0,2)), ((2,2),(2,0)) test if that line intersect with with L and count the number of intersections N
if N is odd the point (x,y) is in the polygon

Intersection of a mesh with a parametric surface

I'm wondering how a precise algorithm can be written to compute the frontier of the surface of intersection between a parametric surface f : R^2 --> R^3 and a triangulated mesh.
I've thought to a first approach:
nStepsU = 100
nStepsV = 100
tolerance=0.01 // pick some sensical value
intersectionVertices={}
for u from minU to maxU in nStepsU:
for v from minV to maxV in nStepsV:
for v in verticesInMesh:
if euclidean distance( f(u,v), v ) < tolerance:
add vertex v in a set
connect the vertices in intersectionVertices with a line strip
draw the vertices in intersectionVertices
This algorithm, is very simple but slow (n^3) and does not keep in account that the topography of the mesh is based on triangles so the output points are points of the mesh and not points computed exploiting the intersection of surface with the triangles and is heavily dependent of the tolerance one has to set.
Has someone some better idea or can one drive me to a suitable library for this purpose?
I would iterate over each triangle, and compute the intersection of the triangle with the surface. I would use a geometry shader which takes the triangles as input, and outputs line strips. For each vertex in the triangle, compute the signed distance to the surface. Then iterate over the edges: If there are two vertices where h has different signs, the edge between these vertices intersects with the surface. While I'm sure the exact intersection can be computed, the easiest solution would be to interpolate linearly, i.e.
vec3 intersection = (h0 * v1 + h1 * v0) / (h0 + h1);
Then output each intersection as a vertex of your line segment.
The code I posted here can get you started. If you want to just draw the result, you will probably run into the same problem that I described in that question. If you need the vertices on the client, you can use transform feedback.
Edit: I just did a little test. As the distance function I used
float distToHelicoid(in vec3 p)
{
float theta = p.y / 5 + offset.x / 50;
float a = mod(theta - atan(p.z, p.x), 2*PI) - PI; // [-PI, PI[
if (abs(a) > PI/2)
a = mod(theta - atan(-p.z, -p.x), 2*PI) - PI;
return a;
}
Since there is no inside/outside, and this distance function goes from -90° to 90°, you can only emit vertices if the sign goes from small negative to small positive or vice versa, not when it flips from 90° to -90°. Here I simply filtered out distances where abs(dist) > 45°:
The clean way would be to determine the index of the closest revolution. E.g. [-pi, pi] would be revolution 0, [pi, 3pi] = revolution 1, etc. You would then only emit if two distances refer to the same revolution.
If your surface is always helicoid, you can try to project everything on a cylinder around axis Y.
The surface of helicoid consists of lines orthogonal to the surface of that cylinder and after projection you will get a spiral. After projection of 3D triangle mesh onto that cylinder you will get 2D triangle mesh (note that some areas may be covered with several layers of triangles).
So the task becomes finding triangles in 2D triangle mesh intersecting the spiral which is simpler. If you are OK with approximations, you can segment that spiral and use some kind of tree to find triangles intersecting the spiral.
When you have a triangle intersecting part of spiral, its intersection will be a segment, you can just recalculate 3D coordinates of the segment and set of these segments is your intersection line.

Line - Circle intersection test in 3d world?

i have a 3d world where i have several 2d circles laying on the ground facing to the sky.
how can i check if a line will intersect one of those circles frop top-to-down?
i tried to search but all i get is this kind of intersection test:
http://mathworld.wolfram.com/Circle-LineIntersection.html
but its not what i need, here is image what i mean:
http://imageshack.us/m/192/8343/linecircleintersect.png
If you are in a coordinate system, where the ground is given by z = c for c some constant, then you could simply calculate the x, y coordinates of the line for z = c. Now for a circle of origin x0, y0 and radius R, you would simply check if
(x - x0)^2 + (y - y0)^2 <= R^2.
If this is true, the line intersects the circle.
In a 3D sense you are first concerned with not with a circle but with the plane where the circle lies on. Then you can find the point of intersection between the ray (line) and the plane (disk).
I like to use homogeneous coordinates for point, planes and lines and I hope you are familiar with vector dot · and cross products ×. Here is the method:
Plane (disk) is defined by a point vector r=[rx,ry,rz] and a normal direction vector n=[nx,ny,nz]. Together they form a plane W=[W1,W2]=[n,-r·n].
Line (ray) is defined by two point vectors r_A=[rAx,rAy,rAz] and r_B=[rBx,rBy,rBz]. Together they form the line L=[L1,L2]=[r_B-r_A, r_A×r_B]
The intersecting Point is defined by P=[P1,P2]=[L1×W1-W2*L2, -L2·W1], or expanded out as
P=[ (r_B-r_A)×n-(r·n)*(r_A×r_B), -(r_A×r_B)·n ]
The coordinates for the point are found by r_P = P1/P2 where P1 has three elements and P2 is scalar.
Once you have the coordinates you check the distance with the center of the circle by d=sqrt((r_p-r)·(r_p-r)) and checking d<=R where R is the radius of the circle. Note the difference in notation between a scalar multiplication * and a dot product ·
If you know for sure that the circles lie on the ground (r=[0,0,0]) and face up (n=[0,0,1]) then you can make a lot of simplifications to the above general case.
[ref: Plucker Coordinates]
Update:
When using the ground (with +Z up) as the plane (where circles lie), then use r=[rx,ry,0] and n=[0,0,1] and the above intersection point simplifies to
r_p = [ rBy-rAy, rAx-rBx, 0] / (rAy*rBx-rAx*rBy)
of which you can check the distance to the circle center.