vcglib/apps/sample/space_index_2d/space_index_2d.cpp

351 lines
10 KiB
C++

/****************************************************************************
* 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;
}