void NavigationPolygon::make_polygons_from_outlines() { List<TriangulatorPoly> in_poly,out_poly; Vector2 outside_point(-1e10,-1e10); for(int i=0; i<outlines.size(); i++) { DVector<Vector2> ol = outlines[i]; int olsize = ol.size(); if (olsize<3) continue; DVector<Vector2>::Read r=ol.read(); for(int j=0; j<olsize; j++) { outside_point.x = MAX( r[j].x, outside_point.x ); outside_point.y = MAX( r[j].y, outside_point.y ); } } outside_point+=Vector2(0.7239784,0.819238); //avoid precision issues for(int i=0; i<outlines.size(); i++) { DVector<Vector2> ol = outlines[i]; int olsize = ol.size(); if (olsize<3) continue; DVector<Vector2>::Read r=ol.read(); int interscount=0; //test if this is an outer outline for(int k=0; k<outlines.size(); k++) { if (i==k) continue; //no self intersect DVector<Vector2> ol2 = outlines[k]; int olsize2 = ol2.size(); if (olsize2<3) continue; DVector<Vector2>::Read r2=ol2.read(); for(int l=0; l<olsize2; l++) { if (Geometry::segment_intersects_segment_2d(r[0],outside_point,r2[l],r2[(l+1)%olsize2],NULL)) { interscount++; } } } bool outer = (interscount%2)==0; TriangulatorPoly tp; tp.Init(olsize); for(int j=0; j<olsize; j++) { tp[j]=r[j]; } if (outer) tp.SetOrientation(TRIANGULATOR_CCW); else { tp.SetOrientation(TRIANGULATOR_CW); tp.SetHole(true); } in_poly.push_back(tp); } TriangulatorPartition tpart; if (tpart.ConvexPartition_HM(&in_poly,&out_poly)==0) { //failed! print_line("convex partition failed!"); return; } polygons.clear(); vertices.resize(0); Map<Vector2,int> points; for(List<TriangulatorPoly>::Element*I = out_poly.front(); I; I=I->next()) { TriangulatorPoly& tp = I->get(); struct Polygon p; for(int i=0; i<tp.GetNumPoints(); i++) { Map<Vector2,int>::Element *E=points.find(tp[i]); if (!E) { E=points.insert(tp[i],vertices.size()); vertices.push_back(tp[i]); } p.indices.push_back(E->get()); } polygons.push_back(p); } emit_signal(CoreStringNames::get_singleton()->changed); }