You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
350 lines
10 KiB
350 lines
10 KiB
/**************************************************************************** |
|
* VCGLib o o * |
|
* Visual and Computer Graphics Library o o * |
|
* _ O _ * |
|
* Copyright(C) 2004-2009 \/)\/ * |
|
* Visual Computing Lab /\/| * |
|
* ISTI - Italian National Research Council | * |
|
* \ * |
|
* All rights reserved. * |
|
* * |
|
* This program is free software; you can redistribute it and/or modify * |
|
* it under the terms of the GNU General Public License as published by * |
|
* the Free Software Foundation; either version 2 of the License, or * |
|
* (at your option) any later version. * |
|
* * |
|
* This program is distributed in the hope that it will be useful, * |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of * |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
|
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * |
|
* for more details. * |
|
* * |
|
****************************************************************************/ |
|
#include <stdio.h> |
|
#include <time.h> |
|
#include <vcg/space/distance2.h> |
|
#include <vcg/space/segment2.h> |
|
#include <vcg/space/index/grid_static_ptr2d.h> |
|
#include <vcg/space/index/grid_closest2d.h> |
|
#include <vcg/space/intersection2.h> |
|
|
|
typedef double MyScalarType; |
|
typedef vcg::Point2<MyScalarType> MyCoordType; |
|
typedef vcg::Ray2<MyScalarType> MyRayType; |
|
|
|
//**BASIC SEGMENT CLASS |
|
class MySegmentType:public vcg::Segment2<MyScalarType> |
|
{ |
|
public: |
|
int mark; |
|
bool IsD(){return false;} |
|
|
|
MySegmentType(const vcg::Point2<MyScalarType> &_P0, |
|
const vcg::Point2<MyScalarType> &_P1) |
|
{ |
|
P0()=_P0; |
|
P1()=_P1; |
|
mark=0; |
|
} |
|
|
|
int &TMark(){return mark;} |
|
|
|
MySegmentType(){} |
|
|
|
MySegmentType(const MySegmentType &s1):vcg::Segment2<MyScalarType>(s1) |
|
{ |
|
P0()=s1.P0(); |
|
P1()=s1.P1(); |
|
mark=s1.mark; |
|
} |
|
}; |
|
|
|
|
|
//**ALLOCATED SEGMENTS**// |
|
std::vector<MySegmentType> AllocatedSeg; |
|
|
|
//**GENERATION OF RANDOM SEGMENTS |
|
|
|
vcg::Point2<MyScalarType> RandomPoint(MyScalarType SpaceSize=100) |
|
{ |
|
int dimension=RAND_MAX; |
|
int X=rand(); |
|
int Y=rand(); |
|
vcg::Point2<MyScalarType> P0=vcg::Point2<MyScalarType>((MyScalarType)X/dimension,(MyScalarType)Y/dimension); |
|
P0*=SpaceSize; |
|
return P0; |
|
} |
|
|
|
|
|
void RandomSeg(vcg::Point2<MyScalarType> &P0, |
|
vcg::Point2<MyScalarType> &P1, |
|
MyScalarType SpaceSize=100, |
|
MyScalarType maxdim=1) |
|
{ |
|
|
|
P0=RandomPoint(SpaceSize); |
|
vcg::Point2<MyScalarType> D=RandomPoint(SpaceSize); |
|
D.Normalize(); |
|
D*=maxdim; |
|
P1=P0+D; |
|
} |
|
|
|
void InitRandom(int num, |
|
MyScalarType SpaceSize=100, |
|
MyScalarType maxdim=1) |
|
{ |
|
AllocatedSeg.clear(); |
|
AllocatedSeg.resize(num); |
|
srand(clock()); |
|
for (int i=0;i<num;i++) |
|
{ |
|
vcg::Point2<MyScalarType> P0,P1; |
|
RandomSeg(P0,P1,SpaceSize,maxdim); |
|
AllocatedSeg[i]=MySegmentType(P0,P1); |
|
//AllocatedSeg[i].deleted=false; |
|
} |
|
|
|
} |
|
|
|
|
|
//**MARKER CLASSES**// |
|
class MyMarker |
|
{ |
|
|
|
public: |
|
int mark; |
|
|
|
MyMarker(){mark=0;} |
|
|
|
void UnMarkAll(){mark++;} |
|
|
|
bool IsMarked(MySegmentType* obj) |
|
{ |
|
int markObj=obj->TMark(); |
|
return(markObj==mark); |
|
} |
|
|
|
void Mark(MySegmentType* obj) |
|
{obj->TMark()=mark;} |
|
|
|
}; |
|
|
|
//**GRID-RELATED STUFF**// |
|
MyMarker mf; |
|
vcg::GridStaticPtr2D<MySegmentType,MyScalarType> Grid2D; |
|
|
|
//**QUERIES |
|
MySegmentType * GetClosestSegment(MyCoordType & _p, |
|
MyCoordType &_closestPt) |
|
{ |
|
vcg::PointSegment2DEPFunctor<MyScalarType> PDistFunct; |
|
|
|
MyScalarType _minDist; |
|
MyScalarType _maxDist=std::numeric_limits<MyScalarType>::max(); |
|
return (Grid2D.GetClosest(PDistFunct,mf,_p,_maxDist,_minDist,_closestPt)); |
|
} |
|
|
|
void GetInBoxSegments(vcg::Box2<MyScalarType> bbox,std::vector<MySegmentType*> &result) |
|
{ |
|
Grid2D.GetInBox(mf,bbox,result); |
|
} |
|
|
|
MySegmentType * DoRay(MyRayType & _r, |
|
MyCoordType &_closestPt) |
|
{ |
|
MyRayType _ray1=_r; |
|
_ray1.Normalize(); |
|
typedef vcg::RaySegmentIntersectionFunctor SintFunct; |
|
SintFunct rs; |
|
MyScalarType _maxDist=std::numeric_limits<MyScalarType>::max(); |
|
MyScalarType _t; |
|
MySegmentType *seg=Grid2D.DoRay(rs,mf,_ray1,_maxDist,_t); |
|
|
|
if (seg==NULL)return NULL; |
|
_closestPt=_ray1.Origin()+_ray1.Direction()*_t; |
|
return seg; |
|
} |
|
|
|
//**BRUTE FORCE QUERIES |
|
void GetInBoxSegmentsBruteF( vcg::Box2<MyScalarType> bbox, |
|
std::vector<MySegmentType*> &result) |
|
{ |
|
vcg::Box2<MyScalarType> ibbox; |
|
for (size_t i=0;i<AllocatedSeg.size();i++) |
|
{ |
|
AllocatedSeg[i].GetBBox(ibbox); |
|
if (!ibbox.Collide(bbox)) continue; |
|
result.push_back(&AllocatedSeg[i]); |
|
} |
|
} |
|
|
|
MySegmentType* GetClosesestSegmentBruteF(MyCoordType & _p, |
|
MyCoordType &_closestPt) |
|
{ |
|
MyScalarType _minDist=std::numeric_limits<MyScalarType>::max(); |
|
MySegmentType *ret=NULL; |
|
for (size_t i=0;i<AllocatedSeg.size();i++) |
|
{ |
|
vcg::Point2<MyScalarType> test; |
|
test=vcg::ClosestPoint(AllocatedSeg[i],_p); |
|
MyScalarType currD=(test-_p).Norm(); |
|
if (currD<_minDist) |
|
{ |
|
_closestPt=test; |
|
_minDist=currD; |
|
ret=&AllocatedSeg[i]; |
|
} |
|
} |
|
return ret; |
|
} |
|
|
|
MySegmentType * DoRayBruteF(MyRayType & _r, |
|
MyCoordType &_closestPt) |
|
{ |
|
MyScalarType _minDist=std::numeric_limits<MyScalarType>::max(); |
|
MySegmentType *ret=NULL; |
|
for (size_t i=0;i<AllocatedSeg.size();i++) |
|
{ |
|
vcg::Point2<MyScalarType> test; |
|
bool inters=vcg::RaySegmentIntersection(_r,AllocatedSeg[i],test); |
|
if (!inters)continue; |
|
MyScalarType currD=(test-_r.Origin()).Norm(); |
|
if (currD<_minDist) |
|
{ |
|
_closestPt=test; |
|
_minDist=currD; |
|
ret=&AllocatedSeg[i]; |
|
} |
|
} |
|
return ret; |
|
} |
|
|
|
|
|
void TestBox(int num_test=100000, |
|
MyScalarType SpaceSize=100) |
|
{ |
|
int numWrong=0; |
|
|
|
for (int i=0;i<num_test;i++) |
|
{ |
|
vcg::Point2<MyScalarType> P0=RandomPoint(SpaceSize); |
|
vcg::Point2<MyScalarType> P1=RandomPoint(SpaceSize); |
|
vcg::Box2<MyScalarType> bbox; |
|
bbox.Add(P0); |
|
bbox.Add(P1); |
|
std::vector<MySegmentType*> result0; |
|
GetInBoxSegments(bbox,result0); |
|
|
|
std::vector<MySegmentType*> result1; |
|
GetInBoxSegmentsBruteF(bbox,result1); |
|
|
|
std::sort(result0.begin(),result0.end()); |
|
std::sort(result1.begin(),result1.end()); |
|
|
|
std::vector<MySegmentType*>::iterator new_end=std::unique(result1.begin(),result1.end()); |
|
int dist=distance(result1.begin(),new_end); |
|
result1.resize(dist); |
|
|
|
if (result0.size()!=result1.size())numWrong++; |
|
|
|
for (size_t j = 0; j < result0.size(); j++) |
|
if (result0[j] != result1[j]) |
|
{ |
|
numWrong++; |
|
} |
|
} |
|
printf("WRONG TESTS BBOX %d ON %d \n",numWrong,num_test); |
|
fflush(stdout); |
|
} |
|
|
|
void TestClosest(int num_test=100000, |
|
MyScalarType SpaceSize=100) |
|
{ |
|
|
|
int numWrong=0; |
|
for (int i=0;i<num_test;i++) |
|
{ |
|
vcg::Point2<MyScalarType> P0=RandomPoint(SpaceSize); |
|
|
|
vcg::Point2<MyScalarType> closest0; |
|
MySegmentType* result0=GetClosestSegment(P0,closest0); |
|
|
|
vcg::Point2<MyScalarType> closest1; |
|
MySegmentType* result1=GetClosesestSegmentBruteF(P0,closest1); |
|
|
|
|
|
if (result0!=result1) |
|
{ |
|
numWrong++; |
|
printf("D0 %5.5f \n",(closest0-P0).Norm()); |
|
printf("D1 %5.5f \n",(closest1-P0).Norm()); |
|
fflush(stdout); |
|
} |
|
} |
|
printf("WRONG TESTS CLOSEST %d ON %d \n",numWrong,num_test); |
|
fflush(stdout); |
|
} |
|
|
|
void TestRay(int num_test=100000, |
|
MyScalarType SpaceSize=100) |
|
{ |
|
int numWrong=0; |
|
int NUll0=0; |
|
int NUll1=0; |
|
for (int i=0;i<num_test;i++) |
|
{ |
|
vcg::Point2<MyScalarType> P0=RandomPoint(SpaceSize); |
|
vcg::Point2<MyScalarType> P1=RandomPoint(SpaceSize); |
|
vcg::Point2<MyScalarType> Orig=P0; |
|
vcg::Point2<MyScalarType> Dir=P1-P0; |
|
Dir.Normalize(); |
|
|
|
MyRayType r(Orig,Dir); |
|
|
|
vcg::Point2<MyScalarType> closest0; |
|
MySegmentType* result0=DoRay(r,closest0); |
|
|
|
vcg::Point2<MyScalarType> closest1; |
|
MySegmentType* result1=DoRayBruteF(r,closest1); |
|
|
|
|
|
if (result0!=result1) |
|
{ |
|
numWrong++; |
|
// printf("D0 %5.5f \n",(closest0-P0).Norm()); |
|
// printf("D1 %5.5f \n",(closest1-P0).Norm()); |
|
// fflush(stdout); |
|
} |
|
if (result0==NULL) NUll0++; |
|
if (result1==NULL) NUll1++; |
|
} |
|
printf("WRONG TESTS DORAY %d ON %d \n",numWrong,num_test); |
|
printf("NULL0 %d \n",NUll0); |
|
printf("NULL1 %d \n",NUll1); |
|
fflush(stdout); |
|
} |
|
|
|
int main( int argc, char **argv ) |
|
{ |
|
(void) argc; |
|
(void) argv; |
|
int num_sample=20000; |
|
int t0=clock(); |
|
|
|
printf("** Random Initialization ** \n"); |
|
fflush(stdout); |
|
InitRandom(num_sample,100,0.3); |
|
int t1=clock(); |
|
|
|
///Initialization performance |
|
printf("** Time elapsed for initialization of %d sample is %d\n \n",num_sample,t1-t0); |
|
Grid2D.Set(AllocatedSeg.begin(),AllocatedSeg.end()); |
|
fflush(stdout); |
|
|
|
//Box Query correctness |
|
TestBox(num_sample); |
|
TestClosest(num_sample); |
|
TestRay(num_sample); |
|
|
|
return 0; |
|
}
|
|
|