int ccw_cmp(const void *a, const void *b){ Point *p1 = (Point *)a; Point *p2 = (Point *)b; if (ccw(start_p, *p1, *p2) == CCW) return -1; if (ccw(start_p, *p2, *p1) == CCW) return 1; return 0; }
bool CLine2d::intersects(const CLine2d& otherLine) const { bool retval = false; if (getExtent().intersects(otherLine.getExtent())) { int ccw0 = ccw(otherLine.m_p0) * ccw(otherLine.m_p1); if (ccw0 == 0) { retval = true; } else { int ccw1 = otherLine.ccw(m_p0) * otherLine.ccw(m_p1); if (ccw1 == 0) { retval = true; } else { retval = ((ccw0 < 0) && (ccw1 < 0)); } } } return retval; }
bool intersect( Line line1, Line line2 ) { return (( ccw(line1.p1, line1.p2, line2.p1) * ccw(line1.p1, line1.p2, line2.p2)) <= 0) && (( ccw(line2.p1, line2.p2, line1.p1) * ccw(line2.p1, line2.p2, line1.p2)) <= 0); }
int main() { srand(time(NULL)); //points = (point*) calloc(points_count, sizeof(struct point)); struct point * hull = (point*) calloc(points_count, sizeof(struct point)); rand_points(&points, points_count, dimxy); qsort(points, points_count, sizeof(struct point), cmp_points); int hind = 0; for(int i=0; i < points_count; i++) { while (hind >= 2 && !ccw(hull[hind-2], hull[hind-1], points[i])) {hind--;} hull[hind++] = points[i]; } for(int i = points_count-2, lim = hind+1; i >= 0; --i) { while (hind >= lim && !ccw(hull[hind-2], hull[hind-1], points[i])) {hind--;} hull[hind++] = points[i]; } /*printf("hull:"); for (int i=0; i < hind; i++) { printf("(%d,%d),", hull[i].x, hull[i].y); } printf("\n");*/ void * r = realloc(hull, sizeof(struct point) * hind); int ret = plot(points, points_count, hull, hind); free(points); }
/** * compute the convex hull of a collection of Points * * @param points the points as a Vector2 array. * @param pointsLength the number of vertices of the polygon. * @param retPoly pre allocated array of floats to put the vertices * @return the number of points in the polygon 0 if no intersection */ int SpotShadow::hull(Vector2* points, int pointsLength, Vector2* retPoly) { xsort(points, pointsLength); int n = pointsLength; Vector2 lUpper[n]; lUpper[0] = points[0]; lUpper[1] = points[1]; int lUpperSize = 2; for (int i = 2; i < n; i++) { lUpper[lUpperSize] = points[i]; lUpperSize++; while (lUpperSize > 2 && !ccw( lUpper[lUpperSize - 3].x, lUpper[lUpperSize - 3].y, lUpper[lUpperSize - 2].x, lUpper[lUpperSize - 2].y, lUpper[lUpperSize - 1].x, lUpper[lUpperSize - 1].y)) { // Remove the middle point of the three last lUpper[lUpperSize - 2].x = lUpper[lUpperSize - 1].x; lUpper[lUpperSize - 2].y = lUpper[lUpperSize - 1].y; lUpperSize--; } } Vector2 lLower[n]; lLower[0] = points[n - 1]; lLower[1] = points[n - 2]; int lLowerSize = 2; for (int i = n - 3; i >= 0; i--) { lLower[lLowerSize] = points[i]; lLowerSize++; while (lLowerSize > 2 && !ccw( lLower[lLowerSize - 3].x, lLower[lLowerSize - 3].y, lLower[lLowerSize - 2].x, lLower[lLowerSize - 2].y, lLower[lLowerSize - 1].x, lLower[lLowerSize - 1].y)) { // Remove the middle point of the three last lLower[lLowerSize - 2] = lLower[lLowerSize - 1]; lLowerSize--; } } // output points in CW ordering const int total = lUpperSize + lLowerSize - 2; int outIndex = total - 1; for (int i = 0; i < lUpperSize; i++) { retPoly[outIndex] = lUpper[i]; outIndex--; } for (int i = 1; i < lLowerSize - 1; i++) { retPoly[outIndex] = lLower[i]; outIndex--; } // TODO: Add test harness which verify that all the points are inside the hull. return total; }
int intersect(Line l1, Line l2) { // The following expression evaluates true if both endpoints of each line // are on different sides of the other: return ((ccw(l1.p1, l1.p2, l2.p1)*ccw(l1.p1, l1.p2, l2.p2)) <= 0) && ((ccw(l2.p1, l2.p2, l1.p1)*ccw(l2.p1, l2.p2, l1.p2)) <= 0); }
bool Geometry::checkIntersectionOfLines( const Vector2<>& l1p1, const Vector2<>& l1p2, const Vector2<>& l2p1, const Vector2<>& l2p2) { return (((ccw(l1p1, l1p2, l2p1) * ccw(l1p1, l1p2, l2p2)) <= 0) && ((ccw(l2p1, l2p2, l1p1) * ccw(l2p1, l2p2, l1p2)) <= 0)); }
VP ConvexCut(const VP &ps, L l) { VP Q; for (int i = 0; i < (int)ps.size(); i++) { P A = ps[i], B = ps[(i+1)%ps.size()]; if (ccw(l.a, l.b, A) != -1) Q.push_back(A); if (ccw(l.a, l.b, A) * ccw(l.a, l.b, B) < 0) Q.push_back(is_ll((L){A, B}, l)); } return Q; }
// Recursive Delaunay Triangulation Procedure // Contains modifications for axis-switching division. void CDelaunay::build(int lo, int hi, EdgePointer *le, EdgePointer *re, int rows) { EdgePointer a, b, c, ldo, rdi, ldi, rdo, maxx, minx; int split, lowrows; int low, high; SitePointer s1, s2, s3; low = lo; high = hi; if ( low < (high-2) ) { // more than three elements; do recursion minx = sp[low]; maxx = sp[high]; if (rows == 1) { // time to switch axis of division spsorty( sp, low, high); rows = 65536; } lowrows = rows/2; split = low - 1 + (int) (0.5 + ((double)(high-low+1) * ((double)lowrows / (double)rows))); build( low, split, &ldo, &ldi, lowrows ); build( split+1, high, &rdi, &rdo, (rows-lowrows) ); doMerge(&ldo, ldi, rdi, &rdo); while (orig(ldo) != minx) { ldo = rprev(ldo); } while (orig(rdo) != maxx) { rdo = (SitePointer) lprev(rdo); } *le = ldo; *re = rdo; } else if (low >= (high - 1)) { // two or one points a = makeEdge(sp[low], sp[high]); *le = a; *re = (EdgePointer) sym(a); } else { // three points // 3 cases: triangles of 2 orientations, and 3 points on a line a = makeEdge((s1 = sp[low]), (s2 = sp[low+1])); b = makeEdge(s2, (s3 = sp[high])); splice((EdgePointer) sym(a), b); if (ccw(s1, s3, s2)) { c = connectLeft(b, a); *le = (EdgePointer) sym(c); *re = c; } else { *le = a; *re = (EdgePointer) sym(b); if (ccw(s1, s2, s3)) { // not colinear c = connectLeft(b, a); } } } }
// 左側切除 Polygon convex_cut(const Polygon &p, const Line &l){ Polygon res; for(int i = 0; i < p.size(); ++i){ P a = curr(p,i), b = next(p,i); Line tl = Line(a, b); if(ccw(l[0], l[1], a) != -1) res.push_back(a); if(ccw(l[0], l[1], a) * ccw(l[0], l[1], b) < 0) res.push_back(crosspointLL(tl, l)); } return res; }
Polygon convex_hull(vector<Point> ps) { int n = ps.size(), k = 0; sort(begin(ps), end(ps), comp); Polygon ch(2 * n); for (int i = 0; i < n; ch[k++] = ps[i++]) while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k; for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--]) while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k; ch.resize(k - 1); return ch; }
VP ConvexHull(VP ps) { int n = ps.size(); int k = 0; sort(ps.begin(), ps.end()); VP ch(2 * n); for (int i = 0; i < n; ch[k++] = ps[i++]) while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k; for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--]) while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k; ch.resize(k - 1); return ch; }
Polygon convexCut(const Polygon &P, const Line &l) { Polygon Q; for (int i = 0; i < (int)P.size(); i++) { Point A = CURR(P, i), B = NEXT(P, i); if (ccw(l[0], l[1], A) != -1) { Q.push_back(A); } if (ccw(l[0], l[1], A) * ccw(l[0], l[1], B) < 0) { Q.push_back(crosspointSS(Line(A, B), l)); } } return Q; }
bool KarbonCalligraphicShape::flipDetected(const QPointF &p1, const QPointF &p2) { // detect the flip caused by the angle changing 180 degrees // thus detect the boundary crossing int index = pointCount() / 2; QPointF last1 = pointByIndex(KoPathPointIndex(0, index - 1))->point(); QPointF last2 = pointByIndex(KoPathPointIndex(0, index))->point(); int sum1 = std::abs(ccw(p1, p2, last1) + ccw(p1, last2, last1)); int sum2 = std::abs(ccw(p2, p1, last2) + ccw(p2, last1, last2)); // if there was a flip return sum1 < 2 && sum2 < 2; }
double line_segment_distance(L(a,b), L(c,d)) { double x = INFINITY; if (abs(a - b) < EPS && abs(c - d) < EPS) x = abs(a - c); else if (abs(a - b) < EPS) x = abs(a - closest_point(c, d, a, true)); else if (abs(c - d) < EPS) x = abs(c - closest_point(a, b, c, true)); else if ((ccw(a, b, c) < 0) != (ccw(a, b, d) < 0) && (ccw(c, d, a) < 0) != (ccw(c, d, b) < 0)) x = 0; else { x = min(x, abs(a - closest_point(c,d, a, true))); x = min(x, abs(b - closest_point(c,d, b, true))); x = min(x, abs(c - closest_point(a,b, c, true))); x = min(x, abs(d - closest_point(a,b, d, true))); } return x; }
void Cloud::update() { switch (state) { case 1: //delay and cw if (millis () - startTime > _delayTime ) { cw (); state = 2; startTime = millis(); } break; case 2: //check left if (digitalRead (_limitPinL) == 0 || (millis () - startTime > 8000) ) { stop(); state = 3; startTime = millis(); } break; case 3: //delay and ccw if (millis () - startTime > _delayTime ) { state = 4; ccw (); startTime = millis(); } break; case 4: //check right if (digitalRead (_limitPinR) == 0 || (millis () - startTime > 8000) ) { stop (); state = 1; startTime = millis(); } break; } }
int convex_hull(Point *p, int n, Point *hull) { int count, mini, i; start_p.x = p[0].x; start_p.y = p[0].y; for (mini = 0, i = 1; i < n; i++) if ((p[i].y < start_p.y) || (p[i].y == start_p.y && p[i].x < start_p.x)) { start_p = p[i]; mini = i; } p[mini] = p[0]; p[0] = start_p; qsort((p+1), n-1, sizeof(Point), ccw_cmp); count = 0; hull[count] = p[count]; count++; hull[count] = p[count]; count++; for (i = 2; i < n; i++) { while (count > 1 && ccw(hull[count-2], hull[count-1], p[i]) == CW) { count--; } hull[count++] = p[i]; } return count; }
vector<Point *> &convex_hull() { Point mostLeft = points[0]; for (auto &d : points) { if (mostLeft.y > d.y || (mostLeft.y == d.y && mostLeft.x > d.x)) { mostLeft = d; } } gen_angle(mostLeft); sort(points.begin(), points.end()); hull.clear(); for (auto &p : points) { while (hull.size() >= 2 && ccw(*hull[hull.size() - 2], *hull.back(), p) <= 0) { hull.pop_back(); } hull.emplace_back(&p); } return hull; }
int main(void) { Point a, b, c; int a1, a2, a3, a4, a5, a6; int res; while (scanf("%d %d %d %d %d %d", &a1, &a2, &a3, &a4, &a5, &a6) == 6) { a.x = a1; a.y = a2; b.x = a3; b.y = a4; c.x = a5; c.y = a6; res = ccw(a,b,c); if (res == CW) { printf("CW\n"); } else if (res == CCW) { printf("CCW\n"); } else if (res == CNEITHER) { printf("CNEITHER\n"); } else { printf("Help, I am in trouble!\n"); exit(1); } } return 0; }
Polygon convexHull(const Polygon& pol) { if (pol.size() <= 3) return pol; std::vector<Point> points = pol.get_points(); // Find leftmost point size_t p0 = 0; for (size_t i = 1; i < points.size(); ++i) { if (points[i].y < points[p0].y || (points[i].y == points[p0].y && points[i].x < points[p0].x)) p0 = i; } std::swap(points[0], points[p0]); std::sort(++points.begin(), points.end(), CCWSort(points[0])); std::vector<Point> hull(points.size()); hull.resize(points.size()); hull[0]= points[0]; hull[1] = points[1]; hull[2] = points[2]; int hi = 3; for (size_t i = 3; i < points.size(); ++i) { const Point& p = points[i]; for (; hi >= 2 && !ccw(hull[hi-2], hull[hi-1], p); hi--); hull[hi++] = p; } hull.resize(hi); return Polygon(hull); }
int main() { struct Point points[MAX_POINTS]; int numPoints = readPoints(points); //populate the array and get numPoints if(numPoints == 0) return 1; //exit failure struct Point hullPoints[MAX_POINTS]; //sizing is just to be safe struct Point pointOnHull = leftmostPoint(points, numPoints); int i = 0; struct Point endpoint; do { hullPoints[i] = pointOnHull; //use as next pivot endpoint = points[0]; //initial endpoint candidate for(int j = 1; j < numPoints; j++) { if(equal(endpoint,pointOnHull)|| (ccw(hullPoints[i], endpoint, points[j]) > 0)) { endpoint = points[j]; //found greater left turn, update endpoint } } i++; pointOnHull = endpoint; } while(!equal(endpoint,hullPoints[0])); //wrapped around to first hull point printf("Set of points:\n"); displayPoints(points, numPoints); printf("Convex hull:\n"); displayPoints(hullPoints,i); return 0; //success }
/* * Construct a simple polygon by ustilising the sorting step of the Graham scan algorithm. * Given a array of points, and sets this.cell equal to a simple ccw polygon * First select the bottom-leftmost point l then sorts all following points ccw around L * **Ref: J. Erickson, “Lecture: Convex Hulls,” 2008. * Available: www.cs.uiuc.edu/jeffe/teaching/compgeom/notes/01-convexhull.pdf */ void Server::GrahamSort(std::vector<Point> points) { int lpos = 0; Point l = points[lpos]; Point tmp, p1, p2; // Find top-leftmost point for (unsigned int i=1;i<points.size();i++) { if (points[i].x() <= l.x()) { // Second mininum x l = points[i]; lpos = i; } } // Remove l from vector points points.erase(points.begin()+lpos); this->addVertex(l,true); unsigned i; // Sort for (i = 0;i <points.size()-1;i++) { for(unsigned j = i+1; j<points.size(); j++) { p1 = points[i]; p2 = points[j]; if (!ccw(l, points[i], points[j])){ // If not ccw, swap so that it is counter clock wise; tmp = points[i]; points[i] = points[j]; points[j] = tmp; } } this->addVertex(points[i], true); } this->addVertex(points[i],true); }
vector<point> CH(vector<point> P) { // the content of P may be reshuffled int i, j, n = (int)P.size(); if (n <= 3) { if (!(P[0] == P[n-1])) P.push_back(P[0]); // safeguard from corner case return P; // special case, the CH is P itself } // first, find P0 = point with lowest Y and if tie: rightmost X int P0 = 0; for (i = 1; i < n; i++) if (P[i].y < P[P0].y || (P[i].y == P[P0].y && P[i].x > P[P0].x)) P0 = i; point temp = P[0]; P[0] = P[P0]; P[P0] = temp; // swap P[P0] with P[0] // second, sort points by angle w.r.t. pivot P0 pivot = P[0]; // use this global variable as reference sort(++P.begin(), P.end(), angleCmp); // we do not sort P[0] // third, the ccw tests vector<point> S; S.push_back(P[n-1]); S.push_back(P[0]); S.push_back(P[1]); // initial S i = 2; // then, we check the rest while (i < n) { // note: N must be >= 3 for this method to work j = (int)S.size()-1; if (ccw(S[j-1], S[j], P[i])) S.push_back(P[i++]); // left turn, accept else S.pop_back(); } // or pop the top of S until we have a left turn return S; } // return the result
vector<pt> hull(vector<pt> pts) { if(pts.size() <= 1) return pts; vector<pt> ret; int mini = 0; for(int i = 1; i < pts.size(); ++i) if(pts[i] < pts[mini]) mini = i; pivot = pts[mini]; swap(pts[0], pts[mini]); sort(pts.begin() + 1, pts.end(), hull_comp); ret.push_back(pts[0]); ret.push_back(pts[1]); int sz = 2; for(int i = 2; i < pts.size(); ++i) { while(sz >= 2 && ccw(ret[sz-2], ret[sz-1], pts[i]) <= 0) ret.pop_back(), --sz; ret.push_back(pts[i]), ++sz; } return ret; }
//A method that does the jarvis algorithm. Takes a set of points and number of points //in this set that are valid, find the points in this set and add them to convexHull //@param points, the set of points, a subset of these points will be the convex hull //@param numPoints, the number of points in points that are valid //@param convexHull, this will be manipualted from empty to containing the complex hull int jarvis(struct Point points[], struct Point convexHull[],int numPoints) { struct Point pointOnHull=leftmostPoint(points,numPoints); int i=0; struct Point endPoint; do { convexHull[i]=pointOnHull; endPoint=points[0]; for(int j=1; j<numPoints; j++) { if(equal(endPoint,pointOnHull) || (ccw(convexHull[i], endPoint,points[j])>0)) { endPoint=points[j]; } } i++; pointOnHull=endPoint; } while(!equal(endPoint,convexHull[0])); return i; }
void PolygonCollider::PointSearch(std::vector<Vec2> &PointLocate, std::vector<Vec2> &ConvexPoint) { Vec2 P1 = PointLocate[1]; Vec2 P2 = PointLocate[2]; for (unsigned int i = 3; i < PointLocate.size(); i++) { while (ccw(P1, P2, PointLocate[i]) <= 0 && PointLocate[i].angle>0) { ConvexPoint.pop_back(); P2 = ConvexPoint.back(); ConvexPoint.pop_back(); P1 = ConvexPoint.back(); ConvexPoint.push_back(P2); } if (PointLocate[i].angle != 0) { ConvexPoint.push_back(PointLocate[i]); } P2 = ConvexPoint.back(); ConvexPoint.pop_back(); P1 = ConvexPoint.back(); ConvexPoint.push_back(P2); } ConvexPoint.push_back(PointLocate[0]); }
void convex_hull(point in[], int n, polygon *hull) { int i; /* input counter */ int top; /* current hull size */ bool smaller_angle(); if(n <= 3) { /* all points on hull! */ for (i=0; i<n; i++) copy_point(in[i], hull->p[i]); hull->n = n; return; } sort_and_remove_duplicates(in, &n); copy_point(in[0], first_point); qsort(&in[1], n-1, sizeof(point), smaller_angle); copy_point(first_point, hull->p[0]); copy_point(in[1], hull->p[1]); copy_point(first_point, in[n]); /* sentinel to avoid special case */ top = 1; i = 2; while(i <= n) if(!ccw(hull->p[top-1], hull->p[top], in[i])) top--; /* top not on hull */ else { top++; copy_point(in[i], hull->p[top]); i++; } hull->n = top; }
int intersectCS(const circle& c, const line& s) { if (not intersectCL(c, s)) return 0; double a = abs(s.a - c.o); double b = abs(s.b - c.o); if (lt(a, c.r) and lt(b, c.r)) return 0; if (lt(a, c.r) or lt(b, c.r)) return 1; return ccw(s.a, s.b, proj(s, c.o)) ? 0 : 2; }
// Polygon 'subject' can be a polygon of any type. // Polygon 'clip' must be a convex polygon. std::vector<Point2d> sutherland_hodgman(const std::vector<Point2d>& subject, const std::vector<Point2d>& clip) { std::vector<Point2d> in, out; Point2d inter; P2::Line clip_line; P2::Line in_line; // Initialize out = subject; const size_t M = clip.size(); // Loop. for (size_t e2 = 0, e1 = M-1; e2 != M; e1 = e2++) // 'e' like edge of the clip polygon. { in = out; out.clear(); const size_t N = in.size(); for (size_t v2 = 0, v1 = N-1; v2 != N; v1 = v2++) { int ccw1 = ccw(clip[e1], clip[e2], in[v1]); int ccw2 = ccw(clip[e1], clip[e2], in[v2]); if (ccw1 == 1 && ccw2 == 1) out.push_back(in[v2]); else if (ccw1 == 1 && ccw2 == -1) { clip_line = line(clip[e1], clip[e2]); in_line = line(in[v1], in[v2]); if ( intersection(clip_line, in_line, inter) ) out.push_back(inter); } else if (ccw1 == -1 && ccw2 == 1) { clip_line = line(clip[e1], clip[e2]); in_line = line(in[v1], in[v2]); if ( intersection(clip_line, in_line, inter) ) out.push_back(inter); out.push_back(in[v2]); } } } return out; }
vector<point> ConvexHull(vector<point> P){ sort(P.begin(),P.end()); int n = P.size(),k = 0; point H[2*n]; for(int i=0;i<n;++i){ while(k>=2 && !ccw(H[k-2],H[k-1],P[i])) --k; H[k++] = P[i]; } for(int i=n-2,t=k;i>=0;--i){ while(k>t && !ccw(H[k-2],H[k-1],P[i])) --k; H[k++] = P[i]; } return vector<point> (H,H+k); }