33 #include "geom_utils.h"    34 #include "lsconstants.h"    40 template<
typename I> 
class queryHelper
    45     vector<MocQueryComponent> comp;
    46     vector<T_Healpix_Base<I> > base;
    52     vector<pair<I,int> > stk; 
    58     void check_pixel (
int zone, Moc<I> &pixset)
    64           pixset.appendPixel(o,pix); 
    66           for (
int i=0; i<4; ++i)
    67             stk.push_back(make_pair(4*pix+3-i,o+1)); 
    73           pixset.appendPixel(order,pix>>(2*(o-order))); 
    79             for (
int i=0; i<4; ++i) 
    80               stk.push_back(make_pair(4*pix+3-i,o+1));
    83             pixset.appendPixel(order,pix>>(2*(o-order))); 
    91           pixset.appendPixel(order,pix);
    97             for (
int i=0; i<4; ++i) 
    98               stk.push_back(make_pair(4*pix+3-i,o+1));
   101             pixset.appendPixel(order,pix); 
   106     void correctLoc(
int &loc)
 const   109       planck_assert((myloc>=0)&&(myloc<
int(comp.size())),
"inconsistency");
   110       for (
int i=0; i<comp[myloc].nops; ++i)
   114     int getZone (
int &loc, 
int zmin, 
int zmax)
 const   116       if (zmin==zmax) { loc=shortcut[loc]; 
return zmin; } 
   119       switch (comp[myloc].op)
   124           for (
int i=0; i<comp[myloc].nops; ++i)
   125             z1 = getZone(loc,zmin,z1);
   131           for (
int i=0; i<comp[myloc].nops; ++i)
   132             z1 = getZone(loc,z1,zmax);
   137           int z1=getZone(loc,0,3);
   138           int z2=getZone(loc,0,3);
   139           return max(zmin,min(zmax,max(min(z1,3-z2),min(3-z1,z2))));
   142           return 3-getZone(loc,3-zmax,3-zmin);
   146           double crad=dotprod(pv,comp[myloc].center);
   147           if (crad<=crmax(o,myloc)) res=0;
   148           else if (crad<=cr[myloc]) res=1;
   149           else if (crad<=crmin(o,myloc)) res=2;
   150           return max(zmin,min(zmax,res));
   153       planck_fail(
"must not get here");
   157     queryHelper (
int order_, 
int omax_, 
bool inclusive_,
   158       const vector<MocQueryComponent> &comp_)
   159       : order(order_), omax(omax_), inclusive(inclusive_), comp(comp_),
   160         base(omax+1), shortcut(comp.size()), cr(comp.size()),
   161         crmin(omax+1,comp.size()), crmax(omax+1,comp.size())
   163       planck_assert(comp.size()>=1,
"bad query component vector");
   164       planck_assert(order<=omax,"order>omax
");   165       if (!inclusive) planck_assert(order==omax,"inconsistency
");   166       planck_assert(omax<=T_Healpix_Base<I>::order_max,"omax too high
");   168       for (tsize i=0; i<comp.size(); ++i)   169         if (comp[i].op==NONE) // it's a cap   170           cr[i]=cos(comp[i].radius);   171       for (o=0; o<=omax; ++o) // prepare data at the required orders   174         double dr=base[o].max_pixrad(); // safety distance   175         for (tsize i=0; i<comp.size(); ++i)   176           if (comp[i].op==NONE) // it's a cap   178             crmax(o,i) = (comp[i].radius+dr>=pi) ? -1.01:cos(comp[i].radius+dr);   179             crmin(o,i) = (comp[i].radius-dr<=0.) ?  1.01:cos(comp[i].radius-dr);   183       for (tsize i=0; i<comp.size(); ++i)   193       stk.reserve(12+3*omax); // reserve maximum size to avoid reallocation   194       for (int i=0; i<12; ++i) // insert the 12 base pixels in reverse order   195         stk.push_back(make_pair(I(11-i),0));   197       stacktop=0; // a place to save a stack position   199       while (!stk.empty()) // as long as there are pixels on the stack   201         // pop current pixel number and order from the stack   202         pix=stk.back().first;   205         pv = base[o].pix2vec(pix);   207         int loc=comp.size()-1;   208         tsize zone=getZone(loc,0,3);   209         check_pixel (zone, pixset);   210         planck_assert(loc==-1,"stack not used up
");   216 double isLeft (const vec3 &a, const vec3 &b, const vec3 &c)   217   { return dotprod(crossprod(a,b),c); }   219 // adapted from code available at http://geomalgorithms.com/a12-_hull-3.html   220 // Original copyright notice follows:   221 // Copyright 2001 softSurfer, 2012 Dan Sunday   222 // This code may be freely used and modified for any purpose   223 // providing that this copyright notice is included with it.   224 // SoftSurfer makes no warranty for this code, and cannot be held   225 // liable for any real or imagined damage resulting from its use.   226 // Users of this code must verify correctness for their application.   227 vector<int> getHull (const vector<vec3> &vert, const vector<int> &P)   229   // initialize a deque D[] from bottom to top so that the   230   // 1st three vertices of P[] are a ccw triangle   233   int bot = n-2, top = bot+3;    // initial bottom and top deque indices   234   D[bot] = D[top] = P[2];      // 3rd vertex is at both bot and top   235   if (isLeft(vert[P[0]], vert[P[1]], vert[P[2]]) > 0)   238     D[bot+2] = P[1];           // ccw vertices are: 2,0,1,2   243     D[bot+2] = P[0];           // ccw vertices are: 2,1,0,2   246   // compute the hull on the deque D[]   247   for (int i=3; i<n; i++)   248     {   // process the rest of vertices   249     // test if next vertex is inside the deque hull   250     if ((isLeft(vert[D[bot]], vert[D[bot+1]], vert[P[i]]) > 0) &&   251         (isLeft(vert[D[top-1]], vert[D[top]], vert[P[i]]) > 0) )   252       continue;         // skip an interior vertex   254     // incrementally add an exterior vertex to the deque hull   255     // get the rightmost tangent at the deque bot   256     while (isLeft(vert[D[bot]], vert[D[bot+1]], vert[P[i]]) <= 0)   257       ++bot;                 // remove bot of deque   258     D[--bot] = P[i];         // insert P[i] at bot of deque   260     // get the leftmost tangent at the deque top   261     while (isLeft(vert[D[top-1]], vert[D[top]], vert[P[i]]) <= 0)   262       --top;                 // pop top of deque   263     D[++top] = P[i];         // push P[i] onto top of deque   266   // transcribe deque D[] to the output hull array H[]   268   vector<int> res(nout);   269   for (int h=0; h<nout; h++)   270     res[h] = D[bot + h +1];   275 void prepPolyHelper (const vector<vec3> &vv, const vector<int> &P,   276   vector<MocQueryComponent> &comp, bool doLast)   278   vector<int> hull=getHull(vv,P);   279   vector<bool> addHull(hull.size());   281   // sync both sequences at the first point of the convex hull   282   int ihull=0, ipoly=0, nhull=hull.size(), npoly=P.size();   283   while (hull[ihull]!=P[ipoly]) ++ipoly;   285   // iterate over the pockets between the polygon and its convex hull   287   if (P.size()==3) // really P.size(), not vv.size()?   288     for (int i=0; i<3; i++) addHull[i]=true;   293       int ihull_next = (ihull+1)%nhull,   294           ipoly_next = (ipoly+1)%npoly;   295       if (hull[ihull_next]==P[ipoly_next]) // no pocket found   296         { addHull[ihull]=true; ihull=ihull_next; ipoly=ipoly_next; }   299         int nvpocket=2; // number of vertices for this pocket   300         while (P[ipoly_next]!=hull[ihull_next])   302           ipoly_next = (ipoly_next+1)%npoly;   305         vector<int> ppocket(nvpocket);   307         int ipoly_bw=ipoly_next;   308         while (P[ipoly_bw]!=hull[ihull])   310           ppocket[idx++]=P[ipoly_bw];   311           ipoly_bw=(ipoly_bw+npoly-1)%npoly;   313         ppocket[idx]=hull[ihull];   314         // process pocket recursively   316         prepPolyHelper (vv, ppocket, comp, false);   323     comp.push_back(MocQueryComponent(OR,npockets));   325     comp.push_back(MocQueryComponent(NOT));   328     addHull.back()=false;   331   for (tsize i=0; i<hull.size(); ++i)   333       comp.push_back(MocQueryComponent   334         (crossprod(vv[hull[i]],vv[hull[(i+1)%hull.size()]]).Norm(),0.5*pi));   337   for (tsize i=0; i<hull.size(); ++i)   338     if (addHull[i]) ++num_and;   339   if (npockets>0) ++num_and;   341     comp.push_back(MocQueryComponent(AND,num_and));   344 } // unnamed namespace   346 template<typename I> Moc<I> mocQuery (int order,   347   const vector<MocQueryComponent> &comp)   348   { return queryHelper<I>(order,order,false,comp).result(); }   349 template Moc<int> mocQuery (int order, const vector<MocQueryComponent> &comp);   350 template Moc<int64> mocQuery (int order, const vector<MocQueryComponent> &comp);   352 template<typename I> Moc<I> mocQueryInclusive (int order, int omax,   353   const vector<MocQueryComponent> &comp)   354   { return queryHelper<I>(order,omax,true,comp).result(); }   355 template Moc<int> mocQueryInclusive (int order, int omax,   356   const vector<MocQueryComponent> &comp);   357 template Moc<int64> mocQueryInclusive (int order, int omax,   358   const vector<MocQueryComponent> &comp);   360 vector<MocQueryComponent> prepPolygon (const vector<vec3> &vertex)   362   planck_assert(vertex.size()>=3,"not enough vertices in polygon
");   363   vector<vec3> vv(vertex.size());   364   for (tsize i=0; i<vertex.size(); ++i)   365     vv[i]=vertex[i].Norm();   367   vector<int> P(vv.size());   368   for (tsize i=0; i<P.size(); ++i)   370   vector<MocQueryComponent> comp;   371   prepPolyHelper(vv,P,comp,true);