00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef __VCG_OUTLINE2_PACKER_H__
00024 #define __VCG_OUTLINE2_PACKER_H__
00025
00026 #include <limits>
00027 #include <stdio.h>
00028 #include <assert.h>
00029 #include <algorithm>
00030 #include <vector>
00031 #include <vcg/space/box2.h>
00032 #include <vcg/space/rect_packer.h>
00033 #include <vcg/space/point2.h>
00034 #include <vcg/math/similarity2.h>
00035
00036
00037
00038 namespace vcg
00039 {
00040
00041 template <class SCALAR_TYPE>
00042 class PolyPacker
00043 {
00044 typedef typename vcg::Box2<SCALAR_TYPE> Box2x;
00045 typedef typename vcg::Point2<SCALAR_TYPE> Point2x;
00046 typedef typename vcg::Similarity2<SCALAR_TYPE> Similarity2x;
00047
00048 public:
00049
00050 static Box2f getPolyBB(const std::vector<Point2x> &poly)
00051 {
00052 Box2f bb;
00053 for(size_t i=0;i<poly.size();++i)
00054 bb.Add(poly[i]);
00055
00056 return bb;
00057 }
00058
00059 static Box2f getPolyOOBB(const std::vector<Point2x> &poly, float &rot)
00060 {
00061 const int stepNum=32;
00062 float bestAngle;
00063 float bestArea = std::numeric_limits<float>::max();
00064 Box2f bestBB;
00065
00066 for(int i=0;i<stepNum;++i)
00067 {
00068 float angle = float(i)*(M_PI/2.0)/float(stepNum);
00069 Box2f bb;
00070 for(size_t j=0;j<poly.size();++j)
00071 {
00072 Point2f pp=poly[j];
00073 pp.Rotate(angle);
00074 bb.Add(pp);
00075 }
00076
00077 if(bb.Area()<bestArea)
00078 {
00079 bestAngle=angle;
00080 bestArea=bb.Area();
00081 bestBB=bb;
00082 }
00083 }
00084 rot=bestAngle;
00085 return bestBB;
00086 }
00087
00088 static bool PackAsEqualSquares(const std::vector< std::vector<Point2x> > &polyVec,
00089 const Point2i containerSizeX,
00090 std::vector<Similarity2x> &trVec,
00091 Point2x &coveredContainer)
00092 {
00093 int minSide = std::min(containerSizeX[0],containerSizeX[1]);
00094 const vcg::Point2i containerSize(minSide,minSide);
00095 int polyPerLine = ceil(sqrt((double)polyVec.size()));
00096 int pixelPerPoly = minSide / (polyPerLine);
00097 if(pixelPerPoly < 1) return false;
00098
00099 trVec.clear();
00100 trVec.resize(polyVec.size());
00101 Box2f bbMax;
00102 std::vector<Box2x> bbVec;
00103 for(size_t i=0;i<polyVec.size();++i)
00104 {
00105 bbVec.push_back(getPolyBB(polyVec[i]));
00106 bbMax.Add(bbVec.back());
00107 }
00108
00109 float unitScale = 1.0/std::max(bbMax.DimX(), bbMax.DimY());
00110 float polyScale = unitScale * pixelPerPoly;
00111
00112 int baseX =0;
00113 int baseY=0;
00114 for(size_t i=0;i<polyVec.size();++i)
00115 {
00116 trVec[i].sca = polyScale;
00117 trVec[i].tra = Point2f(baseX+(0.5*pixelPerPoly), baseY+(0.5*pixelPerPoly)) - bbVec[i].Center()*polyScale;
00118 baseX +=pixelPerPoly;
00119
00120 if(baseX +pixelPerPoly>minSide)
00121 {
00122 baseY+=pixelPerPoly;
00123 baseX=0;
00124 }
00125 }
00126 return true;
00127 }
00128
00129 static bool PackAsAxisAlignedRect(const std::vector< std::vector<Point2x> > &polyVec,
00130 const Point2i containerSizeX,
00131 std::vector<Similarity2x> &trVec,
00132 Point2x &coveredContainer)
00133 {
00134 trVec.clear();
00135 trVec.resize(polyVec.size());
00136 std::vector<Box2x> bbVec;
00137 for(size_t i=0;i<polyVec.size();++i)
00138 {
00139 assert(polyVec[i].size()>0);
00140 bbVec.push_back(getPolyBB(polyVec[i]));
00141 }
00142 return RectPacker<float>::Pack(bbVec,containerSizeX,trVec,coveredContainer);
00143 }
00144
00145 static bool PackAsObjectOrientedRect(const std::vector< std::vector<Point2x> > &polyVec,
00146 const Point2i containerSizeX,
00147 std::vector<Similarity2x> &trVec,
00148 Point2x &coveredContainer)
00149 {
00150 trVec.clear();
00151 trVec.resize(polyVec.size());
00152 std::vector<Box2x> bbVec;
00153 std::vector<float> rotVec;
00154 for(size_t i=0;i<polyVec.size();++i)
00155 {
00156 float rot;
00157 bbVec.push_back(getPolyOOBB(polyVec[i],rot));
00158 rotVec.push_back(rot);
00159 }
00160
00161 bool ret= RectPacker<float>::Pack(bbVec,containerSizeX,trVec,coveredContainer);
00162
00163 for(size_t i=0;i<polyVec.size();++i)
00164 {
00165 trVec[i].rotRad=rotVec[i];
00166 }
00167 return ret;
00168 }
00169
00170
00171 static bool PackMultiAsObjectOrientedRect(const std::vector< std::vector<Point2x> > &polyVec,
00172 const Point2x containerSizeX, const int containerNum,
00173 std::vector<Similarity2x> &trVec, std::vector<int> &indVec,
00174 std::vector<Point2x> &coveredContainerVec)
00175 {
00176 trVec.clear();
00177 trVec.resize(polyVec.size());
00178 std::vector<Box2x> bbVec;
00179 std::vector<float> rotVec;
00180 for(size_t i=0;i<polyVec.size();++i)
00181 {
00182 float rot;
00183 bbVec.push_back(getPolyOOBB(polyVec[i],rot));
00184 rotVec.push_back(rot);
00185 }
00186 const Point2i containerSizeI=Point2i::Construct(containerSizeX);
00187 bool ret= RectPacker<float>::PackMulti(bbVec,containerSizeI,containerNum,trVec,indVec,coveredContainerVec);
00188
00189 for(size_t i=0;i<polyVec.size();++i)
00190 {
00191 trVec[i].rotRad=rotVec[i];
00192 }
00193 return ret;
00194 }
00195
00196 static bool WritePolyVec(const std::vector< std::vector<Point2x> > &polyVec, const char *filename)
00197 {
00198 FILE *fp=fopen(filename,"w");
00199 if(!fp) return false;
00200 fprintf(fp,"%lu\n",polyVec.size());
00201 for(size_t i=0;i<polyVec.size();++i)
00202 {
00203 fprintf(fp,"%lu\n",polyVec[i].size());
00204 for(size_t j=0;j<polyVec[i].size();++j)
00205 fprintf(fp,"%f %f ",polyVec[i][j].X(),polyVec[i][j].Y());
00206 fprintf(fp,"\n");
00207 }
00208 fclose(fp);
00209 return true;
00210 }
00211
00212 static bool ReadPolyVec(std::vector< std::vector<Point2x> > &polyVec, const char *filename)
00213 {
00214 FILE *fp=fopen(filename,"r");
00215 if(!fp) return false;
00216 int sz;
00217 fscanf(fp,"%i\n",&sz);
00218 polyVec.clear();
00219 polyVec.resize(sz);
00220 for(size_t i=0;i<polyVec.size();++i)
00221 {
00222 fscanf(fp,"%i\n",&sz);
00223 polyVec[i].resize(sz);
00224 for(size_t j=0;j<polyVec[i].size();++j)
00225 {
00226 float x,y;
00227 fscanf(fp,"%f %f",&x,&y);
00228 polyVec[i][j].X()=x;
00229 polyVec[i][j].Y()=y;
00230 }
00231 }
00232 fclose(fp);
00233 return true;
00234 }
00235
00236
00237 };
00238 }
00239 #endif // POLY_PACKER_H