00001
00008 #include <blort/Recognizer3D/SPolygon.hh>
00009 #include <blort/Recognizer3D/Geometry.hh>
00010 #include <float.h>
00011 #include <stdio.h>
00012 #include <fstream>
00013 #include <iostream>
00014
00015 namespace P
00016 {
00017
00018 SPolygon::SPolygon()
00019 {
00020 p = UNDEF_ID;
00021 center = Vector2(DBL_MAX,DBL_MAX);
00022 }
00023
00024 #ifdef USE_VS_CLOSURES
00025 SPolygon::SPolygon(Closure *c)
00026 {
00027 p = UNDEF_ID;
00028 v = c->v;
00029 center = Vector2(DBL_MAX,DBL_MAX);
00030
00031 }
00032 #endif
00033
00034 SPolygon::SPolygon(Array<Vector2> &p)
00035 {
00036 v = p;
00037 center = Vector2(DBL_MAX,DBL_MAX);
00038
00039 }
00040
00041 SPolygon& SPolygon::operator=(const SPolygon &p)
00042 {
00043 this->v = p.v;
00044 this->p = p.p;
00045 this->center = p.center;
00046 return *this;
00047 }
00048
00053 void SPolygon::SetConvexHull(Array<Vector2> &p)
00054 {
00055 ChainHull2D( p, v);
00056 }
00057
00058 void SPolygon::Expand(double d)
00059 {
00060 double angle;
00061 double h2;
00062 int j;
00063 int jm1;
00064 int jp1;
00065 Vector2 p4;
00066 int n=v.Size();
00067
00068 Array<Vector2> eh;
00069
00070
00071 for ( j = 0; j < n; j++ )
00072 {
00073 jm1 = IWrap ( j-1, 0, n-1 );
00074 jp1 = IWrap ( j+1, 0, n-1 );
00075
00076
00077
00078
00079
00080
00081
00082 AngleHalf (v[jm1],v[j],v[jp1],p4);
00083
00084
00085 angle = AngleRAD (v[jm1],v[j],p4);
00086
00087
00088 h2 = d / sin(angle);
00089 eh.PushBack(Vector2(v[j].x-h2*(p4.x-v[j].x), v[j].y-h2*(p4.y-v[j].y)));
00090 }
00091 v=eh;
00092 }
00093
00114 bool SPolygon::Inside(double x, double y)
00115 {
00116 int i, j, npol = v.Size();
00117 bool c = false;
00118 for(i = 0, j = npol-1; i < npol; j = i++)
00119 {
00120 if((((v[i].y <= y) && (y < v[j].y)) ||
00121 ((v[j].y <= y) && (y < v[i].y))) &&
00122 (x < (v[j].x - v[i].x) * (y - v[i].y) / (v[j].y - v[i].y) + v[i].x))
00123 c = !c;
00124 }
00125 return c;
00126 }
00127
00128 bool SPolygon::OnContour(double x, double y, double eps)
00129 {
00130 for (unsigned i=0; i<v.Size(); i++)
00131 {
00132 if (Distance(v[i],P::Vector2(x,y)) < eps)
00133 return true;
00134 }
00135 return false;
00136 }
00137
00138 bool SPolygon::Inside(Array<Vector2> &vs, Vector2 &p)
00139 {
00140 int i, j, npol = vs.Size();
00141 bool c = false;
00142 for(i = 0, j = npol-1; i < npol; j = i++)
00143 {
00144 if((((vs[i].y <= p.y) && (p.y < vs[j].y)) ||
00145 ((vs[j].y <= p.y) && (p.y < vs[i].y))) &&
00146 (p.x < (vs[j].x - vs[i].x) * (p.y - vs[i].y) / (vs[j].y - vs[i].y) + vs[i].x))
00147 c = !c;
00148 }
00149 return c;
00150 }
00151
00155 double SPolygon::NearestNeighbour(Vector2 &p, Array<Vector2> &vs, unsigned &id)
00156 {
00157 double dist, min_dist=DBL_MAX;
00158 for (unsigned i=0; i<vs.Size(); i++){
00159 dist = Distance(p, vs[i]);
00160 if (dist<min_dist){
00161 min_dist = dist;
00162 id = i;
00163 }
00164 }
00165 return min_dist;
00166 }
00167
00171 double SPolygon::NearestLine(Vector2 &p, Array<Vector2> &vs, unsigned &id)
00172 {
00173 id=UINT_MAX;
00174 double dist, min_dist=DBL_MAX;
00175 Vector2 d, l2p;
00176
00177 for (unsigned i=0; i<vs.Size(); i++){
00178 d = vs[vs.CircularNext(i)]-vs[i];
00179 d.Normalise();
00180 l2p = p-vs[i];
00181
00182 dist = fabs(Cross(l2p, d));
00183 if (Dot(l2p,d)>0. && dist<min_dist){
00184 min_dist=dist;
00185 id=i;
00186 }
00187 }
00188
00189 return min_dist;
00190 }
00191
00195 double SPolygon::Match(Array<Vector2> &vs1, Array<Vector2> &vs2)
00196 {
00197 unsigned z;
00198 double dist, h_dist=0., min_dist=DBL_MAX;
00199
00200
00201 for (unsigned i=0; i<vs1.Size(); i++){
00202
00203 min_dist = NearestNeighbour(vs1[i], vs2, z);
00204
00205 dist = NearestLine(vs1[i], vs2, z);
00206 if (dist<min_dist) min_dist=dist;
00207
00208 if (min_dist>h_dist) h_dist=min_dist;
00209 }
00210
00211
00212 for (unsigned i=0; i<vs2.Size(); i++){
00213
00214 min_dist = NearestNeighbour(vs2[i], vs1, z);
00215
00216 dist = NearestLine(vs2[i], vs1, z);
00217 if (dist<min_dist) min_dist=dist;
00218
00219 if (min_dist>h_dist) h_dist=min_dist;
00220 }
00221
00222 return h_dist;
00223 }
00224
00228 void SPolygon::CenterOfGravity(Array<Vector2> &vs, Vector2 &vc)
00229 {
00230 vc=P::Vector2(0.,0.);
00231 if (vs.Size()>0)
00232 {
00233 for (unsigned i=0; i<vs.Size(); i++)
00234 vc+=vs[i];
00235 vc/=vs.Size();
00236 }
00237 }
00238
00242 double SPolygon::Area(Array<Vector2> &vs)
00243 {
00244 double area;
00245 int im1;
00246 int ip1;
00247
00248 area = 0.0;
00249
00250 for ( unsigned i = 1; i <= vs.Size(); i++ )
00251 {
00252 im1 = IWrap ( i-1, 1, vs.Size() );
00253 ip1 = IWrap ( i+1, 1, vs.Size() );
00254
00255 area = area + vs[i-1].x * ( vs[ip1-1].y - vs[im1-1].y );
00256 }
00257
00258 area = 0.5 * fabs ( area );
00259
00260 return area;
00261
00262 }
00263
00264
00265 void SPolygon::Save(ofstream &os, const SPolygon &p)
00266 {
00267 os<<p.v.Size();
00268
00269 for (unsigned i=0; i<p.v.Size(); i++)
00270 os<<' '<<p.v[i].x<<' '<<p.v[i].y;
00271
00272 os<<' '<<p.center.x<<' '<<p.center.y;
00273 os<<' '<<p.p<<'\n';
00274 }
00275
00276 void SPolygon::Load(ifstream &is, SPolygon &p)
00277 {
00278 unsigned size;
00279 is >> size;
00280 p.v.Resize(size);
00281 for (unsigned i=0; i<size; i++)
00282 is >>p.v[i].x>>p.v[i].y;
00283 is >>p.center.x>>p.center.y;
00284 is >>p.p;
00285 }
00286
00287
00288
00289
00290
00291 }
00292