LSSTApplications  12.1-5-gbdcc3ab,15.0+10,15.0+19,15.0-1-g19261fa+10,15.0-1-g60afb23+19,15.0-1-g615e0bb+11,15.0-1-g6668b0b+6,15.0-1-g788a293+19,15.0-1-ga91101e+19,15.0-1-gae1598d+9,15.0-1-gd076f1f+17,15.0-1-gdf18595+3,15.0-1-gf4f1c34+9,15.0-10-g113cadf7+2,15.0-11-g5674e3b,15.0-2-g100d730+12,15.0-2-g20c4630+8,15.0-2-g35685a8+15,15.0-2-g5dfaa72+8,15.0-2-gf38729e+14,15.0-24-g02ed2a30c+2,15.0-3-g11fe1a0+3,15.0-3-g130a88a+2,15.0-3-g707930d+1,15.0-3-g9103c06+9,15.0-3-ga03b4ca+26,15.0-3-gaec6799+6,15.0-4-g32c2b40+2,15.0-4-g535e784+3,15.0-4-g654b129+17,15.0-5-g23e394c+7,15.0-5-g54bfcd9+2,15.0-5-gb31927c,15.0-6-g4418537+2,15.0-7-g0c26201,15.0-7-g6bb3a066+2,15.0-9-g5661f8f+4,w.2018.18
LSSTDataManagementBasePackage
Classes | Functions | Variables
lsst.geom.geometry Namespace Reference

Classes

class  _SubList
 
class  PartitionMap
 
class  SphericalBox
 
class  SphericalBoxPartitionMap
 
class  SphericalCircle
 
class  SphericalConvexPolygon
 
class  SphericalEllipse
 
class  SphericalRegion
 

Functions

def isinf (x)
 
def dot (v1, v2)
 
def cross (v1, v2)
 
def invScale (v, s)
 
def normalize (v)
 
def sphericalCoords (args)
 
def cartesianUnitVector (args)
 
def sphericalAngularSep (p1, p2)
 
def clampPhi (phi)
 
def reduceTheta (theta)
 
def northEast (v)
 
def alpha (r, centerPhi, phi)
 
def maxAlpha (r, centerPhi)
 
def cartesianAngularSep (v1, v2)
 
def minEdgeSep (p, n, v1, v2)
 
def minPhiEdgeSep (p, phi, minTheta, maxTheta)
 
def minThetaEdgeSep (p, theta, minPhi, maxPhi)
 
def centroid (vertices)
 
def between (p, n, v1, v2)
 
def segments (phiMin, phiMax, width)
 
def median (array)
 
def hemispherical (points)
 
def convex (vertices)
 
def convexHull (points)
 

Variables

float ARCSEC_PER_DEG = 3600.0
 
float DEG_PER_ARCSEC = 1.0 / 3600.0
 
float ANGLE_EPSILON = 0.001 * DEG_PER_ARCSEC
 
float POLE_EPSILON = 1.0 * DEG_PER_ARCSEC
 
float COS_MAX = 1.0 - 1.0e-15
 
int CROSS_N2MIN = 2e-15
 
 SIN_MIN = math.sqrt(CROSS_N2MIN)
 
 INF = float('inf')
 
 NEG_INF = float('-inf')
 
 MAX_FLOAT = float_info.max
 
 MIN_FLOAT = float_info.min
 
 EPSILON = float_info.epsilon
 
 isinf = math.isinf
 

Function Documentation

◆ alpha()

def lsst.geom.geometry.alpha (   r,
  centerPhi,
  phi 
)
Returns the longitude angle alpha of the intersections (alpha, phi),
(-alpha, phi) of the circle centered on (0, centerPhi) with radius r and
the plane z = sin(phi). If there is no intersection, None is returned.
Examples:
forEachPixel.cc.

Definition at line 222 of file geometry.py.

222 def alpha(r, centerPhi, phi):
223  """Returns the longitude angle alpha of the intersections (alpha, phi),
224  (-alpha, phi) of the circle centered on (0, centerPhi) with radius r and
225  the plane z = sin(phi). If there is no intersection, None is returned.
226  """
227  if phi < centerPhi - r or phi > centerPhi + r:
228  return None
229  a = abs(centerPhi - phi)
230  if a <= r - (90.0 - phi) or a <= r - (90.0 + phi):
231  return None
232  p = math.radians(phi)
233  cp = math.radians(centerPhi)
234  x = math.cos(math.radians(r)) - math.sin(cp) * math.sin(cp)
235  u = math.cos(cp) * math.cos(p)
236  y = math.sqrt(abs(u * u - x * x))
237  return math.degrees(abs(math.atan2(y, x)))
238 
239 
Angle abs(Angle const &a)
Definition: Angle.h:106
def alpha(r, centerPhi, phi)
Definition: geometry.py:222

◆ between()

def lsst.geom.geometry.between (   p,
  n,
  v1,
  v2 
)
Tests whether p lies on the shortest great circle arc from cartesian
unit vectors v1 to v2, assuming that p is a unit vector on the plane
defined by the origin, v1 and v2.

Definition at line 329 of file geometry.py.

329 def between(p, n, v1, v2):
330  """Tests whether p lies on the shortest great circle arc from cartesian
331  unit vectors v1 to v2, assuming that p is a unit vector on the plane
332  defined by the origin, v1 and v2.
333  """
334  p1 = cross(n, v1)
335  p2 = cross(n, v2)
336  return dot(p1, p) >= 0.0 and dot(p2, p) <= 0.0
337 
338 
def dot(v1, v2)
Definition: geometry.py:79
def cross(v1, v2)
Definition: geometry.py:85
def between(p, n, v1, v2)
Definition: geometry.py:329

◆ cartesianAngularSep()

def lsst.geom.geometry.cartesianAngularSep (   v1,
  v2 
)
Returns the angular separation in degrees between points v1 and v2,
which must both be specified as cartesian 3-vectors.

Definition at line 260 of file geometry.py.

260 def cartesianAngularSep(v1, v2):
261  """Returns the angular separation in degrees between points v1 and v2,
262  which must both be specified as cartesian 3-vectors.
263  """
264  cs = dot(v1, v2)
265  n = cross(v1, v2)
266  ss = math.sqrt(dot(n, n))
267  if cs == 0.0 and ss == 0.0:
268  return 0.0
269  return math.degrees(math.atan2(ss, cs))
270 
271 
def dot(v1, v2)
Definition: geometry.py:79
def cross(v1, v2)
Definition: geometry.py:85
def cartesianAngularSep(v1, v2)
Definition: geometry.py:260

◆ cartesianUnitVector()

def lsst.geom.geometry.cartesianUnitVector (   args)
Returns a unit cartesian 3-vector corresponding to the input
coordinates, which can be spherical or 3D cartesian. The 2 (spherical)
or 3 (cartesian 3-vector) input coordinates can either be passed
individually or as a tuple/list, and can be of any type convertible
to a float.

Definition at line 141 of file geometry.py.

141 def cartesianUnitVector(*args):
142  """Returns a unit cartesian 3-vector corresponding to the input
143  coordinates, which can be spherical or 3D cartesian. The 2 (spherical)
144  or 3 (cartesian 3-vector) input coordinates can either be passed
145  individually or as a tuple/list, and can be of any type convertible
146  to a float.
147  """
148  if len(args) == 1:
149  args = args[0]
150  if len(args) == 2:
151  theta = math.radians(float(args[0]))
152  phi = math.radians(float(args[1]))
153  cosPhi = math.cos(phi)
154  return (math.cos(theta) * cosPhi,
155  math.sin(theta) * cosPhi,
156  math.sin(phi))
157  elif len(args) == 3:
158  x = float(args[0])
159  y = float(args[1])
160  z = float(args[2])
161  n = math.sqrt(x * x + y * y + z * z)
162  if n == 0.0:
163  raise RuntimeError('Cannot normalize a 3-vector with 0 magnitude')
164  return (x / n, y / n, z / n)
165  raise TypeError('Expecting 2 or 3 coordinates, or a tuple/list ' +
166  'containing 2 or 3 coordinates')
167 
168 
def cartesianUnitVector(args)
Definition: geometry.py:141

◆ centroid()

def lsst.geom.geometry.centroid (   vertices)
Computes the centroid of a set of vertices (which must be passed in
as a list of cartesian unit vectors) on the unit sphere.

Definition at line 316 of file geometry.py.

316 def centroid(vertices):
317  """Computes the centroid of a set of vertices (which must be passed in
318  as a list of cartesian unit vectors) on the unit sphere.
319  """
320  x, y, z = 0.0, 0.0, 0.0
321  # Note: could use more accurate summation routines
322  for v in vertices:
323  x += v[0]
324  y += v[1]
325  z += v[2]
326  return normalize((x, y, z))
327 
328 
def normalize(v)
Definition: geometry.py:99
def centroid(vertices)
Definition: geometry.py:316

◆ clampPhi()

def lsst.geom.geometry.clampPhi (   phi)
Clamps the input latitude angle phi to [-90.0, 90.0] deg.

Definition at line 184 of file geometry.py.

184 def clampPhi(phi):
185  """Clamps the input latitude angle phi to [-90.0, 90.0] deg.
186  """
187  if phi < -90.0:
188  return -90.0
189  elif phi >= 90.0:
190  return 90.0
191  return phi
192 
193 
def clampPhi(phi)
Definition: geometry.py:184

◆ convex()

def lsst.geom.geometry.convex (   vertices)
Tests whether an ordered list of vertices (which must be specified
as cartesian unit vectors) form a spherical convex polygon and determines
their winding order. Returns a 2-tuple as follows:

(True, True):   The vertex list forms a spherical convex polygon and is in
                counter-clockwise order when viewed from outside the unit
                sphere in a right handed coordinate system.
(True, False):  The vertex list forms a spherical convex polygon and is in
                in clockwise order.
(False, msg):   The vertex list does not form a spherical convex polygon -
                msg is a string describing why the test failed.

The algorithm completes in O(n) time, where n is the number of
input vertices.

Definition at line 1782 of file geometry.py.

1782 def convex(vertices):
1783  """Tests whether an ordered list of vertices (which must be specified
1784  as cartesian unit vectors) form a spherical convex polygon and determines
1785  their winding order. Returns a 2-tuple as follows:
1786 
1787  (True, True): The vertex list forms a spherical convex polygon and is in
1788  counter-clockwise order when viewed from outside the unit
1789  sphere in a right handed coordinate system.
1790  (True, False): The vertex list forms a spherical convex polygon and is in
1791  in clockwise order.
1792  (False, msg): The vertex list does not form a spherical convex polygon -
1793  msg is a string describing why the test failed.
1794 
1795  The algorithm completes in O(n) time, where n is the number of
1796  input vertices.
1797  """
1798  if len(vertices) < 3:
1799  return (False, '3 or more vertices must be specified')
1800  if not hemispherical(vertices):
1801  return (False, 'vertices are not hemispherical')
1802  center = centroid(vertices)
1803  windingAngle = 0.0
1804  clockwise = False
1805  counterClockwise = False
1806  p1 = cross(center, vertices[-1])
1807  n2 = dot(p1, p1)
1808  if abs(n2) < CROSS_N2MIN:
1809  return (False, 'centroid of vertices is too close to a vertex')
1810  for i in range(len(vertices)):
1811  beg = vertices[i - 2]
1812  mid = vertices[i - 1]
1813  end = vertices[i]
1814  plane = cross(mid, end)
1815  n2 = dot(plane, plane)
1816  if dot(mid, end) >= COS_MAX or n2 < CROSS_N2MIN:
1817  return (False, 'vertex list contains [near-]duplicates')
1818  plane = invScale(plane, math.sqrt(n2))
1819  d = dot(plane, beg)
1820  if d > SIN_MIN:
1821  if clockwise:
1822  return (False, 'vertices wind around centroid in both ' +
1823  'clockwise and counter-clockwise order')
1824  counterClockwise = True
1825  elif d < -SIN_MIN:
1826  if counterClockwise:
1827  return (False, 'vertices wind around centroid in both ' +
1828  'clockwise and counter-clockwise order')
1829  clockwise = True
1830  # center must be inside polygon formed by vertices if they form a
1831  # convex polygon - an equivalent check is to test that polygon
1832  # vertices always wind around center in the same direction.
1833  d = dot(plane, center)
1834  if d < SIN_MIN and counterClockwise or d > -SIN_MIN and clockwise:
1835  return (False, 'centroid of vertices is not conclusively ' +
1836  'inside all edges')
1837  # sum up winding angle for edge (mid, end)
1838  p2 = cross(center, end)
1839  n2 = dot(p2, p2)
1840  if abs(n2) < CROSS_N2MIN:
1841  return (False, 'centroid of vertices is too close to a vertex')
1842  windingAngle += cartesianAngularSep(p1, p2)
1843  p1 = p2
1844  # For convex polygons, the closest multiple of 360 to
1845  # windingAngle is 1.
1846  m = math.floor(windingAngle / 360.0)
1847  if m == 0.0 and windingAngle > 180.0 or m == 1.0 and windingAngle < 540.0:
1848  return (True, counterClockwise)
1849  return (False, 'vertices do not completely wind around centroid, or ' +
1850  'wind around it multiple times')
1851 
1852 
def dot(v1, v2)
Definition: geometry.py:79
Angle abs(Angle const &a)
Definition: Angle.h:106
def hemispherical(points)
Definition: geometry.py:1740
def invScale(v, s)
Definition: geometry.py:93
def centroid(vertices)
Definition: geometry.py:316
def cross(v1, v2)
Definition: geometry.py:85
def convex(vertices)
Definition: geometry.py:1782
def cartesianAngularSep(v1, v2)
Definition: geometry.py:260

◆ convexHull()

def lsst.geom.geometry.convexHull (   points)
Computes the convex hull (a spherical convex polygon) of an unordered
list of points on the unit sphere, which must be passed in as cartesian
unit vectors. The algorithm takes O(n log n) time, where n is the number
of points.

Definition at line 1853 of file geometry.py.

1853 def convexHull(points):
1854  """Computes the convex hull (a spherical convex polygon) of an unordered
1855  list of points on the unit sphere, which must be passed in as cartesian
1856  unit vectors. The algorithm takes O(n log n) time, where n is the number
1857  of points.
1858  """
1859  if len(points) < 3:
1860  return None
1861  if not hemispherical(points):
1862  return None
1863  center = centroid(points)
1864  maxSep = 0.0
1865  extremum = 0
1866  # Vertex furthest from the center is on the hull
1867  for i in range(len(points)):
1868  sep = cartesianAngularSep(points[i], center)
1869  if sep > maxSep:
1870  extremum = i
1871  maxSep = sep
1872  anchor = points[extremum]
1873  refPlane = cross(center, anchor)
1874  n2 = dot(refPlane, refPlane)
1875  if n2 < CROSS_N2MIN:
1876  # vertex and center are too close
1877  return None
1878  refPlane = invScale(refPlane, math.sqrt(n2))
1879  # Order points by winding angle from the first (extreme) vertex
1880  av = [(0.0, anchor)]
1881  for i in range(0, len(points)):
1882  if i == extremum:
1883  continue
1884  v = points[i]
1885  plane = cross(center, v)
1886  n2 = dot(plane, plane)
1887  if n2 >= CROSS_N2MIN:
1888  plane = invScale(plane, math.sqrt(n2))
1889  p = cross(refPlane, plane)
1890  sa = math.sqrt(dot(p, p))
1891  if dot(p, center) < 0.0:
1892  sa = -sa
1893  angle = math.atan2(sa, dot(refPlane, plane))
1894  if angle < 0.0:
1895  angle += 2.0 * math.pi
1896  av.append((angle, v))
1897  if len(av) < 3:
1898  return None
1899  av.sort(key=lambda t: t[0]) # stable, so av[0] still contains anchor
1900  # Loop over vertices using a Graham scan adapted for spherical geometry.
1901  # Chan's algorithm would be an improvement, but seems likely to be slower
1902  # for small vertex counts (the expected case).
1903  verts = [anchor]
1904  edges = [None]
1905  edge = None
1906  i = 1
1907  while i < len(av):
1908  v = av[i][1]
1909  p = cross(anchor, v)
1910  n2 = dot(p, p)
1911  if dot(anchor, v) < COS_MAX and n2 >= CROSS_N2MIN:
1912  if edge is None:
1913  # Compute first edge
1914  edge = invScale(p, math.sqrt(n2))
1915  verts.append(v)
1916  edges.append(edge)
1917  anchor = v
1918  else:
1919  d = dot(v, edge)
1920  if d > SIN_MIN:
1921  # v is inside the edge defined by the last
1922  # 2 vertices on the hull
1923  edge = invScale(p, math.sqrt(n2))
1924  verts.append(v)
1925  edges.append(edge)
1926  anchor = v
1927  elif d < -SIN_MIN:
1928  # backtrack - the most recently added hull vertex
1929  # is not actually on the hull.
1930  verts.pop()
1931  edges.pop()
1932  anchor = verts[-1]
1933  edge = edges[-1]
1934  # reprocess v to decide whether to add it to the hull
1935  # or whether further backtracking is necessary
1936  continue
1937  # v is coplanar with edge, skip it
1938  i += 1
1939  # Handle backtracking necessary for last edge
1940  if len(verts) < 3:
1941  return None
1942  v = verts[0]
1943  while True:
1944  p = cross(anchor, v)
1945  n2 = dot(p, p)
1946  if dot(anchor, v) < COS_MAX and n2 >= CROSS_N2MIN:
1947  if dot(v, edge) > SIN_MIN:
1948  edges[0] = invScale(p, math.sqrt(n2))
1949  break
1950  verts.pop()
1951  edges.pop()
1952  anchor = verts[-1]
1953  edge = edges[-1]
1954  if len(verts) < 3:
1955  return None
1956  return SphericalConvexPolygon(verts, edges)
1957 
1958 
1959 # -- Generic unit sphere partitioning scheme base class ----
1960 
1961 # TODO: make this an ABC once python 2.6 becomes the default
def dot(v1, v2)
Definition: geometry.py:79
def hemispherical(points)
Definition: geometry.py:1740
def invScale(v, s)
Definition: geometry.py:93
def centroid(vertices)
Definition: geometry.py:316
def cross(v1, v2)
Definition: geometry.py:85
def convexHull(points)
Definition: geometry.py:1853
def cartesianAngularSep(v1, v2)
Definition: geometry.py:260

◆ cross()

def lsst.geom.geometry.cross (   v1,
  v2 
)
Returns the cross product of cartesian 3-vectors v1 and v2.

Definition at line 85 of file geometry.py.

85 def cross(v1, v2):
86  """Returns the cross product of cartesian 3-vectors v1 and v2.
87  """
88  return (v1[1] * v2[2] - v1[2] * v2[1],
89  v1[2] * v2[0] - v1[0] * v2[2],
90  v1[0] * v2[1] - v1[1] * v2[0])
91 
92 
def cross(v1, v2)
Definition: geometry.py:85

◆ dot()

def lsst.geom.geometry.dot (   v1,
  v2 
)
Returns the dot product of cartesian 3-vectors v1 and v2.

Definition at line 79 of file geometry.py.

79 def dot(v1, v2):
80  """Returns the dot product of cartesian 3-vectors v1 and v2.
81  """
82  return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]
83 
84 
def dot(v1, v2)
Definition: geometry.py:79

◆ hemispherical()

def lsst.geom.geometry.hemispherical (   points)
Tests whether a set of points is hemispherical, i.e. whether a plane
exists such that all points are strictly on one side of the plane. The
algorithm used is Megiddo's algorithm for linear programming in R2 and
has run-time O(n), where n is the number of points. Points must be passed
in as a list of cartesian unit vectors.

Definition at line 1740 of file geometry.py.

1740 def hemispherical(points):
1741  """Tests whether a set of points is hemispherical, i.e. whether a plane
1742  exists such that all points are strictly on one side of the plane. The
1743  algorithm used is Megiddo's algorithm for linear programming in R2 and
1744  has run-time O(n), where n is the number of points. Points must be passed
1745  in as a list of cartesian unit vectors.
1746  """
1747  # Check whether the set of linear equations
1748  # x * v[0] + y * v[1] + z * v[2] > 0.0 (for v in points)
1749  # has a solution (x, y, z). If (x,y,z) is a solution (is feasible),
1750  # so is C*(x,y,z), C > 0. Therefore we can fix z to 1, -1 and
1751  # perform 2D feasibility tests.
1752  if _feasible2D(points, 1.0):
1753  return True
1754  if _feasible2D(points, -1.0):
1755  return True
1756  # At this point a feasible solution must have z = 0. Fix y to 1, -1 and
1757  # perform 1D feasibility tests.
1758  if _feasible1D(points, 1.0):
1759  return True
1760  if _feasible1D(points, -1.0):
1761  return True
1762  # At this point a feasible solution must have y = z = 0. If all v[0]
1763  # are non-zero and have the same sign, then there is a feasible solution.
1764  havePos = False
1765  haveNeg = False
1766  for v in points:
1767  if v[0] > 0.0:
1768  if haveNeg:
1769  return False
1770  havePos = True
1771  elif v[0] < 0.0:
1772  if havePos:
1773  return False
1774  haveNeg = True
1775  else:
1776  return False
1777  return True
1778 
1779 
1780 # -- Convexity test and convex hull algorithm ----
1781 
def hemispherical(points)
Definition: geometry.py:1740

◆ invScale()

def lsst.geom.geometry.invScale (   v,
  s 
)
Returns a copy of the cartesian 3-vector v scaled by 1 / s.

Definition at line 93 of file geometry.py.

93 def invScale(v, s):
94  """Returns a copy of the cartesian 3-vector v scaled by 1 / s.
95  """
96  return (v[0] / s, v[1] / s, v[2] / s)
97 
98 
def invScale(v, s)
Definition: geometry.py:93

◆ isinf()

def lsst.geom.geometry.isinf (   x)

Definition at line 73 of file geometry.py.

73  def isinf(x):
74  return x == INF or x == NEG_INF
75 
76 # -- Utility methods ----
77 
78 

◆ maxAlpha()

def lsst.geom.geometry.maxAlpha (   r,
  centerPhi 
)
Computes alpha, the extent in longitude angle [-alpha, alpha] of the
circle with radius r and center (0, centerPhi) on the unit sphere.
Both r and centerPhi are assumed to be in units of degrees.
centerPhi is clamped to lie in the range [-90,90] and r must
lie in the range [0, 90].

Definition at line 240 of file geometry.py.

240 def maxAlpha(r, centerPhi):
241  """Computes alpha, the extent in longitude angle [-alpha, alpha] of the
242  circle with radius r and center (0, centerPhi) on the unit sphere.
243  Both r and centerPhi are assumed to be in units of degrees.
244  centerPhi is clamped to lie in the range [-90,90] and r must
245  lie in the range [0, 90].
246  """
247  assert r >= 0.0 and r <= 90.0
248  if r == 0.0:
249  return 0.0
250  centerPhi = clampPhi(centerPhi)
251  if abs(centerPhi) + r > 90.0 - POLE_EPSILON:
252  return 180.0
253  r = math.radians(r)
254  c = math.radians(centerPhi)
255  y = math.sin(r)
256  x = math.sqrt(abs(math.cos(c - r) * math.cos(c + r)))
257  return math.degrees(abs(math.atan(y / x)))
258 
259 
Angle abs(Angle const &a)
Definition: Angle.h:106
def maxAlpha(r, centerPhi)
Definition: geometry.py:240
def clampPhi(phi)
Definition: geometry.py:184

◆ median()

def lsst.geom.geometry.median (   array)
Finds the median element of the given array in linear time.
Examples:
imageStatistics.cc.

Definition at line 1544 of file geometry.py.

1544 def median(array):
1545  """Finds the median element of the given array in linear time.
1546  """
1547  left = 0
1548  right = len(array)
1549  if right == 0:
1550  return None
1551  k = right >> 1
1552  while True:
1553  i = _medianOfMedians(array, left, right)
1554  i = _partition(array, left, right, i)
1555  if k == i:
1556  return array[k]
1557  elif k < i:
1558  right = i
1559  else:
1560  left = i + 1
1561 
1562 
1563 # -- Testing whether a set of points is hemispherical ----
1564 #
1565 # This test is used by the convexity test and convex hull algorithm. It is
1566 # implemented using Megiddo's algorithm for linear programming in R2, see:
1567 #
1568 # Megiddo, N. 1982. Linear-time algorithms for linear programming in R3 and related problems.
1569 # In Proceedings of the 23rd Annual Symposium on Foundations of Computer Science (November 03 - 05, 1982).
1570 # SFCS. IEEE Computer Society, Washington, DC, 329-338. DOI=
1571 # http://dx.doi.org/10.1109/SFCS.1982.74
1572 
def median(array)
Definition: geometry.py:1544

◆ minEdgeSep()

def lsst.geom.geometry.minEdgeSep (   p,
  n,
  v1,
  v2 
)
Returns the minimum angular separation in degrees between p
and points on the great circle edge with plane normal n and
vertices v1, v2. All inputs must be unit cartesian 3-vectors.

Definition at line 272 of file geometry.py.

272 def minEdgeSep(p, n, v1, v2):
273  """Returns the minimum angular separation in degrees between p
274  and points on the great circle edge with plane normal n and
275  vertices v1, v2. All inputs must be unit cartesian 3-vectors.
276  """
277  p1 = cross(n, v1)
278  p2 = cross(n, v2)
279  if dot(p1, p) >= 0.0 and dot(p2, p) <= 0.0:
280  return abs(90.0 - cartesianAngularSep(p, n))
281  else:
282  return min(cartesianAngularSep(p, v1), cartesianAngularSep(p, v2))
283 
284 
def dot(v1, v2)
Definition: geometry.py:79
Angle abs(Angle const &a)
Definition: Angle.h:106
int min
Definition: Coord.cc:82
def cross(v1, v2)
Definition: geometry.py:85
def minEdgeSep(p, n, v1, v2)
Definition: geometry.py:272
def cartesianAngularSep(v1, v2)
Definition: geometry.py:260

◆ minPhiEdgeSep()

def lsst.geom.geometry.minPhiEdgeSep (   p,
  phi,
  minTheta,
  maxTheta 
)
Returns the minimum angular separation in degrees between p
and points on the small circle edge with constant latitude angle
phi and vertices (minTheta, phi), (maxTheta, phi). p must be in
spherical coordinates.

Definition at line 285 of file geometry.py.

285 def minPhiEdgeSep(p, phi, minTheta, maxTheta):
286  """Returns the minimum angular separation in degrees between p
287  and points on the small circle edge with constant latitude angle
288  phi and vertices (minTheta, phi), (maxTheta, phi). p must be in
289  spherical coordinates.
290  """
291  if minTheta > maxTheta:
292  if p[0] >= minTheta or p[0] <= maxTheta:
293  return abs(p[1] - phi)
294  else:
295  if p[0] >= minTheta and p[0] <= maxTheta:
296  return abs(p[1] - phi)
297  return min(sphericalAngularSep(p, (minTheta, phi)),
298  sphericalAngularSep(p, (maxTheta, phi)))
299 
300 
Angle abs(Angle const &a)
Definition: Angle.h:106
int min
Definition: Coord.cc:82
def minPhiEdgeSep(p, phi, minTheta, maxTheta)
Definition: geometry.py:285
def sphericalAngularSep(p1, p2)
Definition: geometry.py:169

◆ minThetaEdgeSep()

def lsst.geom.geometry.minThetaEdgeSep (   p,
  theta,
  minPhi,
  maxPhi 
)
Returns the minimum angular separation in degrees between p
and points on the great circle edge with constant longitude angle
theta and vertices (theta, minPhi), (theta, maxPhi). p must be a
unit cartesian 3-vector.

Definition at line 301 of file geometry.py.

301 def minThetaEdgeSep(p, theta, minPhi, maxPhi):
302  """Returns the minimum angular separation in degrees between p
303  and points on the great circle edge with constant longitude angle
304  theta and vertices (theta, minPhi), (theta, maxPhi). p must be a
305  unit cartesian 3-vector.
306  """
307  v1 = cartesianUnitVector(theta, minPhi)
308  v2 = cartesianUnitVector(theta, maxPhi)
309  n = cross(v1, v2)
310  d2 = dot(n, n)
311  if d2 == 0.0:
312  return min(cartesianAngularSep(p, v1), cartesianAngularSep(p, v2))
313  return minEdgeSep(p, invScale(n, math.sqrt(d2)), v1, v2)
314 
315 
def dot(v1, v2)
Definition: geometry.py:79
def invScale(v, s)
Definition: geometry.py:93
def minThetaEdgeSep(p, theta, minPhi, maxPhi)
Definition: geometry.py:301
int min
Definition: Coord.cc:82
def cross(v1, v2)
Definition: geometry.py:85
def minEdgeSep(p, n, v1, v2)
Definition: geometry.py:272
def cartesianUnitVector(args)
Definition: geometry.py:141
def cartesianAngularSep(v1, v2)
Definition: geometry.py:260

◆ normalize()

def lsst.geom.geometry.normalize (   v)
Returns a normalized copy of the cartesian 3-vector v.

Definition at line 99 of file geometry.py.

99 def normalize(v):
100  """Returns a normalized copy of the cartesian 3-vector v.
101  """
102  n = math.sqrt(dot(v, v))
103  if n == 0.0:
104  raise RuntimeError('Cannot normalize a 3-vector with 0 magnitude')
105  return (v[0] / n, v[1] / n, v[2] / n)
106 
107 
def normalize(v)
Definition: geometry.py:99
def dot(v1, v2)
Definition: geometry.py:79

◆ northEast()

def lsst.geom.geometry.northEast (   v)
Returns unit N,E basis vectors for a point v, which must be a
cartesian 3-vector.

Definition at line 205 of file geometry.py.

205 def northEast(v):
206  """Returns unit N,E basis vectors for a point v, which must be a
207  cartesian 3-vector.
208  """
209  north = (-v[0] * v[2],
210  -v[1] * v[2],
211  v[0] * v[0] + v[1] * v[1])
212  if north == (0.0, 0.0, 0.0):
213  # pick an arbitrary orthogonal basis with z = 0
214  north = (-1.0, 0.0, 0.0)
215  east = (0.0, 1.0, 0.0)
216  else:
217  north = normalize(north)
218  east = normalize(cross(north, v))
219  return north, east
220 
221 
def normalize(v)
Definition: geometry.py:99
def cross(v1, v2)
Definition: geometry.py:85

◆ reduceTheta()

def lsst.geom.geometry.reduceTheta (   theta)
Range reduces the given longitude angle to lie in the range
[0.0, 360.0).

Definition at line 194 of file geometry.py.

194 def reduceTheta(theta):
195  """Range reduces the given longitude angle to lie in the range
196  [0.0, 360.0).
197  """
198  theta = math.fmod(theta, 360.0)
199  if theta < 0.0:
200  return theta + 360.0
201  else:
202  return theta
203 
204 
def reduceTheta(theta)
Definition: geometry.py:194

◆ segments()

def lsst.geom.geometry.segments (   phiMin,
  phiMax,
  width 
)
Computes the number of segments to divide the given latitude angle
range [phiMin, phiMax] (degrees) into. Two points within the range
separated by at least one segment are guaranteed to have angular
separation of at least width degrees.

Definition at line 339 of file geometry.py.

339 def segments(phiMin, phiMax, width):
340  """Computes the number of segments to divide the given latitude angle
341  range [phiMin, phiMax] (degrees) into. Two points within the range
342  separated by at least one segment are guaranteed to have angular
343  separation of at least width degrees.
344  """
345  p = max(abs(phiMin), abs(phiMax))
346  if p > 90.0 - 1.0 * DEG_PER_ARCSEC:
347  return 1
348  if width >= 180.0:
349  return 1
350  elif width < 1.0 * DEG_PER_ARCSEC:
351  width = 1.0 * DEG_PER_ARCSEC
352  p = math.radians(p)
353  cw = math.cos(math.radians(width))
354  sp = math.sin(p)
355  cp = math.cos(p)
356  x = cw - sp * sp
357  u = cp * cp
358  y = math.sqrt(abs(u * u - x * x))
359  return int(math.floor((2.0 * math.pi) / abs(math.atan2(y, x))))
360 
361 
362 # -- Regions on the unit sphere ----
363 
364 # TODO: make this an ABC once python 2.6 becomes the default
Angle abs(Angle const &a)
Definition: Angle.h:106
int max
Definition: BoundedField.cc:99
def segments(phiMin, phiMax, width)
Definition: geometry.py:339

◆ sphericalAngularSep()

def lsst.geom.geometry.sphericalAngularSep (   p1,
  p2 
)
Returns the angular separation in degrees between points p1 and p2,
which must both be specified in spherical coordinates. The implementation
uses the halversine distance formula.

Definition at line 169 of file geometry.py.

169 def sphericalAngularSep(p1, p2):
170  """Returns the angular separation in degrees between points p1 and p2,
171  which must both be specified in spherical coordinates. The implementation
172  uses the halversine distance formula.
173  """
174  sdt = math.sin(math.radians(p1[0] - p2[0]) * 0.5)
175  sdp = math.sin(math.radians(p1[1] - p2[1]) * 0.5)
176  cc = math.cos(math.radians(p1[1])) * math.cos(math.radians(p2[1]))
177  s = math.sqrt(sdp * sdp + cc * sdt * sdt)
178  if s > 1.0:
179  return 180.0
180  else:
181  return 2.0 * math.degrees(math.asin(s))
182 
183 
def sphericalAngularSep(p1, p2)
Definition: geometry.py:169

◆ sphericalCoords()

def lsst.geom.geometry.sphericalCoords (   args)
Returns spherical coordinates in degrees for the input coordinates,
which can be spherical or 3D cartesian. The 2 (spherical) or 3
(cartesian 3-vector) inputs can be passed either individually
or as a tuple/list, and can be of any type convertible to a float.

Definition at line 108 of file geometry.py.

108 def sphericalCoords(*args):
109  """Returns spherical coordinates in degrees for the input coordinates,
110  which can be spherical or 3D cartesian. The 2 (spherical) or 3
111  (cartesian 3-vector) inputs can be passed either individually
112  or as a tuple/list, and can be of any type convertible to a float.
113  """
114  if len(args) == 1:
115  args = args[0]
116  if len(args) == 2:
117  t = (float(args[0]), float(args[1]))
118  if t[1] < -90.0 or t[1] > 90.0:
119  raise RuntimeError('Latitude angle is out of bounds')
120  return t
121  elif len(args) == 3:
122  x = float(args[0])
123  y = float(args[1])
124  z = float(args[2])
125  d2 = x * x + y * y
126  if d2 == 0.0:
127  theta = 0.0
128  else:
129  theta = math.degrees(math.atan2(y, x))
130  if theta < 0.0:
131  theta += 360.0
132  if z == 0.0:
133  phi = 0.0
134  else:
135  phi = math.degrees(math.atan2(z, math.sqrt(d2)))
136  return (theta, phi)
137  raise TypeError('Expecting 2 or 3 coordinates, or a tuple/list ' +
138  'containing 2 or 3 coordinates')
139 
140 
def sphericalCoords(args)
Definition: geometry.py:108

Variable Documentation

◆ ANGLE_EPSILON

float lsst.geom.geometry.ANGLE_EPSILON = 0.001 * DEG_PER_ARCSEC

Definition at line 37 of file geometry.py.

◆ ARCSEC_PER_DEG

float lsst.geom.geometry.ARCSEC_PER_DEG = 3600.0

Definition at line 33 of file geometry.py.

◆ COS_MAX

float lsst.geom.geometry.COS_MAX = 1.0 - 1.0e-15

Definition at line 44 of file geometry.py.

◆ CROSS_N2MIN

int lsst.geom.geometry.CROSS_N2MIN = 2e-15

Definition at line 48 of file geometry.py.

◆ DEG_PER_ARCSEC

float lsst.geom.geometry.DEG_PER_ARCSEC = 1.0 / 3600.0

Definition at line 34 of file geometry.py.

◆ EPSILON

float lsst.geom.geometry.EPSILON = float_info.epsilon

Definition at line 62 of file geometry.py.

◆ INF

lsst.geom.geometry.INF = float('inf')

Definition at line 55 of file geometry.py.

◆ isinf

lsst.geom.geometry.isinf = math.isinf

Definition at line 71 of file geometry.py.

◆ MAX_FLOAT

float lsst.geom.geometry.MAX_FLOAT = float_info.max

Definition at line 60 of file geometry.py.

◆ MIN_FLOAT

float lsst.geom.geometry.MIN_FLOAT = float_info.min

Definition at line 61 of file geometry.py.

◆ NEG_INF

lsst.geom.geometry.NEG_INF = float('-inf')

Definition at line 56 of file geometry.py.

◆ POLE_EPSILON

float lsst.geom.geometry.POLE_EPSILON = 1.0 * DEG_PER_ARCSEC

Definition at line 40 of file geometry.py.

◆ SIN_MIN

lsst.geom.geometry.SIN_MIN = math.sqrt(CROSS_N2MIN)

Definition at line 52 of file geometry.py.