Example #1
0
// tests whether or not a given polygon (in CW or CCW order) is simple
// a polygon is considered simple if its sides do not intersect.
bool IsSimple(const vector<PT> &p) {
	for (int i = 0; i < p.size(); i++) {
		for (int k = i+1; k < p.size(); k++) {
			int j = (i+1) % p.size();
			int l = (k+1) % p.size();
			if (i == l || j == k) continue;
			if (SegmentsIntersect(p[i], p[j], p[k], p[l])) 
				return false;
		}
	}
	return true;
}
Example #2
0
int main() {
	// expected (-5,2)/(5,-2)/(-5,2)/(5,2)/(5,2) (7.5,3) (2.5,1)
	cerr << RotateCCW90(PT(2,5)) << endl;
	cerr << RotateCW90(PT(2,5)) << endl;
	cerr << RotateCCW(PT(2,5),M_PI/2) << endl;
	cerr << ProjectPointLine(PT(-5,-2), PT(10,4), PT(3,7)) << endl;
	cerr << ProjectPointSegment(PT(-5,-2), PT(10,4), PT(3,7)) << " "
		 << ProjectPointSegment(PT(7.5,3), PT(10,4), PT(3,7)) << " "
		 << ProjectPointSegment(PT(-5,-2), PT(2.5,1), PT(3,7)) << endl;

	// expected 6.78903/1 0 1/0 0 1/1 1 1 0/(1,2)/(1,1)
	cerr << DistancePointPlane(4,-4,3,2,-2,5,-8) << endl;
	cerr << LinesParallel(PT(1,1), PT(3,5), PT(2,1), PT(4,5)) << " "
		 << LinesParallel(PT(1,1), PT(3,5), PT(2,0), PT(4,5)) << " "
		 << LinesParallel(PT(1,1), PT(3,5), PT(5,9), PT(7,13)) << endl;
	cerr << LinesCollinear(PT(1,1), PT(3,5), PT(2,1), PT(4,5)) << " "
		 << LinesCollinear(PT(1,1), PT(3,5), PT(2,0), PT(4,5)) << " "
		 << LinesCollinear(PT(1,1), PT(3,5), PT(5,9), PT(7,13)) << endl;
	cerr << SegmentsIntersect(PT(0,0), PT(2,4), PT(3,1), PT(-1,3)) << " "
		 << SegmentsIntersect(PT(0,0), PT(2,4), PT(4,3), PT(0,5)) << " "
		 << SegmentsIntersect(PT(0,0), PT(2,4), PT(2,-1), PT(-2,1)) << " "
		 << SegmentsIntersect(PT(0,0), PT(2,4), PT(5,5), PT(1,7)) << endl;
	cerr << ComputeLineIntersection(PT(0,0),PT(2,4),PT(3,1),PT(-1,3)) << endl;
	cerr << ComputeCircleCenter(PT(-3,4), PT(6,1), PT(4,5)) << endl;
  
	vector<PT> v; v.push_back(PT(0,0)); v.push_back(PT(5,0));
	v.push_back(PT(5,5)); v.push_back(PT(0,5));
  
	// expected: 1 1 1 0 0
	cerr << PointInPolygon(v, PT(2,2)) << " "
		 << PointInPolygon(v, PT(2,0)) << " "
		 << PointInPolygon(v, PT(0,2)) << " "
		 << PointInPolygon(v, PT(5,2)) << " "
		 << PointInPolygon(v, PT(2,5)) << endl;
  
	// expected: 0 1 1 1 1
	cerr << PointOnPolygon(v, PT(2,2)) << " "
		 << PointOnPolygon(v, PT(2,0)) << " "
		 << PointOnPolygon(v, PT(0,2)) << " "
		 << PointOnPolygon(v, PT(5,2)) << " "
		 << PointOnPolygon(v, PT(2,5)) << endl;
  
	// expected: (1,6)/(5,4) (4,5)//(4,5) (5,4)//(4,5) (5,4)
	vector<PT> u = CircleLineIntersection(PT(0,6), PT(2,6), PT(1,1), 5);
	for (int i = 0; i < u.size(); i++) cerr << u[i] << " "; cerr << endl;
	u = CircleLineIntersection(PT(0,9), PT(9,0), PT(1,1), 5);
	for (int i = 0; i < u.size(); i++) cerr << u[i] << " "; cerr << endl;
	u = CircleCircleIntersection(PT(1,1), PT(10,10), 5, 5);
	for (int i = 0; i < u.size(); i++) cerr << u[i] << " "; cerr << endl;
	u = CircleCircleIntersection(PT(1,1), PT(8,8), 5, 5);
	for (int i = 0; i < u.size(); i++) cerr << u[i] << " "; cerr << endl;
	u = CircleCircleIntersection(PT(1,1), PT(4.5,4.5), 10, sqrt(2.0)/2.0);
	for (int i = 0; i < u.size(); i++) cerr << u[i] << " "; cerr << endl;
	u = CircleCircleIntersection(PT(1,1), PT(4.5,4.5), 5, sqrt(2.0)/2.0);
	for (int i = 0; i < u.size(); i++) cerr << u[i] << " "; cerr << endl;
  
	// area should be 5.0; centroid should be (1.1666666, 1.166666)
	PT pa[] = {PT(0,0), PT(5,0), PT(1,1), PT(0,5)};
	vector<PT> p(pa, pa+4); PT c = ComputeCentroid(p);
	cerr << "Area: " << ComputeArea(p) << endl;
	cerr << "Centroid: " << c << endl;
}
Example #3
0
int convex_polygon_intersection(
	int n, // n >= 3
	const double *P,
	int m, // m >= 3
	const double *Q,
	int *ni, // on input, size of Pi, on output, numer of points in Pi
	double *Pi // output intersection polygon
){
	int i, j;
	if(n < 3){ return -1; }
	if(NULL == P){ return -2; }
	if(m < 3){ return -3; }
	if(NULL == Q){ return -4; }
	if(NULL == ni){ return -5; }
	if(NULL == Pi){ return -6; }

	// Implementation of:
	// "A new linear algorithm for intersecting convex polygons"
	// Joseph O'Rourke, Chi-Bin Chien, Thomas Olson, and David Naddor
	// Computer Graphics and Image Processing 19, pp. 384-391 (1982)
	
	const int nPi = *ni; *ni = 0;
	
	
	int ip = 1, iq = 1;
	int ipp = 0, iqp = 0; // prev of ip and iq
	char inside = ' ';
	// record first intersection
	int first_xsected = 0;
	int ipf = n, iqf = m;
	int first_iter = 0;
	
	int Pi_full = 0;
	int iter;

	// First, a bounding box check
	{
		int iP_x_min = 0, iP_x_max = 0, iP_y_min = 0, iP_y_max = 0;
		int iQ_x_min = 0, iQ_x_max = 0, iQ_y_min = 0, iQ_y_max = 0;
		for(i = 1; i < n; ++i){
			if(P[2*i+0] < P[2*iP_x_min+0]){ iP_x_min = i; }
			if(P[2*i+1] < P[2*iP_y_min+1]){ iP_y_min = i; }
			if(P[2*i+0] > P[2*iP_x_max+0]){ iP_x_max = i; }
			if(P[2*i+1] > P[2*iP_y_max+1]){ iP_y_max = i; }
		}
		for(i = 1; i < m; ++i){
			if(Q[2*i+0] < Q[2*iQ_x_min+0]){ iQ_x_min = i; }
			if(Q[2*i+1] < Q[2*iQ_y_min+1]){ iQ_y_min = i; }
			if(Q[2*i+0] > Q[2*iQ_x_max+0]){ iQ_x_max = i; }
			if(Q[2*i+1] > Q[2*iQ_y_max+1]){ iQ_y_max = i; }
		}
		if(
			( Q[2*iQ_x_min+0] > P[2*iP_x_max+0] ) ||
			( P[2*iP_x_min+0] > Q[2*iQ_x_max+0] ) ||
			( Q[2*iQ_y_min+1] > P[2*iP_y_max+1] ) ||
			( P[2*iP_y_min+1] > Q[2*iQ_y_max+1] )
		){ return 0; }
	}

	for(iter = 0; iter <= 2*(m+n); ++iter){
//fprintf(stderr, "iter %d, ip = %d, iq = %d, inside = %c\n", iter, ip, iq, inside);
		double xp[2];
		if(SegmentsIntersect(&P[2*ipp],&P[2*ip],&Q[2*iqp],&Q[2*iq],xp, NULL)){
//fprintf(stderr, " xsect! %f,%f %f,%f %f,%f %f,%f\n", P[2*ipp+0],P[2*ipp+1],P[2*ip+0],P[2*ip+1],Q[2*iqp+0],Q[2*iqp+1],Q[2*iq+0],Q[2*iq+1]);
			if(first_xsected && first_iter != iter-1){ // if the first intersection was NOT found during the previous iteration
				if(ip == ipf && iq == iqf){ break; } // if this intersection is the same as the first intersection
			}
			if(*ni >= nPi){ Pi_full = 1; }
			if(!Pi_full){ Pi[2*(*ni)+0] = xp[0]; Pi[2*(*ni)+1] = xp[1]; (*ni)++; }
//fprintf(stderr, "  Adding %f,%f\n", Pi[2*((*ni)-1)+0], Pi[2*((*ni)-1)+1]);
			if(LeftTurn(&Q[2*iqp],&Q[2*iq],&P[2*ip]) >= 0){
				inside = 'P';
			}else{ inside = 'Q'; }
			
			if(!first_xsected){
				first_xsected = 1;
				ipf = ip; iqf = iq;
				first_iter = iter;
			}
		}
		xp[0] = P[2*ip+0] + (Q[2*iq+0] - P[2*ipp+0]);
		xp[1] = P[2*ip+1] + (Q[2*iq+1] - P[2*ipp+1]);
		if(LeftTurn(&Q[2*iqp],&Q[2*iq],xp)/*Cross(Q[2*iq]-Q[2*iqp],P[2*ip]-P[2*ipp])*/ >= 0){
			if(LeftTurn(&Q[2*iqp],&Q[2*iq],&P[2*ip]) >= 0){ // advance Q
				if(inside == 'Q'){
					if(*ni >= nPi){ Pi_full = 1; }
					if(!Pi_full){ Pi[2*(*ni)+0] = Q[2*iq+0]; Pi[2*(*ni)+1] = Q[2*iq+1]; (*ni)++; }
				}
				iqp = iq;
				iq = (iq+1)%m;
			}else{ // advance P
				if(inside == 'P'){
					if(*ni >= nPi){ Pi_full = 1; }
					if(!Pi_full){ Pi[2*(*ni)+0] = P[2*ip+0]; Pi[2*(*ni)+1] = P[2*ip+1]; (*ni)++; }
				}
				ipp = ip;
				ip = (ip+1)%n;
			}
		}else{
			if(LeftTurn(&P[2*ipp],&P[2*ip],&Q[2*iq]) >= 0){ // advance P
				if(inside == 'P'){
					if(*ni >= nPi){ Pi_full = 1; }
					if(!Pi_full){ Pi[2*(*ni)+0] = P[2*ip+0]; Pi[2*(*ni)+1] = P[2*ip+1]; (*ni)++; }
				}
				ipp = ip;
				ip = (ip+1)%n;
			}else{ // advance Q
				if(inside == 'Q'){
					if(*ni >= nPi){ Pi_full = 1; }
					if(!Pi_full){ Pi[2*(*ni)+0] = Q[2*iq+0]; Pi[2*(*ni)+1] = Q[2*iq+1]; (*ni)++; }
				}
				iqp = iq;
				iq = (iq+1)%m;
			}
		}
	}
	// At this point, either P in Q, Q in P, or they don't intersect
	if(*ni == 0){
		int flag = 1;
		for(j = 0; j < n; ++j){ // really we only need to check j == 0, but due to degeneracy, it is safest to check all
			for(i = 0; i < m; ++i){
				if(LeftTurn(&Q[2*i],&Q[2*((i+1)%m)], &P[2*j]) < 0){
					flag = 0; j = n+1; break;
				}
			}
		}
		if(flag){ // P in Q
			if(*ni+n >= nPi){ Pi_full = 1; }
			if(!Pi_full){
				for(i = 0; i < n; ++i){
					Pi[2*(*ni)+0] = P[2*i+0]; Pi[2*(*ni)+1] = P[2*i+1]; (*ni)++;
				}
				return 1;
			}
		}else{
			flag = 1;
			for(j = 0; j < m; ++j){ // really we only need to check j == 0, but due to degeneracy, it is safest to check all
				for(i = 0; i < n; ++i){
					if(LeftTurn(&P[2*i],&P[2*((i+1)%n)],&Q[2*j]) < 0){
						flag = 0; j = m+1; break;
					}
				}
			}
			if(flag){ // Q in P
				if(*ni+m >= nPi){ Pi_full = 1; }
				if(!Pi_full){
					for(i = 0; i < m; ++i){
						Pi[2*(*ni)+0] = Q[2*i+0]; Pi[2*(*ni)+1] = Q[2*i+1]; (*ni)++;
					}
					return 2;
				}
			}
		}
	}
	if(Pi_full){
		return -10;
	}else{
		return 0;
	}
}