Vector<Vector<Vector2> > Geometry::decompose_polygon_in_convex(Vector<Point2> polygon) { Vector<Vector<Vector2> > decomp; List<TriangulatorPoly> in_poly, out_poly; TriangulatorPoly inp; inp.Init(polygon.size()); for (int i = 0; i < polygon.size(); i++) { inp.GetPoint(i) = polygon[i]; } inp.SetOrientation(TRIANGULATOR_CCW); in_poly.push_back(inp); TriangulatorPartition tpart; if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { //failed! ERR_PRINT("Convex decomposing failed!"); return decomp; } decomp.resize(out_poly.size()); int idx = 0; for (List<TriangulatorPoly>::Element *I = out_poly.front(); I; I = I->next()) { TriangulatorPoly &tp = I->get(); decomp.write[idx].resize(tp.GetNumPoints()); for (int i = 0; i < tp.GetNumPoints(); i++) { decomp.write[idx].write[i] = tp.GetPoint(i); } idx++; } return decomp; }
Vector< Vector<Vector2> > CollisionPolygon2D::_decompose_in_convex() { Vector< Vector<Vector2> > decomp; #if 0 //fast but imprecise triangulator, gave us problems decomp = Geometry::decompose_polygon(polygon); #else List<TriangulatorPoly> in_poly,out_poly; TriangulatorPoly inp; inp.Init(polygon.size()); for(int i=0;i<polygon.size();i++) { inp.GetPoint(i)=polygon[i]; } inp.SetOrientation(TRIANGULATOR_CCW); in_poly.push_back(inp); TriangulatorPartition tpart; if (tpart.ConvexPartition_HM(&in_poly,&out_poly)==0) { //failed! ERR_PRINT("Convex decomposing failed!"); return decomp; } decomp.resize(out_poly.size()); int idx=0; for(List<TriangulatorPoly>::Element*I = out_poly.front();I;I=I->next()) { TriangulatorPoly& tp = I->get(); decomp[idx].resize(tp.GetNumPoints()); for(int i=0;i<tp.GetNumPoints();i++) { decomp[idx][i]=tp.GetPoint(i); } idx++; } #endif return decomp; }
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); }