void Quad_ResizeSide4(Point2 corners[4], int side, const Vector2& move, bool symetric) { Point2 ends1 = Segment2(corners[0],corners[3]).midpoint(0.5); Point2 ends2 = Segment2(corners[1],corners[2]).midpoint(0.5); Point2 side1 = Segment2(corners[0],corners[1]).midpoint(0.5); Point2 side2 = Segment2(corners[2],corners[3]).midpoint(0.5); Vector2 dir; switch(side) { case 0: dir = Vector2(side2,side1); break; case 1: dir = Vector2(ends1,ends2); break; case 2: dir = Vector2(side1,side2); break; case 3: dir = Vector2(ends2,ends1); break; } dir.normalize(); Vector2 real_move = dir.projection(move); corners[side] += real_move; corners[(side+1)%4] += real_move; if (symetric) { corners[(side+2)%4] -= real_move; corners[(side+3)%4] -= real_move; } }
void Quad_4to2(const Point2 corners[4], Point2 ends[2], double& width_mtr) { ends[0] = Segment2(corners[0],corners[3]).midpoint(0.5); ends[1] = Segment2(corners[1],corners[2]).midpoint(0.5); Point2 side1 = Segment2(corners[0],corners[1]).midpoint(0.5); Point2 side2 = Segment2(corners[2],corners[3]).midpoint(0.5); width_mtr = sqrt(VectorLLToMeters(Segment2(side1,side2).midpoint(),Vector2(side1,side2)).squared_length()); }
void Quad_4to1(const Point2 corners[4], Point2& ctr, double& heading, double& len_mtr, double& width_mtr) { Point2 ends1 = Segment2(corners[0],corners[3]).midpoint(0.5); Point2 ends2 = Segment2(corners[1],corners[2]).midpoint(0.5); Point2 side1 = Segment2(corners[0],corners[1]).midpoint(0.5); Point2 side2 = Segment2(corners[2],corners[3]).midpoint(0.5); ctr.x_ = (corners[0].x() + corners[1].x() + corners[2].x() + corners[3].x()) * 0.25; ctr.y_ = (corners[0].y() + corners[1].y() + corners[2].y() + corners[3].y()) * 0.25; heading = VectorDegs2NorthHeading(ctr,ends1,Vector2(ends1,ends2)); width_mtr = sqrt(VectorLLToMeters(ctr,Vector2(side1, side2)).squared_length()); len_mtr = sqrt(VectorLLToMeters(ctr,Vector2(ends1, ends2)).squared_length()); }
bool ConvexHull2::checkEdgeIntersection(const Segment2 &seg) const { if ( vertices.size() < 2 ) { return false; } else if ( vertices.size() == 2 ) { return Segment2( vertices.front(), vertices.back() ).intersects( seg ); } else { int iPrev = vertices.size() - 1; for (int i = 0; i < vertices.size(); i++) { Segment2 edge( vertices[iPrev], vertices[i] ); if ( edge.intersects( seg ) ) { return true; } iPrev = i; } return false; } }
double ConvexHull2::sqrDistanceTo(const Point2 &point) const { if ( contains( point ) ) { return 0.0; } else { double sqrDist = Segment2( vertices.back(), vertices.front() ).sqrDistanceTo( point ); for (int i = 1; i < vertices.size(); i++) { double d2 = Segment2( vertices[i-1], vertices[i] ).sqrDistanceTo( point ); sqrDist = std::min( sqrDist, d2 ); } return sqrDist; } }
// Find Coarse Edges list<CVertex> CMeshCreation::InitPolygon(list<CVertex> pList) { mEdgeLength = 0.05f; CVertex st = *pList.begin(); dt.insert(Point2(st.mPos[0], st.mPos[1])); CVertex ed; m2DMesh.mVertexList.push_back(st); for (list<CVertex>::iterator it = pList.begin(); it != pList.end(); it++) { ed = *it; float len = (ed.mPos[0] - st.mPos[0])*(ed.mPos[0] - st.mPos[0]) + (ed.mPos[1] - st.mPos[1])*(ed.mPos[1] - st.mPos[1]); if (len > mEdgeLength*mEdgeLength) { m2DMesh.mVertexList.push_back(CVertex(ed)); m2DMesh.mEdgeList.push_back(CEdge(m2DMesh.mVertexList.size() - 1, m2DMesh.mVertexList.size())); Point2 p0(st.mPos[0], st.mPos[1]); Point2 p1(ed.mPos[0], ed.mPos[1]); dt.insert(p1); vSegments.push_back(Segment2(p0, p1)); st = ed; } } // st + ed st = *pList.begin(); ed = m2DMesh.mVertexList.back(); m2DMesh.mVertexList.push_back(st); Point2 p0(st.mPos[0], st.mPos[1]); Point2 p1(ed.mPos[0], ed.mPos[1]); //dt.insert(p0); vSegments.push_back(Segment2(p1, p0)); return m2DMesh.mVertexList; }
void customVisualization(Zone2* pZone, const std::string& name) { // Create a Visualizer2 object with the output filename "example5.ps" Visualizer2 vis(name); #if 1 // Extract the triangles of the zone std::vector<Triangle2*> vTriangles; pZone->getTriangles(vTriangles); std::cout << "The zone consists of " << vTriangles.size() << " triangles" << std::endl; // Draw the zone triangles in red for (std::vector<Triangle2*>::iterator it(vTriangles.begin()); it != vTriangles.end(); ++it) { vis.addObject(**it, Color(1, 0, 0, 0.01, true)); // true means it is the fill color } // Draw the borders of the zone triangles for (std::vector<Triangle2*>::iterator it(vTriangles.begin()); it != vTriangles.end(); ++it) { vis.addObject(**it, Color(0, 0, 0, 0.01, false)); } #endif #if 0 // Retrieve the triangles of the triangulation. Draw them in black std::vector<Triangle2*> vAllDelaunayTriangles; dt.getTrianglePointers(vAllDelaunayTriangles); for (std::vector<Triangle2*>::iterator it = vAllDelaunayTriangles.begin(); it != vAllDelaunayTriangles.end(); ++it) { Triangle2* t(*it); Point2* p0 = t->getCorner(0); Point2* p1 = t->getCorner(1); Point2* p2 = t->getCorner(2); vis.addObject(Segment2(*p0, *p1), Color(1, 0, 0, 0.01)); vis.addObject(Segment2(*p1, *p2), Color(1, 0, 0, 0.01)); vis.addObject(Segment2(*p2, *p0), Color(1, 0, 0, 0.01)); } #endif // Finally, write the postscript file to disk! vis.writeFile(); }
bool ConvexHull2::intersects(const BBox2 &box) const { int vertI = vertices.size() - 1; for (int vertJ = 0; vertJ < vertices.size(); vertJ++) { if ( box.contains( vertices[vertI] ) || box.intersects( Segment2( vertices[vertI], vertices[vertJ] ) ) ) { return true; } vertI = vertJ; } return false; }
bool build_convex_polygon( Pmwx::Ccb_halfedge_circulator ccb, vector<pair<Pmwx::Halfedge_handle, Pmwx::Halfedge_handle> >& sides, const CoordTranslator2& trans, Polygon2& metric_bounds, double max_err_mtrs, double min_side_len) { double e_sq = max_err_mtrs*max_err_mtrs; sides.clear(); metric_bounds.clear(); Pmwx::Ccb_halfedge_circulator circ(ccb); // Bbox2 bounds; // // do { // bounds += cgal2ben(circ->source()->point()); // } while (++circ != ccb); Pmwx::Ccb_halfedge_circulator start,next; start = ccb; do { --start; if(!sides_can_merge(start,ccb)) break; if(!within_err_metric(start,ccb,trans,e_sq)) break; } while(start != ccb); ++start; // now we can go around. circ = start; //int ne = count_circulator(start); //printf("Poly has %d sides.\n", ne); do { Pmwx::Ccb_halfedge_circulator stop(circ); do { ++stop; } while(sides_can_merge(circ,stop) && within_err_metric(circ,stop,trans,e_sq) && stop != start); --stop; //printf("Pushing side of %d, %d\n", circulator_distance_to(start, circ),circulator_distance_to(start,stop)); sides.push_back(pair<Pmwx::Halfedge_handle,Pmwx::Halfedge_handle>(circ, stop)); ++stop; circ = stop; } while(circ != start); if(sides.size() < 3) { //debug_mesh_point(bounds.centroid(),1,1,1); return false; } int i, j, k; vector<Segment2> msides; for(i = 0; i < sides.size(); ++i) { j = (i + 1) % sides.size(); DebugAssert(sides[i].second->target() == sides[j].first->source()); msides.push_back(Segment2( trans.Forward(cgal2ben(sides[i].first->source()->point())), trans.Forward(cgal2ben(sides[i].second->target()->point())))); } vector<Segment2> debug(msides); for(i = 0; i < sides.size(); ++i) { j = (i + 1) % sides.size(); Vector2 v1(msides[i].p1,msides[i].p2); Vector2 v2(msides[j].p1,msides[j].p2); v1.normalize(); v2.normalize(); if(v1.dot(v2) > 0.9998 || !v1.left_turn(v2)) { //debug_mesh_point(trans.Reverse(msides[i].p2),1,0,0); return false; } double w = width_for_he(sides[i].first); if(w) { v1 = v1.perpendicular_ccw(); v1 *= w; msides[i].p1 += v1; msides[i].p2 += v1; } } for(j = 0; j < sides.size(); ++j) { i = (j + sides.size() - 1) % sides.size(); Line2 li(msides[i]), lj(msides[j]); Point2 p; if(!li.intersect(lj,p)) { Assert(!"Failure to intersect.\n"); return false; } metric_bounds.push_back(p); } for(i = 0; i < metric_bounds.size(); ++i) { j = (i + 1) % metric_bounds.size(); k = (i + 2) % metric_bounds.size(); if(metric_bounds.side(i).squared_length() < (min_side_len*min_side_len)) { //debug_mesh_line(trans.Reverse(metric_bounds.side(i).p1),trans.Reverse(metric_bounds.side(i).p2),1,1,0,1,1,0); return false; } if(!left_turn(metric_bounds[i],metric_bounds[j],metric_bounds[k])) { //debug_mesh_point(trans.Reverse(metric_bounds[j]),1,1,0); return false; } if(Vector2(msides[i].p1,msides[i].p2).dot(Vector2(metric_bounds[i],metric_bounds[j])) < 0.0) { //debug_mesh_line(trans.Reverse(msides[i].p1),trans.Reverse(msides[i].p2),1,0,0,1,0,0); return false; } } DebugAssert(metric_bounds.size() == msides.size()); DebugAssert(msides.size() == sides.size()); return true; }
// This routine tries to find the 'grain' of a block by a weighting of dot // products relative to all sides. A few notes: // 1. It tries to first run wiht a handy-cap to take only street-level roads. // It then tries again if the filter is too harsh. // 2. It does an intentionally bad job when there are a huge number of sides // since such high-count polygons aren't sane AGB candidates. // 3. It ALWAYS returns some answer, no matter how goofy the polygon. void find_major_axis(vector<block_pt>& pts, Segment2 * out_segment, Vector2 * out_major, Vector2 * out_minor, double * bounds) { double best_v = -1.0; Vector2 temp_a, temp_b; double bounds_temp[4]; if(out_major == NULL) out_major = &temp_a; if(out_minor == NULL) out_minor = &temp_b; if(bounds == NULL) bounds = bounds_temp; bool elev_ok = false; for(int tries = 0; tries < 2; ++tries) { for(int i = 0; i < pts.size(); ++i) if(elev_ok || ground_road_access_for_he(pts[i].orig)) { int j = (i + 1) % pts.size(); Vector2 v_a(pts[i].loc,pts[j].loc); v_a.normalize(); Vector2 v_b(v_a.perpendicular_ccw()); double total = 0.0; int max_k = min(pts.size(),PTS_LIM); for(int k = 0; k < max_k; ++k) { int l = (k + 1) % pts.size(); Vector2 s(pts[k].loc,pts[l].loc); total += max(fabs(v_a.dot(s)),fabs(v_b.dot(s))); } if(total >= best_v) { best_v = total; if(out_segment) *out_segment = Segment2(pts[i].loc,pts[j].loc); *out_major = v_a; *out_minor = v_b; } } if(best_v != -1) break; elev_ok = true; } { int longest = -1; double corr_len = -1; for(int i = 0; i < pts.size(); ++i) if(/*elev_ok ||*/ ground_road_access_for_he(pts[i].orig)) { int j = (i + 1) % pts.size(); Vector2 this_side(pts[i].loc,pts[j].loc); double len = this_side.normalize(); double my_corr = fltmax2(fabs(this_side.dot(*out_major)), fabs(this_side.dot(*out_minor))); if(my_corr > 0.996194698091746) { my_corr *= len; if(my_corr > corr_len) { longest = i; corr_len = my_corr; } } } if(longest >= 0) { int i = longest; int j = (longest + 1) % pts.size(); Vector2 v_a(pts[i].loc,pts[j].loc); v_a.normalize(); Vector2 v_b(v_a.perpendicular_ccw()); if(out_segment) *out_segment = Segment2(pts[i].loc,pts[j].loc); *out_major = v_a; *out_minor = v_b; } } bounds[2] = bounds[0] = out_major->dot(Vector2(pts[0].loc)); bounds[3] = bounds[1] = out_minor->dot(Vector2(pts[0].loc)); for(int n = 1; n < pts.size(); ++n) { double ca = out_major->dot(Vector2(pts[n].loc)); double cb = out_minor->dot(Vector2(pts[n].loc)); bounds[0] = min(bounds[0],ca); bounds[1] = min(bounds[1],cb); bounds[2] = max(bounds[2],ca); bounds[3] = max(bounds[3],cb); } // if(fabs(bounds[3] - bounds[1]) > fabs(bounds[2] - bounds[0])) // { // *out_major = out_major->perpendicular_ccw(); // *out_minor = out_minor->perpendicular_ccw(); // // bounds[2] = bounds[0] = out_major->dot(Vector2(pts[0].loc)); // bounds[3] = bounds[1] = out_minor->dot(Vector2(pts[0].loc)); // for(int n = 1; n < pts.size(); ++n) // { // double ca = out_major->dot(Vector2(pts[n].loc)); // double cb = out_minor->dot(Vector2(pts[n].loc)); // bounds[0] = min(bounds[0],ca); // bounds[1] = min(bounds[1],cb); // bounds[2] = max(bounds[2],ca); // bounds[3] = max(bounds[3],cb); // } // // } }
vector<vector<Point> > Resampling(vector<Point>* input_contour, vector<Point>* refer_point) { int i,j; int size = (*input_contour).size(); Point temp; Point Head = (*refer_point)[0]; Point Left_foot = (*refer_point)[1]; Point Right_foot = (*refer_point)[2]; int Head_num=0,Right_foot_num=0,Left_foot_num=0; vector<Point> Head_start_contour(size); int Seg1_length = 0; int Seg2_length = 0; int Seg3_length = 0; int Seg1_sample_point=15; int Seg2_sample_point=10; int Seg3_sample_point=15; for(i=0;i<size;i++) { temp = (*input_contour)[i]; if(temp==Head){Head_num = i;} else if(temp==Right_foot){Right_foot_num=i;} else if(temp==Left_foot){Left_foot_num=i;} else{;}; } if(Head_num > Right_foot_num) { Seg2_length = Right_foot_num - Left_foot_num; Seg3_length = Head_num - Right_foot_num; for(j=Head_num;j<size;j++){Head_start_contour[j-Head_num] = (*input_contour)[j];} for(j=0;j<Head_num;j++){Head_start_contour[j+(size-Head_num)] = (*input_contour)[j];} Right_foot_num = Right_foot_num + (size - Head_num); Left_foot_num = Left_foot_num + (size - Head_num); Head_num = 0; Seg1_length = Left_foot_num; } else if(Head_num < Right_foot_num) { Seg1_length = Left_foot_num - Head_num; Seg2_length = Right_foot_num - Left_foot_num; for(j=Head_num;j<size;j++){Head_start_contour[j-Head_num] = (*input_contour)[j];} for(j=0;j<Head_num;j++){Head_start_contour[j+(size-Head_num)] = (*input_contour)[j];} Right_foot_num = Right_foot_num - Head_num; Left_foot_num = Left_foot_num - Head_num; Head_num = 0; Seg3_length = size - Right_foot_num; } double Seg1_inter_length = ((double)Seg1_length/(double)Seg1_sample_point); double Seg2_inter_length = ((double)Seg2_length/(double)Seg2_sample_point); double Seg3_inter_length = ((double)Seg3_length/(double)Seg3_sample_point); int Whole_point_num = Seg1_sample_point + Seg2_sample_point + Seg3_sample_point; int index1=0,index2=0,index3=0; vector<Point> Segment1(Seg1_sample_point); vector<Point> Segment2(Seg2_sample_point); vector<Point> Segment3(Seg3_sample_point); vector<vector<Point> > result; int k; for(k=0;k<Seg1_sample_point;k++) { index1 = (int)k*Seg1_inter_length; Segment1[k] = Head_start_contour[index1]; temp = Segment1[k]; //cout << index1 << ":" << temp << endl; } for(k=0;k<Seg2_sample_point;k++) { index2 = Seg1_length + (int)k*Seg2_inter_length; Segment2[k] = Head_start_contour[index2]; temp = Segment2[k]; //cout << index2 << ":" << temp << endl; } for(k=0;k<Seg3_sample_point;k++) { index3 = (Seg1_length+Seg2_length) + (int)k*Seg3_inter_length; Segment3[k] = Head_start_contour[index3]; temp = Segment3[k]; //cout << index3 << ":" << temp << endl; } result.push_back(Segment1); result.push_back(Segment2); result.push_back(Segment3); return result; }
{} Point2<T> const& operator[](int i) const { return reinterpret_cast<Point2<T> const*>(this)[i]; } Point2<T>& operator[](int i) { return reinterpret_cast<Point2<T>*>(this)[i]; } }; template <typename T> Segment2<T> const Segment2<T>::NOTHING = Segment2( Point2<T>(+inf(), +inf()), Point2<T>(-inf(), -inf()) ); template <typename T> Segment2<T> const Segment2<T>::EVERYTHING = Segment2( Point2<T>(-inf(), -inf()), Point2<T>(+inf(), +inf()) ); typedef Segment2<int> Segment2i; typedef Segment2<float> Segment2f; template <typename T> Point2<T> center(Segment2<T> const& segment) { return Point2<T>( (segment.min.x + segment.max.x) / 2.0f,
// Determine the 'side' of @point Side ConvexHull2::side(const Point2 &point) const { if ( vertices.size() == 0 ) { return SIDE_NEGATIVE; } else if ( vertices.size() == 1 ) { return point == vertices.front() ? SIDE_ON : SIDE_NEGATIVE; } else if ( vertices.size() == 2 ) { return Segment2( vertices[0], vertices[1] ).on( point ) ? SIDE_ON : SIDE_NEGATIVE; } else { int rightCrossings = 0; int leftCrossings = 0; int iPrev = vertices.size() - 1; for (int i = 0; i < vertices.size(); i++) { //@point is inside if it lies on a vertex if ( point == vertices[i] ) { return SIDE_ON; } //check if the edge at position @iPrev straddles the horizontal axis //that passes through @p bool rightStraddle = ( vertices[i].y > point.y ) != ( vertices[iPrev].y > point.y ); bool leftStraddle = ( vertices[i].y < point.y ) != ( vertices[iPrev].y < point.y ); if ( rightStraddle || leftStraddle ) { double areax2 = Point2::areaOfTrianglex2( vertices[iPrev], vertices[i], point ); bool edgePointsUp = vertices[i].y > vertices[iPrev].y; bool pOnLeft = edgePointsUp ? areax2 > 0.0 : areax2 < 0.0; bool pOnRight = edgePointsUp ? areax2 < 0.0 : areax2 > 0.0; if ( rightStraddle && pOnLeft ) { //right straddle AND @p on left of the edge; intersection between //the edge and the horizontal axis passing through @p lies //to the right of @p rightCrossings++; } if ( leftStraddle && pOnRight ) { //left straddle AND @p on right of the edge; intesection between //the edge and the horizontal axis passing through @o lies //to the left of @p leftCrossings++; } } iPrev = i; } //@p is on an edge if left and right cross counts do not have the //same parity if ( ( rightCrossings % 2 ) != ( leftCrossings %2 ) ) { //@p is inside the boundary return SIDE_ON; } //@p is inside if the number of crossings is odd if ( ( rightCrossings % 2 ) == 1 ) { return SIDE_POSITIVE; } else { return SIDE_NEGATIVE; } } }
void ConvexHull2::addPoint(const Point2 &p) { if ( vertices.size() < 2 ) { if ( !vertices.contains( p ) ) { vertices.push_back( p ); } } else if ( vertices.size() == 2 ) { Segment2 seg( vertices[0], vertices[1] ); if ( seg.onLeft( p ) ) { vertices.push_back( p ); } else if ( seg.onRight( p ) ) { vertices.insert( 1, p ); } } else { // Find the first edge for which @p is on the positive side of the line defined by the edge int firstOnOrLeft = -1; for (int vertI = 0; vertI < vertices.size(); vertI++) { int vertJ = nextIndex( vertI, vertices.size() ); Segment2 seg( vertices[vertI], vertices[vertJ] ); if ( seg.onOrLeft( p ) ) { firstOnOrLeft = vertI; break; } } gs_assert( firstOnOrLeft != -1, "ConvexHull2::addPoint(): could not find first segment which has @p to the left\n" ); // Starting with at the edge after the first edge for which @p is on the positive side (found in previous step), // find the first edge for which @p is on the negative side int vertI = nextIndex( firstOnOrLeft, vertices.size() ); int firstOnRight = -1; for (int i = 0; i < vertices.size(); i++) { int vertJ = nextIndex( vertI, vertices.size() ); Segment2 seg( vertices[vertI], vertices[vertJ] ); if ( seg.onRight( p ) ) { firstOnRight = vertI; } vertI = vertJ; } // If @firstOnRight is -1, then @p is on the left of all edges, meaning that it is inside the hull; do nothing in this case if ( firstOnRight != -1 ) { // Starting the the first edge for which @p is on the negative side (found in previous step), look at the next // edge, and see if @p is on the negative side. If so, remove the vertex shared by both edges. int vertI = firstOnRight; int vertJ = nextIndex( vertI, vertices.size() ); int vertK = nextIndex( vertJ, vertices.size() ); Segment2 segB( vertices[vertJ], vertices[vertK] ); while ( segB.onRight( p ) ) { vertices.remove( vertJ ); if ( vertJ < vertI ) { vertI--; } vertJ = nextIndex( vertI, vertices.size() ); vertK = nextIndex( vertJ, vertices.size() ); segB = Segment2( vertices[vertJ], vertices[vertK] ); } // Insert @p after @vertI vertices.insert( vertI + 1, p ); } } }