/// <summary> /// Computes the list of hid ranges for a halfspace given as a "circle" /// with a given location in RA/DEC and a radius (in arc minutes). /// </summary> /// <param name="depth">Do not compute trixels beyond this depth</param> /// <param name="ra">RA in degrees</param> /// <param name="dec">DEC in degrees</param> /// <param name="radius">Radius of cone in arc minutes</param> /// <returns>A table of HtmIDs</returns> public static Int64[,] Circle(double depth, double ra, double dec, double radius){ Int64[,] returnResult; // interface to caller ArrayList lohis; // interface to xphtm Convex lohis = new ArrayList(); // Convert arc minutes to Radians. 60 * 180 = 10800; // double x, y, z; double d = Cartesian.Cos(Cartesian.Pi * radius/10800.0); SpatialVector.radec2cartesian(ra, dec, out x, out y, out z); Convex c = new Convex(Convex.Mode.Normal); c.add(x, y, z, d); c.intersect(false, HtmState.Instance.maxlevel, lohis);// lohis is list of pairs int rows = lohis.Count/2; int cols = 2; int k = 0; returnResult = new Int64[rows,cols]; for(int i=0; i<rows; i++){ returnResult[i,0] = (Int64) lohis[k++]; returnResult[i,1] = (Int64) lohis[k++]; } return returnResult; }
/************************** END CIRCLE *******************************/ #endregion #region parse_convex // ////////////////////////////// parse CONVEX private bool parse_convex() { Region region = _targetregion; Convex convex = null; Geometry nextitem; double ra, dec, x, y, z, D; if (region == null) return true; advance(); // Skip over 'CONVEX' _format = peekFormat(); if (ismore && _format != Format.Null) { advance(); } convex = new Convex(); region.add(convex); while (ismore) { nextitem = peekGeometry(); if (nextitem != Geometry.Null) break; switch (_format) { case Format.Null: case Format.Cartesian: try { x = this.getdouble(); y = this.getdouble(); z = this.getdouble(); D = this.getdouble(); } catch { if (_error != Error.errEol) _error = Error.errIllegalNumber; return isok; } convex.add(x, y, z, D); break; case Format.J2000: case Format.Latlon: try { ra = this.getdouble(); dec = this.getdouble(); D = this.getdouble(); } catch { if (_error != Error.errEol) _error = Error.errIllegalNumber; return isok; } if (_format == Format.J2000) { SpatialVector.radec2cartesian(ra, dec, out x, out y, out z); } else { SpatialVector.radec2cartesian(dec, ra, out x, out y, out z); } convex.add(x, y, z, D); break; default: break; } } return true; }
/// <summary> /// Computes the table for a single halfspace. /// Identical in function /// to Circle, only the parameters are different. /// </summary> /// <param name="depth">do not compute trixels beyond this depth</param> /// <param name="x">x-coordinate of halfspace's direction vector</param> /// <param name="y">y-coordinate of halfspace's direction vector</param> /// <param name="z">z-coordinate of halfspace's direction vector</param> /// <param name="d">distance of cutting plane from origin</param> /// <returns></returns> public static Int64[,] Halfspace(double depth, double x, double y, double z, double d){ Int64[,] returnResult; // interface to caller ArrayList lohis; // interface to xphtm Convex lohis = new ArrayList(); Convex c = new Convex(Convex.Mode.Normal); c.add(x, y, z, d); c.intersect(false, HtmState.Instance.maxlevel, lohis);// lohis is list of pairs int rows = lohis.Count/2; int cols = 2; int k = 0; returnResult = new Int64[rows,cols]; for(int i=0; i<rows; i++){ returnResult[i,0] = (Int64) lohis[k++]; returnResult[i,1] = (Int64) lohis[k++]; } return returnResult; }
/// <summary> /// Create a domain with a single convex defined /// by a rectangle. /// The rectangle is defined by /// RA/DEC limits. /// The dec may be in any order, /// but the RA order is significant, because the spehere wraps around. /// In other words RA range 350 - 10 is distinguished from 10 - 350 /// There are two great circles (ra) and two small circles (dec) /// </summary> /// <param name="depth">do not compute trixels beyond this depth</param> /// <param name="ra1"></param> /// <param name="dec1"></param> /// <param name="ra2"></param> /// <param name="dec2"></param> /// <returns>A table of HtmIDs</returns> public static Int64[,] Rectangle(double depth, double ra1, double dec1, double ra2, double dec2) { // // Create four halfspaces. Two great circles for RA and // two small circles for DEC Int64[,] returnResult; double dlo, dhi; // offset from center, parameter for constraint double declo, dechi; double costh, sinth; // sine and cosine of theta (RA) for rotation of vector double x, y, z; ArrayList lohis; // interface to xphtm Convex Convex c = new Convex(Convex.Mode.Normal); lohis = new ArrayList(); // // Halfspaces belonging to declo and dechi are circles parallel // to the xy plane, their normal is (0, 0, +/-1) // // declo halfpsacet is pointing up (0, 0, 1) // dechi is pointing down (0, 0, -1) if (dec1 > dec2){ declo = dec2; dechi = dec1; } else { declo = dec1; dechi = dec2; } dlo = Math.Sin(declo * Cartesian.DTOR); dhi = -Math.Sin(dechi * Cartesian.DTOR); // Yes, MINUS! c.add(0.0, 0.0, 1.0, dlo); // Halfspace #1 c.add(0.0, 0.0, -1.0, dhi); // Halfspace #1 costh = Cartesian.Cos(ra1 * Cartesian.DTOR); sinth = Math.Sin(ra1 * Cartesian.DTOR); x = -sinth; y = costh; z = 0.0; c.add(x, y, z, 0.0);// Halfspace #3 costh = Cartesian.Cos(ra2 * Cartesian.DTOR); sinth = Math.Sin(ra2 * Cartesian.DTOR); x = sinth; y = -costh; z = 0.0; c.add(x, y, z, 0.0);// Halfspace #4 /////////////////////////////////////// INTERSECT c.intersect(false, HtmState.Instance.maxlevel, lohis);// lohis is list of pairs /////////////////////////////////////// STORE RESULT int rows = lohis.Count/2; int cols = 2; int k = 0; returnResult = new Int64[rows,cols]; for(int i=0; i<rows; i++){ returnResult[i,0] = (Int64) lohis[k++]; returnResult[i,1] = (Int64) lohis[k++]; } return returnResult; }
public Polygon.Error add(double[] x, double[] y, double[] z, int len){ bool DIRECTION = false; bool FIRST_DIRECTION = false; // The constraint we have for each side is a 0-constraint (great circle) // passing through the 2 corners. Since we are in counterclockwise order, // the vector product of the two successive corners just gives the correct // constraint. // // Polygons should be counterclockwise // Polygons are assumed to be convex, otherwise windingerror is // computed wrong. int ix; Cartesian v = new Cartesian(); Convex cvx = new Convex(Convex.Mode.Normal); int i; /* PASS 1: check for winding error */ for(i = 0; i < len; i++) { // Keep track of winding direction. Should be positive // that is, CCW. ix = (i==len-1 ? 0 : i+1); if (i>0){ // test third corner against the constraint just formed // v is computed in the previous iteration // Look at a corner dot v if (v.dot(x[ix], y[ix], z[ix]) < Cartesian.Epsilon) { DIRECTION = true; if (i == 1) { FIRST_DIRECTION = true; } // break; // Move to pass 2 } else { DIRECTION = false; if (i == 1) { FIRST_DIRECTION = false; } } if (i > 1) { if (DIRECTION != FIRST_DIRECTION) { // C++: must clea up new Cartesian and convex // or better yet, do no allocate on top until you know // you need it return Polygon.Error.errBowtieOrConcave; // BOWTie error } } } // v = corners[i] ^ corners[ i == len-1 ? 0 : i + 1]; v.assign(x[i], y[i], z[i]); v.crossMe(x[ix], y[ix], z[ix]); if (v.isLength(0.0, Cartesian.Epsilon)) { return Polygon.Error.errZeroLength; } // WARNING! if v = zerovector, then edge error!!! } /* PASS 2: build convex in either original or reverse order */ /* forward: Go from 0 to len-1 by +1, cross i and i+1 (or 0) reverse: Go from len-1 to 0 by -1, cross i and i-1 (or len-1) */ if (DIRECTION) { for(i=len-1; i>=0; i--){ // v = corners[i] ^ corners[ i == 0 ? len-1 : i-1]; // v.normalize(); ix = (i==0? len-1 : i-1); v.assign(x[i], y[i], z[i]); v.crossMe(x[ix], y[ix], z[ix]); // WARNING! if v = zerovector, then edge error!!! v.normalizeMe(); Halfspace c = new Halfspace(v, 0.0); // SpatialConstraint c(v,0); cvx.add(c); } } else { for(i=0; i<len; i++){ //v = corners[i] ^ corners[ i == len-1 ? 0 : i+1]; // v.normalize(); ix = (i==len-1 ? 0 : i+1); v.assign(x[i], y[i], z[i]); v.crossMe(x[ix], y[ix], z[ix]); // WARNING! if v = zerovector, then edge error!!! v.normalizeMe(); Halfspace c = new Halfspace(v, 0.0); cvx.add(c); } } _reg.add(cvx); return Polygon.Error.Ok; }