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);