Clip line to screen coordinates - c++

I have line that is defined as two points.
start = (xs,ys)
end = (xe, ye)
Drawing function that I'm using Only accepts lines that are fully in screen coordinates.
Screen size is (xSize, ySize).
Top left corner is (0,0). Bottom right corner is (xSize, ySize).
Some other funcions gives me line that that is defined for example as start(-50, -15) end(5000, 200). So it's ends are outside of screen size.
In C++
struct Vec2
{
int x, y
};
Vec2 start, end //This is all little bit pseudo code
Vec2 screenSize;//You can access coordinates like start.x end.y
How can I calculate new start and endt that is at the screen edge, not outside screen.
I know how to do it on paper. But I can't transfer it to c++.
On paper I'm sershing for point that belongs to edge and line. But it is to much calculations for c++.
Can you help?

There are many line clipping algorithms like:
Cohen–Sutherland wikipedia page with implementation
Liang–Barsky wikipedia page
Nicholl–Lee–Nicholl (NLN)
and many more. see Line Clipping on wikipedia
[EDIT1]
See below figure:
there are 3 kinds of start point:
sx > 0 and sy < 0 (red line)
sx < 0 and sy > 0 (yellow line)
sx < 0 and sy < 0 (green and violet lines)
In situations 1 and 2 simply find Xintersect and Yintersect respectively and choose them as new start point.
As you can see, there are 2 kinds of lines in situation 3. In this situation find Xintersect and Yintersect and choose the intersect point near the end point which is the point that has minimum distance to endPoint.
min(distance(Xintersect, endPoint), distance(Yintersect, endPoint))
[EDIT2]
// Liang-Barsky function by Daniel White # http://www.skytopia.com/project/articles/compsci/clipping.html
// This function inputs 8 numbers, and outputs 4 new numbers (plus a boolean value to say whether the clipped line is drawn at all).
//
bool LiangBarsky (double edgeLeft, double edgeRight, double edgeBottom, double edgeTop, // Define the x/y clipping values for the border.
double x0src, double y0src, double x1src, double y1src, // Define the start and end points of the line.
double &x0clip, double &y0clip, double &x1clip, double &y1clip) // The output values, so declare these outside.
{
double t0 = 0.0; double t1 = 1.0;
double xdelta = x1src-x0src;
double ydelta = y1src-y0src;
double p,q,r;
for(int edge=0; edge<4; edge++) { // Traverse through left, right, bottom, top edges.
if (edge==0) { p = -xdelta; q = -(edgeLeft-x0src); }
if (edge==1) { p = xdelta; q = (edgeRight-x0src); }
if (edge==2) { p = -ydelta; q = -(edgeBottom-y0src);}
if (edge==3) { p = ydelta; q = (edgeTop-y0src); }
r = q/p;
if(p==0 && q<0) return false; // Don't draw line at all. (parallel line outside)
if(p<0) {
if(r>t1) return false; // Don't draw line at all.
else if(r>t0) t0=r; // Line is clipped!
} else if(p>0) {
if(r<t0) return false; // Don't draw line at all.
else if(r<t1) t1=r; // Line is clipped!
}
}
x0clip = x0src + t0*xdelta;
y0clip = y0src + t0*ydelta;
x1clip = x0src + t1*xdelta;
y1clip = y0src + t1*ydelta;
return true; // (clipped) line is drawn
}

Here is a function I wrote. It cycles through all 4 planes (left, top, right, bottom) and clips each point by the plane.
// Clips a line segment to an axis-aligned rectangle
// Returns true if clipping is successful
// Returns false if line segment lies outside the rectangle
bool clipLineToRect(int a[2], int b[2],
int xmin, int ymin, int xmax, int ymax)
{
int mins[2] = {xmin, ymin};
int maxs[2] = {xmax, ymax};
int normals[2] = {1, -1};
for (int axis=0; axis<2; axis++) {
for (int plane=0; plane<2; plane++) {
// Check both points
for (int pt=1; pt<=2; pt++) {
int* pt1 = pt==1 ? a : b;
int* pt2 = pt==1 ? b : a;
// If both points are outside the same plane, the line is
// outside the rectangle
if ( (a[0]<xmin && b[0]<xmin) || (a[0]>xmax && b[0]>xmax) ||
(a[1]<ymin && b[1]<ymin) || (a[1]>ymax && b[1]>ymax)) {
return false;
}
const int n = normals[plane];
if ( (n==1 && pt1[axis]<mins[axis]) || // check left/top plane
(n==-1 && pt1[axis]>maxs[axis]) ) { // check right/bottom plane
// Calculate interpolation factor t using ratio of signed distance
// of each point from the plane
const float p = (n==1) ? mins[axis] : maxs[axis];
const float q1 = pt1[axis];
const float q2 = pt2[axis];
const float d1 = n * (q1-p);
const float d2 = n * (q2-p);
const float t = d1 / (d1-d2);
// t should always be between 0 and 1
if (t<0 || t >1) {
return false;
}
// Interpolate to find the new point
pt1[0] = (int)(pt1[0] + (pt2[0] - pt1[0]) * t );
pt1[1] = (int)(pt1[1] + (pt2[1] - pt1[1]) * t );
}
}
}
}
return true;
}
Example Usage:
void testClipLineToRect()
{
int screenWidth = 320;
int screenHeight = 240;
int xmin=0;
int ymin=0;
int xmax=screenWidth-1;
int ymax=screenHeight-1;
int a[2] = {-10, 10};
int b[2] = {300, 250};
printf("Before clipping:\n\ta={%d, %d}\n\tb=[%d, %d]\n",
a[0], a[1], b[0], b[1]);
if (clipLineToRect(a, b, xmin, ymin, xmax, ymax)) {
printf("After clipping:\n\ta={%d, %d}\n\tb=[%d, %d]\n",
a[0], a[1], b[0], b[1]);
}
else {
printf("clipLineToRect returned false\n");
}
}
Output:
Before clipping:
a={-10, 10}
b=[300, 250]
After clipping:
a={0, 17}
b=[285, 239]

Related

weird inaccuracy in line rotation - c++

I have programmed a simple dragon curve fractal. It seems to work for the most part, but there is an odd logical error that shifts the rotation of certain lines by one pixel. This wouldn't normally be an issue, but after a few generations, at the right size, the fractal begins to look wonky.
I am using open cv in c++ to generate it, but I'm pretty sure it's a logical error rather than a display error. I have printed the values to the console multiple times and seen for myself that there is a one-digit difference between values that are intended to be the exact same - meaning a line may have a y of 200 at one end and 201 at another.
Here is the full code:
#include<iostream>
#include<cmath>
#include<opencv2/opencv.hpp>
const int width=500;
const int height=500;
const double PI=std::atan(1)*4.0;
struct point{
double x;
double y;
point(double x_,double y_){
x=x_;
y=y_;
}};
cv::Mat img(width,height,CV_8UC3,cv::Scalar(255,255,255));
double deg_to_rad(double degrees){return degrees*PI/180;}
point rotate(int degree, int centx, int centy, int ll) {
double radians = deg_to_rad(degree);
return point(centx + (ll * std::cos(radians)), centy + (ll * std::sin(radians)));
}
void generate(point & r, std::vector < point > & verticies, int rotation = 90) {
int curRotation = 90;
bool start = true;
point center = r;
point rot(0, 0);
std::vector<point> verticiesc(verticies);
for (point i: verticiesc) {
double dx = center.x - i.x;
double dy = center.y - i.y;
//distance from centre
int ll = std::sqrt(dx * dx + dy * dy);
//angle from centre
curRotation = std::atan2(dy, dx) * 180 / PI;
//add 90 degrees of rotation
rot = rotate(curRotation + rotation, center.x, center.y, ll);
verticies.push_back(rot);
//endpoint, where the next centre will be
if (start) {
r = rot;
start = false;
}
}
}
void gen(int gens, int bwidth = 1) {
int ll = 7;
std::vector < point > verticies = {
point(width / 2, height / 2 - ll),
point(width / 2, height / 2)
};
point rot(width / 2, height / 2);
for (int i = 0; i < gens; i++) {
generate(rot, verticies);
}
//draw lines
for (int i = 0; i < verticies.size(); i += 2) {
cv::line(img, cv::Point(verticies[i].x, verticies[i].y), cv::Point(verticies[i + 1].x, verticies[i + 1].y), cv::Scalar(0, 0, 0), 1, 8);
}
}
int main() {
gen(10);
cv::imshow("", img);
cv::waitKey(0);
return 0;
}
First, you use int to store point coordinates - that's a bad idea - you lose all accuracy of point position. Use double or float.
Second, your method for drawing fractals is not too stable numericly. You'd better store original shape and all rotation/translation/scale that indicate where and how to draw scaled copies of the original shape.
Also, I believe this is a bug:
for(point i: verices)
{
...
vertices.push_back(rot);
...
}
Changing size of vertices while inside such a for-loop might cause a crash or UB.
Turns out it was to do with floating-point precision. I changed
x=x_;
y=y_;
to
x=std::round(x_);
y=std::round(y_);
and it works.

Intersection of 3 circle not correct c++

I am trying to find the common intersection(x,y) of 3 circles using c++. But i'm not getting the proper output. What am i doing wrong in my code? Here i my program i'm using to calculate the common intersection point. Here first i have calculated the intersection of two pixels which comes from quadric equation,as (x0,y0), (x1,y1). After that considering that 3rd circle intersects at atleast one point, i have used those two intersection points in 3rd circle, whichever satisfies the 3rd circle it is considered as the common intersection point of 3 circle. Am i doing anything wrong?
vector<pix> obj; struct pix { int x; int y; };
auto p0 = obj[stoi(r[2])][stoi(r[0])];
auto p1 = obj[stoi(r[2])][stoi(r[1])];
int ax = p1.x-p0.x; int ay = p1.y-p0.y;
int bx = -ay; int by = ax;
pix pv;
pv.x = p1.x+bx; pv.y = p1.y+by;
OrigImg.copyTo(cv_ptr->image);
for(auto pi : obj[stoi(r[2])]) {
float p0pi = sqrt(pow(p0.x-pi.x,2)+pow(p0.y-pi.y,2));
float p1pi = sqrt(pow(p1.x-pi.x,2)+pow(p1.y-pi.y,2));
float pvpi = sqrt(pow(pv.x-pi.x,2)+pow(pv.y-pi.y,2));
float a1 = 2*(p1.x-p0.x);
float b1 = 2*(p1.y-p0.y);
float c1 = p0.x*p0.x-p1.x*p1.x+p0.y*p0.y-p1.y*p1.y-p0pi*p0pi+p1pi*p1pi;
float a = a1*a1+b1*b1;
float b = 2*(b1*c1 + b1*a1*p0.x - p0.y*a1*a1);
float c = c1*c1+2*c1*p0.x*a1 + a1*a1*(p0.x*p0.x + p0.y*p0.y - p0pi*p0pi);
int y0 = -(b+sqrt(b*b-4*a*c))/2*a;
int y1 = (b+sqrt(b*b-4*a*c))/2*a;
int x0 = -(b1*y0+c1)/a1;
int x1 = -(b1*y1+c1)/a1;
int x,y;
cout<<"hello"<<x0<<"\t"<<y0<<"\t"<<x1<<"\t"<<y1<<endl;
cout<<pow(x0-pv.x,2)+pow(y0-pv.y,2)<<"\t"<<pvpi*pvpi<<"\t"<<
pow(x1-pv.x,2)+pow(y1-pv.y,2)<<"\t"<<pvpi*pvpi<<endl;
if(sqrt(pow(x0-pv.x,2)+pow(y0-pv.y,2))==pvpi) {
x = x0; y = y0;
}
else if(sqrt(pow(x1-pv.x,2)+pow(y1-pv.y,2))==pvpi) {
x = x1; y = y1;
}
if(x>=0 && x<OrigImg.rows && y>=0 && y<OrigImg.cols) {
cv_ptr->image.at<cv::Vec3b>( y, x )[2] = 0;
cv_ptr->image.at<cv::Vec3b>( y, x )[1] = 0;
cv_ptr->image.at<cv::Vec3b>( y, x )[0] = 0;
}
}
}
image_pub_.publish(cv_ptr->toImageMsg());
Here p0, p1, pv are the position of 3 circles which are at different position. Here what i'm trying to do it, i have saved the pixels belonging to one object in a map obj[obj_index][pixel_index] where pixel index is index for each unique pixel belonging to that pixel and obj_index is index for each unique object.
After applying some pattern matching algorithm i get the r[0]=obj_index, r[1]=p0 index, r[2]=p1 index of object. Now what i'm trying to do it to visualize and check which pixels are present in current analysed object w.r.t previously saved object.
Here the output comes like:
hello 150492 150336 -150180 -150336
4.51763e+10 873 4.52274e+10 873

Ray-triangle intersection algorithm not intersecting (C++)

I've been trying to implement the Moller-Trumbore ray-triangle intersection algorithm in my raytracing code. The code is supposed to read in a mesh and light sources, fire off rays from the light source, and return the triangle from the mesh which each ray intersects. Here is my implementation of the algorithm:
//Moller-Trumbore intersection algorithm
void getFaceIntersect(modelStruct m, ray r, hitFaceStruct& hitFaces)
{
// Constant thoughout loop
point origin = r.p0;
point direction = r.u;
hitFaces.isHit = false;
for (int i = 0; i < m.faces; i++)
{
// Get face vertices
point v1 = m.vertList[m.faceList[i].v1];
point v2 = m.vertList[m.faceList[i].v2];
point v3 = m.vertList[m.faceList[i].v3];
// Get two edgess
point edge1 = v2 - v1;
point edge2 = v3 - v1;
// Get p
point p = direction.cross(direction, edge2);
// Use p to find determinant
double det = p.dot(edge1, p);
// If the determinant is about 0, the ray lies in the plane of the triangle
if (abs(det) < 0.00000000001)
{
continue;
}
double inverseDet = 1 / det;
point v1ToOrigin = (origin - v1);
double u = v1ToOrigin.dot(v1ToOrigin, p) * inverseDet;
// If u is not between 0 and 1, no hit
if (u < 0 || u > 1)
{
continue;
}
// Used for calculating v
point q = v1ToOrigin.cross(v1ToOrigin, edge1);
double v = direction.dot(direction, q) * inverseDet;
if (v < 0 || (u + v) > 1)
{
continue;
}
double t = q.dot(edge2, q) * inverseDet;
// gets closest face
if (t < abs(hitFaces.s)) {
hitFaceStruct goodStruct = hitFaceStruct();
goodStruct.face = i;
goodStruct.hitPoint = p;
goodStruct.isHit = true;
goodStruct.s = t;
hitFaces = goodStruct;
break;
}
}
}
The relevant code for hitFaceStruct and modelStruct is as follows:
typedef struct _hitFaceStruct
{
int face; // the index of the sphere in question in the list of faces
float s; // the distance from the ray that hit it
bool isHit;
point hitPoint;
} hitFaceStruct;
typedef struct _modelStruct {
char *fileName;
float scale;
float rot_x, rot_y, rot_z;
float x, y, z;
float r_amb, g_amb, b_amb;
float r_dif, g_dif, b_dif;
float r_spec, g_spec, b_spec;
float k_amb, k_dif, k_spec, k_reflective, k_refractive;
float spec_exp, index_refraction;
int verts, faces, norms = 0; // Number of vertices, faces, normals, and spheres in the system
point *vertList, *normList; // Vertex and Normal Lists
faceStruct *faceList; // Face List
} modelStruct;
Whenever I shoot a ray, the values of u or v in the algorithm code always come out to a large negative number, rather than the expected small, positive one. The direction vector of the ray is normalized before I pass it on to the intersection code, and I'm positive I'm firing rays that would normally hit the mesh. Can anyone please help me spot my error here?
Thanks!

Implementation of feature detection algorithm

I'm fairly new to programming and would like to know how to start implementing the following algorithm in C++,
Given a binary image where pixels with intensity 255 show edges and pixels with intensity 0 show the background, find line segments longer than n pixels in the image. t is a counter showing the number of iterations without finding a line, and tm is the maximum number of iterations allowed before exiting the program.
Let t=0.
Take two edge points randomly from the image and find equation of the line passing
through them.
Find m, the number of other edge points in the image that are within distance d pixels of
the line.
If m > n, go to Step 5.
Otherwise (m ≤ n), increment t by 1 and if t < tm go to Step 2, and
if t ≥ tm exit program.
Draw the line and remove the edge points falling within distance d pixels of it from the
image. Then, go to Step 1
Basically, I just want to randomly pick two points from the image, find the distance between them, and if that distance is too small, I would detect a line between them.
I would appreciate if a small code snippet is provided, to get me started.
this is more like a RANSAC parametric line detection. I would also keep this post updated if I get it done.
/* Display Routine */
#include "define.h"
ByteImage bimg; //A copy of the image to be viewed
int width, height; //Window dimensions
GLfloat zoomx = 1.0, zoomy = 1.0; //Pixel zoom
int win; //Window index
void resetViewer();
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
if ((w!=width) || (h!=height)) {
zoomx=(GLfloat)w/(GLfloat)bimg.nc;
zoomy=(GLfloat)h/(GLfloat)bimg.nr;
glPixelZoom(zoomx,zoomy);
}
width=w; height=h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void mouse(int button, int state, int x, int y) {
glutPostRedisplay();
if((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN) &&
(zoomx==1.0) && (zoomy==1.0)){
printf(" row=%d, col=%d, int=%d.\n", y,x, (int)bimg.image[(bimg.nr-1-y)*bimg.nc+x]);
glutPostRedisplay();
}
}
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glRasterPos2i(0, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glDrawPixels((GLsizei)bimg.nc,(GLsizei)bimg.nr, GL_LUMINANCE,GL_UNSIGNED_BYTE, bimg.image);
glutSwapBuffers();
}
Let us assume you have an int[XDIMENSION][YDIMENSION]
Let t=0.
int t = 0; // ;-)
Take two edge points randomly from the image and find equation of the line passing through them.
Brute force: you could randomly search the image for points and re-search when they are not edge points
struct Point {
int x;
int y;
};
bool is_edge(Point a) {
return image[a.x][a.y] == 255;
}
int randomUpto(int upto) {
int r = rand() % upto;
return r;
}
, which needs the pseudo-random number generator to be initialized via
srand(time(NULL));
To find edge points
Point a;
do {
a.x = randomUpto(XDIMENSION);
a.y = randomUpto(YDIMENSION);
} while ( ! is_edge(a) );
Find m, the number of other edge points in the image that are within distance d pixels of the line.
You need the line between the points. Some searching yields this fine answer, which leads to
std::vector<Point> getLineBetween(Point a, Point b) {
double dx = b.x - a.x;
double dy = b.y - a.y;
double dist = sqrt(dx * dx + dy * dy);
dx /= dist;
dy /= dist;
std::vector<Point> points;
points.push_back(a);
for ( int i = 0 ; i < 2*dist; i++ ) {
Point tmp;
tmp.x = a.x + (int)(i * dx /2.0);
tmp.y = a.y + (int)(i * dy /2.0);
if ( tmp.x != points.back().x
|| tmp.y != points.back().y ) {
points.push_back(tmp);
}
}
return points;
}
Do you see a pattern here? Isolate the steps into substeps, ask google, look at the documentation, try out stuff until it works.
Your next steps might be to
create a distance function, euclidean should suffice
find all points next to line (or next to a point, which is easier) based on the distance function
Try out some and come back if you still need help.

Algorithm for edge intersection?

Given Polygon P which I have its verticies in order. and I have a rectangle R with 4 verticies how could I do this:
If any edge of P (line between adjacent vertexes) intersects an edge of R, then return TRUE, otherwise return FALSE.
Thanks
* *
* *
What you want is a quick way to determine if a line-segment intersects an axis-aligned rectangle. Then just check each line segment in the edge list against the rectangle. You can do the following:
1) Project the line onto the X-axis, resulting in an interval Lx.
2) Project the rectangle onto the X-axis, resulting in an interval Rx.
3) If Lx and Rx do not intersect, the line and rectangle do not intersect.
[Repeat for the Y-axis]:
4) Project the line onto the Y-axis, resulting in an interval Ly.
5) Project the rectangle onto the Y-axis, resulting in an interval Ry.
6) If Ly and Ry do not intersect, the line and rectangle do not intersect.
7) ...
8) They intersect.
Note if we reach step 7, the shapes cannot be separated by an axis-aligned line. The thing to determine now is if the line is fully outside the rectangle. We can determine this by checking that all the corner points on the rectangle are on the same side of the line. If they are, the line and rectangle are not intersecting.
The idea behind 1-3 and 4-6 comes from the separating axis theorem; if we cannot find a separating axis, they must be intersecting. All these cases must be tested before we can conclude they are intersecting.
Here's the matching code:
#include <iostream>
#include <utility>
#include <vector>
typedef double number; // number type
struct point
{
number x;
number y;
};
point make_point(number pX, number pY)
{
point r = {pX, pY};
return r;
}
typedef std::pair<number, number> interval; // start, end
typedef std::pair<point, point> segment; // start, end
typedef std::pair<point, point> rectangle; // top-left, bottom-right
namespace classification
{
enum type
{
positive = 1,
same = 0,
negative = -1
};
}
classification::type classify_point(const point& pPoint,
const segment& pSegment)
{
// implicit line equation
number x = (pSegment.first.y - pSegment.second.y) * pPoint.x +
(pSegment.second.x - pSegment.first.x) * pPoint.y +
(pSegment.first.x * pSegment.second.y -
pSegment.second.x * pSegment.first.y);
// careful with floating point types, should use approximation
if (x == 0)
{
return classification::same;
}
else
{
return (x > 0) ? classification::positive :classification::negative;
}
}
bool number_interval(number pX, const interval& pInterval)
{
if (pInterval.first < pInterval.second)
{
return pX > pInterval.first && pX < pInterval.second;
}
else
{
return pX > pInterval.second && pX < pInterval.first;
}
}
bool inteveral_interval(const interval& pFirst, const interval& pSecond)
{
return number_interval(pFirst.first, pSecond) ||
number_interval(pFirst.second, pSecond) ||
number_interval(pSecond.first, pFirst) ||
number_interval(pSecond.second, pFirst);
}
bool segment_rectangle(const segment& pSegment, const rectangle& pRectangle)
{
// project onto x (discard y values)
interval segmentX =
std::make_pair(pSegment.first.x, pSegment.second.x);
interval rectangleX =
std::make_pair(pRectangle.first.x, pRectangle.second.x);
if (!inteveral_interval(segmentX, rectangleX))
return false;
// project onto y (discard x values)
interval segmentY =
std::make_pair(pSegment.first.y, pSegment.second.y);
interval rectangleY =
std::make_pair(pRectangle.first.y, pRectangle.second.y);
if (!inteveral_interval(segmentY, rectangleY))
return false;
// test rectangle location
point p0 = make_point(pRectangle.first.x, pRectangle.first.y);
point p1 = make_point(pRectangle.second.x, pRectangle.first.y);
point p2 = make_point(pRectangle.second.x, pRectangle.second.y);
point p3 = make_point(pRectangle.first.x, pRectangle.second.y);
classification::type c0 = classify_point(p0, pSegment);
classification::type c1 = classify_point(p1, pSegment);
classification::type c2 = classify_point(p2, pSegment);
classification::type c3 = classify_point(p3, pSegment);
// test they all classify the same
return !((c0 == c1) && (c1 == c2) && (c2 == c3));
}
int main(void)
{
rectangle r = std::make_pair(make_point(1, 1), make_point(5, 5));
segment s0 = std::make_pair(make_point(0, 3), make_point(2, -3));
segment s1 = std::make_pair(make_point(0, 0), make_point(3, 0));
segment s2 = std::make_pair(make_point(3, 0), make_point(3, 6));
segment s3 = std::make_pair(make_point(2, 3), make_point(9, 8));
std::cout << std::boolalpha;
std::cout << segment_rectangle(s0, r) << std::endl;
std::cout << segment_rectangle(s1, r) << std::endl;
std::cout << segment_rectangle(s2, r) << std::endl;
std::cout << segment_rectangle(s3, r) << std::endl;
}
Hope that makes sense.
I think your problem is equivalent to convex polygon intersection, in which case this might help. See also: How do I determine if two convex polygons intersect?
Untested, obviously, but in rough pseudocode:
// test two points against an edge
function intersects ( side, lower, upper, pt1Perp, pt1Par, pt2Perp, pt2Par )
{
if ( ( pt1Perp < side and pt2Perp > side ) or ( pt1Perp > side and pt2Perp < side )
{
intersection = (side - pt1Perp) * (pt2Par - pt1Par) / (pt2Perp - pt1Perp);
return (intersection >= lower and intersection <= higher);
}
else
{
return false;
}
}
// left, right, bottom, top are the bounds of R
for pt1, pt2 adjacent in P // don't forget to do last,first
{
if ( intersects ( left, bottom, top, pt1.x, pt1.y, pt2.x, pt2.y )
or intersects ( right, bottom, top, pt1.x, pt1.y, pt2.x, pt2.y )
or intersects ( top, left, right, pt1.y, pt1.x, pt2.y, pt2.x )
or intersects ( bottom, left, right, pt1.y, pt1.x, pt2.y, pt2.x ) )
{
return true;
}
}
Basically, if two adjacent P vertices are on opposite sides of one of the R's edges, check whether the intersection point falls in range.
Just FYI, geometrictools is a great resource for such things (especially the Math section)