#include "precompiled.h" #include "0ad_warning_disable.h" # include # include "sr_box.h" # include "sr_geo2.h" # include "sr_polygon.h" //# define SR_USE_TRACE1 # include "sr_trace.h" //=================================== SrPolygon ================================================= const char* SrPolygon::class_name = "Polygon"; SrPolygon::SrPolygon ( int s, int c ) : SrArray ( s, c ) { _open = 0; } SrPolygon::SrPolygon ( const SrPolygon& p ) : SrArray ( p ) { _open = p._open; } SrPolygon::SrPolygon ( SrVec2* pt, int s, int c ) : SrArray ( pt, s, c ) { _open = 0; } void SrPolygon::set_from_float_array ( const float* pt, int numv ) { if ( numv<0 ) return; size ( numv ); for ( int i=0; i0 if ccw { float sum=0; int i, j; if ( size()<=2 ) return 0; // degenerated polygon with 1 or 2 edges for ( i=0; ip2.y ) { SrVec2 tmp; SR_SWAP(p1,p2); } if ( p1.y>=p.y ) return false; // not intercepting if ( p2.y0 ) { p.set ( radius*sinf(ang), radius*cosf(ang) ); p += center; push ( p ); ang += incang; nvertices--; } _open = 0; } float SrPolygon::perimeter () const { if ( size()<2 ) return 0; int i; float len=0; for ( i=1; imaxlen ) { nsub = (int)(len/maxlen); len = len/(nsub+1); v2 = v2 - v1; v2.len(len); while ( nsub>0 ) { v1+=v2; obsamp.push()=v1; nsub--; } } } take_data ( obsamp ); } void SrPolygon::remove_duplicated_vertices ( float epsilon ) { int i1, i2; SrVec2 v1, v2; epsilon *= epsilon; i1 = 0; while ( i1=size()-2 ) break; i1 = (i+1)%size(); i2 = (i+2)%size(); if ( sr_point_line_dist ( get(i).x, get(i).y, get(i1).x, get(i1).y, get(i2).x, get(i2).y )<=epsilon ) remove(i1); else i++; } } //# define SE_CCW(ax,ay,bx,by,cx,cy) ((ax*by) + (bx*cy) + (cx*ay) - (bx*ay) - (cx*by) - (ax*cy)) //# define VCCW(p1,p2,p3) SE_CCW(p1.x,p1.y,p2.x,p2.y,p3.x,p3.y) static void grow_corner ( const SrVec2& v1, const SrVec2& v2, const SrVec2& v3, float r, float maxang, bool grow, SrPolygon& obs ) { enum MoreOrLessThanPi { LESS_THAN_PI, MORE_THAN_PI }; MoreOrLessThanPi type; SrVec2 vec1, vec2; if ( grow ) type = ccw(v1,v2,v3)>=0? MORE_THAN_PI:LESS_THAN_PI; else type = ccw(v1,v2,v3)>=0? LESS_THAN_PI:MORE_THAN_PI; vec1 = v1-v2; vec1.normalize(); vec2 = v3-v2; vec2.normalize(); // get corner separator points: if ( type==LESS_THAN_PI ) // get the bissector point { float ang = angle_fornormvecs(vec1,vec2) / 2.0f; // angle divided by 2 float sinang = sinf(ang); if ( !grow ) ang=-ang; SrVec2 x (vec1); x.rot ( sinf(ang), cosf(ang) ); x *= r/sinang; x += v2; /* if ( grow ) { type = ccw(v1,x,v3)>0? MORE_THAN_PI:LESS_THAN_PI; if ( type==LESS_THAN_PI ) obs.push().set ( x.x, x.y ); } else { obs.push().set ( x.x, x.y ); } */ obs.push().set ( x.x, x.y ); } else // MORE_THAN_PI { SrVec2 sp1, sp2; sp1.set ( -vec1.y, vec1.x ); // 90 degrees rotation sp2.set ( vec2.y, -vec2.x ); // 90 degrees rotation float f = r; if ( !grow ) { vec1*=-1; vec2*=-1; f=-r; } sp1.len(f); sp2.len(f); sp1 += v2; sp2 += v2; // smooth: obs.push() = sp1; vec1 = sp1-v2; vec1.normalize(); vec2 = sp2-v2; vec2.normalize(); float ang = angle_fornormvecs(vec1,vec2); if ( ang>maxang ) { int nsub = (int)(ang/maxang); float angstep = ang/(nsub+1); if ( !grow ) angstep*=-1; float s=sinf(angstep); float c=cosf(angstep); vec1.len ( r ); while ( nsub-- ) { vec1.rot(s,c); vec2 = v2 + vec1; obs.push() = vec2; } } obs.push() = sp2; } } void SrPolygon::grow ( float radius, float maxangrad ) { if ( radius==0 || size()<2 ) return; const float MIN = SR_TORAD(1); if ( maxangrad0? true:false; if ( !grow ) radius = -radius; int i; if ( _open ) { for ( i=size()-02; i>0; i-- ) push()=get(i); _open=0; grow = true; } else { if ( size()<3 ) return;} SrVec2 v1, v2, v3; SrPolygon obgrow; obgrow.size(size()*2); obgrow.size(0); for ( i=0; i& tris ) const { enum Case { TriangleOk, TriangleIntersects, DisconsiderPoint }; Case c; int a1, a2, a3, b, size; float prec = 0.000001f; //sr_out<3 ) { size = pol.size(); for ( a2=pol.size()-1; a2>=0; a2-- ) { a1 = pol.validate(a2-1); a3 = pol.validate(a2+1); //printf ("%d:\n",a1); if ( ccw ( pol[a1], pol[a2], pol[a3] )<=0 ) continue; // not ccw //printf ("CCW\n"); c = TriangleOk; for ( b=0; b&)p; } SrInput& operator>> ( SrInput& inp, SrPolygon& p ) { inp.get_token(); if ( inp.last_token_type()==SrInput::Name && inp.last_token()=="open" ) p.open ( true ); else inp.unget_token(); return inp >> (SrArray&)p; } //================================ End of File =================================================