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
Public Member Functions | Public Attributes | List of all members
lsst.geom.geometry.SphericalConvexPolygon Class Reference
Inheritance diagram for lsst.geom.geometry.SphericalConvexPolygon:
lsst.geom.geometry.SphericalRegion

Public Member Functions

def __init__ (self, args)
 
def getVertices (self)
 
def getEdges (self)
 
def getBoundingCircle (self)
 
def getBoundingBox (self)
 
def getZRange (self)
 
def clip (self, plane)
 
def intersect (self, poly)
 
def area (self)
 
def containsPoint (self, v)
 
def contains (self, pointOrRegion)
 
def intersects (self, pointOrRegion)
 
def __repr__ (self)
 
def __eq__ (self, other)
 
def __hash__ (self)
 

Public Attributes

 boundingBox
 
 boundingCircle
 
 vertices
 
 edges
 

Detailed Description

A convex polygon on the unit sphere with great circle edges. Points
falling exactly on polygon edges are considered to be inside (contained
by) the polygon.

Definition at line 1110 of file geometry.py.

Constructor & Destructor Documentation

◆ __init__()

def lsst.geom.geometry.SphericalConvexPolygon.__init__ (   self,
  args 
)
Creates a new polygon. Arguments must be either:

1. a SphericalConvexPolygon
2. a list of vertices
3. a list of vertices and a list of corresponding edges

In the first case, a copy is constructed. In the second case,
the argument must be a sequence of 3 element tuples/lists
(unit cartesian 3-vectors) - a copy of the vertices is stored
and polygon edges are computed. In the last case, copies of the
input vertex and edge lists are stored.

Vertices must be hemispherical and in counter-clockwise order when
viewed from outside the unit sphere in a right handed coordinate
system. They must also form a convex polygon.

When edges are specified, the i-th edge must correspond to the plane
equation of great circle connecting vertices (i - 1, i), that is,
the edge should be a unit cartesian 3-vector parallel to v[i-1] ^ v[i]
(where ^ denotes the vector cross product).

Note that these conditions are NOT verified for performance reasons.
Operations on SphericalConvexPolygon objects constructed with inputs
not satisfying these conditions are undefined. Use the convex()
function to check for convexity and ordering of the vertices. Or,
use the convexHull() function to create a SphericalConvexPolygon
from an arbitrary list of hemispherical input vertices.

Definition at line 1116 of file geometry.py.

1116  def __init__(self, *args):
1117  """Creates a new polygon. Arguments must be either:
1118 
1119  1. a SphericalConvexPolygon
1120  2. a list of vertices
1121  3. a list of vertices and a list of corresponding edges
1122 
1123  In the first case, a copy is constructed. In the second case,
1124  the argument must be a sequence of 3 element tuples/lists
1125  (unit cartesian 3-vectors) - a copy of the vertices is stored
1126  and polygon edges are computed. In the last case, copies of the
1127  input vertex and edge lists are stored.
1128 
1129  Vertices must be hemispherical and in counter-clockwise order when
1130  viewed from outside the unit sphere in a right handed coordinate
1131  system. They must also form a convex polygon.
1132 
1133  When edges are specified, the i-th edge must correspond to the plane
1134  equation of great circle connecting vertices (i - 1, i), that is,
1135  the edge should be a unit cartesian 3-vector parallel to v[i-1] ^ v[i]
1136  (where ^ denotes the vector cross product).
1137 
1138  Note that these conditions are NOT verified for performance reasons.
1139  Operations on SphericalConvexPolygon objects constructed with inputs
1140  not satisfying these conditions are undefined. Use the convex()
1141  function to check for convexity and ordering of the vertices. Or,
1142  use the convexHull() function to create a SphericalConvexPolygon
1143  from an arbitrary list of hemispherical input vertices.
1144  """
1145  self.boundingBox = None
1146  self.boundingCircle = None
1147  if len(args) == 0:
1148  raise RuntimeError('Expecting at least one argument')
1149  elif len(args) == 1:
1150  if isinstance(args[0], SphericalConvexPolygon):
1151  self.vertices = tuple(args[0].vertices)
1152  self.edges = tuple(args[0].edges)
1153  else:
1154  self.vertices = tuple(args[0])
1155  self._computeEdges()
1156  elif len(args) == 2:
1157  self.vertices = tuple(args[0])
1158  self.edges = tuple(args[1])
1159  if len(self.edges) != len(self.vertices):
1160  raise RuntimeError(
1161  'number of edges does not match number of vertices')
1162  else:
1163  self.vertices = tuple(args)
1164  self._computeEdges()
1165  if len(self.vertices) < 3:
1166  raise RuntimeError(
1167  'spherical polygon must contain at least 3 vertices')
1168 
def __init__(self, minimum, dataRange, Q)
Definition: rgb.py:414

Member Function Documentation

◆ __eq__()

def lsst.geom.geometry.SphericalConvexPolygon.__eq__ (   self,
  other 
)

Definition at line 1456 of file geometry.py.

1456  def __eq__(self, other):
1457  if not isinstance(other, SphericalConvexPolygon):
1458  return False
1459  n = len(self.vertices)
1460  if n != len(other.vertices):
1461  return False
1462  # Test for equality up to cyclic permutation of vertices/edges
1463  try:
1464  offset = other.vertices.index(self.vertices[0])
1465  except ValueError:
1466  return False
1467  for i in range(0, n):
1468  j = offset + i
1469  if j >= n:
1470  j -= n
1471  if (self.vertices[i] != self.vertices[j] or
1472  self.edges[i] != self.edges[j]):
1473  return False
1474  return True
1475 

◆ __hash__()

def lsst.geom.geometry.SphericalConvexPolygon.__hash__ (   self)

Definition at line 1476 of file geometry.py.

1476  def __hash__(self):
1477  return hash((self.vertices, self.edges))
1478 
1479 # -- Finding the median element of an array in linear time ----
1480 #
1481 # This is a necessary primitive for Megiddo's linear time
1482 # 2d linear programming algorithm.
1483 

◆ __repr__()

def lsst.geom.geometry.SphericalConvexPolygon.__repr__ (   self)
Returns a string representation of this polygon.

Definition at line 1450 of file geometry.py.

1450  def __repr__(self):
1451  """Returns a string representation of this polygon.
1452  """
1453  return ''.join([self.__class__.__name__, '(',
1454  repr(map(sphericalCoords, self.vertices)), ')'])
1455 

◆ area()

def lsst.geom.geometry.SphericalConvexPolygon.area (   self)
Returns the area of this spherical convex polygon.

Definition at line 1314 of file geometry.py.

1314  def area(self):
1315  """Returns the area of this spherical convex polygon.
1316  """
1317  numVerts = len(self.vertices)
1318  angleSum = 0.0
1319  for i in range(numVerts):
1320  tmp = cross(self.edges[i - 1], self.edges[i])
1321  sina = math.sqrt(dot(tmp, tmp))
1322  cosa = -dot(self.edges[i - 1], self.edges[i])
1323  a = math.atan2(sina, cosa)
1324  angleSum += a
1325  return angleSum - (numVerts - 2) * math.pi
1326 
def dot(v1, v2)
Definition: geometry.py:79
def cross(v1, v2)
Definition: geometry.py:85

◆ clip()

def lsst.geom.geometry.SphericalConvexPolygon.clip (   self,
  plane 
)
Returns the polygon corresponding to the intersection of this
polygon with the positive half space defined by the given plane.
The plane must be specified with a cartesian unit vector (its
normal) and always passes through the origin.

Clipping is performed using the Sutherland-Hodgman algorithm,
adapted for spherical polygons.

Definition at line 1220 of file geometry.py.

1220  def clip(self, plane):
1221  """Returns the polygon corresponding to the intersection of this
1222  polygon with the positive half space defined by the given plane.
1223  The plane must be specified with a cartesian unit vector (its
1224  normal) and always passes through the origin.
1225 
1226  Clipping is performed using the Sutherland-Hodgman algorithm,
1227  adapted for spherical polygons.
1228  """
1229  vertices, edges, classification = [], [], []
1230  vin, vout = False, False
1231  for i in range(len(self.vertices)):
1232  d = dot(plane, self.vertices[i])
1233  if d > SIN_MIN:
1234  vin = True
1235  elif d < -SIN_MIN:
1236  vout = True
1237  else:
1238  d = 0.0
1239  classification.append(d)
1240  if not vin and not vout:
1241  # polygon and clipping plane are coplanar
1242  return None
1243  if not vout:
1244  return self
1245  elif not vin:
1246  return None
1247  v0 = self.vertices[-1]
1248  d0 = classification[-1]
1249  for i in range(len(self.vertices)):
1250  v1 = self.vertices[i]
1251  d1 = classification[i]
1252  if d0 > 0.0:
1253  if d1 >= 0.0:
1254  # positive to positive, positive to zero: no intersection,
1255  # add current input vertex to output polygon
1256  vertices.append(v1)
1257  edges.append(self.edges[i])
1258  else:
1259  # positive to negative: add intersection point to polygon
1260  f = d0 / (d0 - d1)
1261  v = normalize((v0[0] + (v1[0] - v0[0]) * f,
1262  v0[1] + (v1[1] - v0[1]) * f,
1263  v0[2] + (v1[2] - v0[2]) * f))
1264  vertices.append(v)
1265  edges.append(self.edges[i])
1266  elif d0 == 0.0:
1267  if d1 >= 0.0:
1268  # zero to positive: no intersection, add current input
1269  # vertex to output polygon.
1270  vertices.append(v1)
1271  edges.append(self.edges[i])
1272  # zero to zero: coplanar edge - since the polygon has vertices
1273  # on both sides of plane, this implies concavity or a
1274  # duplicate vertex. Under the convexity assumption, this
1275  # must be caused by a near duplicate vertex, so skip the
1276  # vertex.
1277  #
1278  # zero to negative: no intersection, skip the vertex
1279  else:
1280  if d1 > 0.0:
1281  # negative to positive: add intersection point to output
1282  # polygon followed by the current input vertex
1283  f = d0 / (d0 - d1)
1284  v = normalize((v0[0] + (v1[0] - v0[0]) * f,
1285  v0[1] + (v1[1] - v0[1]) * f,
1286  v0[2] + (v1[2] - v0[2]) * f))
1287  vertices.append(v)
1288  edges.append(tuple(plane))
1289  vertices.append(v1)
1290  edges.append(self.edges[i])
1291  elif d1 == 0.0:
1292  # negative to zero: add current input vertex to output
1293  # polygon
1294  vertices.append(v1)
1295  edges.append(tuple(plane))
1296  # negative to negative: no intersection, skip vertex
1297  v0 = v1
1298  d0 = d1
1299  return SphericalConvexPolygon(vertices, edges)
1300 
def normalize(v)
Definition: geometry.py:99
def dot(v1, v2)
Definition: geometry.py:79

◆ contains()

def lsst.geom.geometry.SphericalConvexPolygon.contains (   self,
  pointOrRegion 
)
Returns True if the specified point or spherical region is
completely contained in this polygon. Note that the implementation
is conservative where ellipses are concerned: False may be returned
for an ellipse that is actually completely contained by this polygon.

Definition at line 1333 of file geometry.py.

1333  def contains(self, pointOrRegion):
1334  """Returns True if the specified point or spherical region is
1335  completely contained in this polygon. Note that the implementation
1336  is conservative where ellipses are concerned: False may be returned
1337  for an ellipse that is actually completely contained by this polygon.
1338  """
1339  pr = pointOrRegion
1340  if isinstance(pr, SphericalConvexPolygon):
1341  for v in pr.getVertices():
1342  if not self.containsPoint(v):
1343  return False
1344  return True
1345  elif isinstance(pr, SphericalEllipse):
1346  return self.contains(pr.getBoundingCircle())
1347  elif isinstance(pr, SphericalCircle):
1348  cv = cartesianUnitVector(pr.getCenter())
1349  if not self.containsPoint(cv):
1350  return False
1351  else:
1352  minSep = INF
1353  for i in range(len(self.vertices)):
1354  s = minEdgeSep(cv, self.edges[i],
1355  self.vertices[i - 1], self.vertices[i])
1356  minSep = min(minSep, s)
1357  return minSep >= pr.getRadius()
1358  elif isinstance(pr, SphericalBox):
1359  # check that all box vertices are inside the polygon
1360  bMin, bMax = pr.getMin(), pr.getMax()
1361  bzMin = math.sin(math.radians(bMin[1]))
1362  bzMax = math.sin(math.radians(bMax[1]))
1363  verts = map(cartesianUnitVector,
1364  (bMin, bMax, (bMin[0], bMax[1]), (bMax[0], bMin[1])))
1365  for v in verts:
1366  if not self.containsPoint(v):
1367  return False
1368  # check that intersections of box small circles with polygon
1369  # edges either don't exist or fall outside the box.
1370  for i in range(len(self.vertices)):
1371  v0 = self.vertices[i - 1]
1372  v1 = self.vertices[i]
1373  e = self.edges[i]
1374  d = e[0] * e[0] + e[1] * e[1]
1375  if abs(e[2]) >= COS_MAX or d < MIN_FLOAT:
1376  # polygon edge is approximately described by z = +/-1.
1377  # box vertices are inside the polygon, so they
1378  # cannot intersect the edge.
1379  continue
1380  D = d - bzMin * bzMin
1381  if D >= 0.0:
1382  # polygon edge intersects z = bzMin
1383  D = math.sqrt(D)
1384  xr = -e[0] * e[2] * bzMin
1385  yr = -e[1] * e[2] * bzMin
1386  i1 = ((xr + e[1] * D) / d, (yr - e[0] * D) / d, bzMin)
1387  i2 = ((xr - e[1] * D) / d, (yr + e[0] * D) / d, bzMin)
1388  if (pr.containsPoint(sphericalCoords(i1)) or
1389  pr.containsPoint(sphericalCoords(i2))):
1390  return False
1391  D = d - bzMax * bzMax
1392  if D >= 0.0:
1393  # polygon edge intersects z = bzMax
1394  D = math.sqrt(D)
1395  xr = -e[0] * e[2] * bzMax
1396  yr = -e[1] * e[2] * bzMax
1397  i1 = ((xr + e[1] * D) / d, (yr - e[0] * D) / d, bzMax)
1398  i2 = ((xr - e[1] * D) / d, (yr + e[0] * D) / d, bzMax)
1399  if (pr.containsPoint(sphericalCoords(i1)) or
1400  pr.containsPoint(sphericalCoords(i2))):
1401  return False
1402  return True
1403  else:
1404  return self.containsPoint(cartesianUnitVector(pr))
1405 
Angle abs(Angle const &a)
Definition: Angle.h:106
bool contains(VertexIterator const begin, VertexIterator const end, UnitVector3d const &v)
int min
Definition: Coord.cc:82
def sphericalCoords(args)
Definition: geometry.py:108
def minEdgeSep(p, n, v1, v2)
Definition: geometry.py:272
def cartesianUnitVector(args)
Definition: geometry.py:141

◆ containsPoint()

def lsst.geom.geometry.SphericalConvexPolygon.containsPoint (   self,
  v 
)

Definition at line 1327 of file geometry.py.

1327  def containsPoint(self, v):
1328  for e in self.edges:
1329  if dot(v, e) < 0.0:
1330  return False
1331  return True
1332 
def dot(v1, v2)
Definition: geometry.py:79

◆ getBoundingBox()

def lsst.geom.geometry.SphericalConvexPolygon.getBoundingBox (   self)
Returns a bounding box for this spherical convex polygon.

Definition at line 1202 of file geometry.py.

1202  def getBoundingBox(self):
1203  """Returns a bounding box for this spherical convex polygon.
1204  """
1205  if self.boundingBox is None:
1206  self.boundingBox = SphericalBox()
1207  for i in range(0, len(self.vertices)):
1208  self.boundingBox.extend(SphericalBox.edge(
1209  self.vertices[i - 1], self.vertices[i], self.edges[i]))
1210  return self.boundingBox
1211 

◆ getBoundingCircle()

def lsst.geom.geometry.SphericalConvexPolygon.getBoundingCircle (   self)
Returns a bounding circle (not necessarily minimal) for this
spherical convex polygon.

Definition at line 1190 of file geometry.py.

1190  def getBoundingCircle(self):
1191  """Returns a bounding circle (not necessarily minimal) for this
1192  spherical convex polygon.
1193  """
1194  if self.boundingCircle is None:
1195  center = centroid(self.vertices)
1196  radius = 0.0
1197  for v in self.vertices:
1198  radius = max(radius, cartesianAngularSep(center, v))
1199  self.boundingCircle = SphericalCircle(center, radius)
1200  return self.boundingCircle
1201 
def centroid(vertices)
Definition: geometry.py:316
int max
Definition: BoundedField.cc:99
def cartesianAngularSep(v1, v2)
Definition: geometry.py:260

◆ getEdges()

def lsst.geom.geometry.SphericalConvexPolygon.getEdges (   self)
Returns the list of polygon edges. The i-th edge is the plane
equation for the great circle edge formed by vertices i-1 and i.

Definition at line 1184 of file geometry.py.

1184  def getEdges(self):
1185  """Returns the list of polygon edges. The i-th edge is the plane
1186  equation for the great circle edge formed by vertices i-1 and i.
1187  """
1188  return self.edges
1189 

◆ getVertices()

def lsst.geom.geometry.SphericalConvexPolygon.getVertices (   self)
Returns the list of polygon vertices.

Definition at line 1179 of file geometry.py.

1179  def getVertices(self):
1180  """Returns the list of polygon vertices.
1181  """
1182  return self.vertices
1183 

◆ getZRange()

def lsst.geom.geometry.SphericalConvexPolygon.getZRange (   self)
Returns the z coordinate range spanned by this spherical
convex polygon.

Definition at line 1212 of file geometry.py.

1212  def getZRange(self):
1213  """Returns the z coordinate range spanned by this spherical
1214  convex polygon.
1215  """
1216  bbox = self.getBoundingBox()
1217  return (math.sin(math.radians(bbox.getMin()[1])),
1218  math.sin(math.radians(bbox.getMax()[1])))
1219 

◆ intersect()

def lsst.geom.geometry.SphericalConvexPolygon.intersect (   self,
  poly 
)
Returns the intersection of poly with this polygon, or
None if the intersection does not exist.

Definition at line 1301 of file geometry.py.

1301  def intersect(self, poly):
1302  """Returns the intersection of poly with this polygon, or
1303  None if the intersection does not exist.
1304  """
1305  if not isinstance(poly, SphericalConvexPolygon):
1306  raise TypeError('Expecting a SphericalConvexPolygon object')
1307  p = self
1308  for edge in poly.getEdges():
1309  p = p.clip(edge)
1310  if p is None:
1311  break
1312  return p
1313 

◆ intersects()

def lsst.geom.geometry.SphericalConvexPolygon.intersects (   self,
  pointOrRegion 
)
Returns True if the given point or spherical region intersects
this polygon. Note that the implementation is conservative where
ellipses are concerned: True may be returned for an ellipse that
is actually disjoint from this polygon.

Definition at line 1406 of file geometry.py.

1406  def intersects(self, pointOrRegion):
1407  """Returns True if the given point or spherical region intersects
1408  this polygon. Note that the implementation is conservative where
1409  ellipses are concerned: True may be returned for an ellipse that
1410  is actually disjoint from this polygon.
1411  """
1412  pr = pointOrRegion
1413  if isinstance(pr, SphericalConvexPolygon):
1414  return self.intersect(pr) is not None
1415  elif isinstance(pr, SphericalEllipse):
1416  return self.intersects(pr.getBoundingCircle())
1417  elif isinstance(pr, SphericalCircle):
1418  cv = cartesianUnitVector(pr.getCenter())
1419  if self.containsPoint(cv):
1420  return True
1421  else:
1422  minSep = INF
1423  for i in range(len(self.vertices)):
1424  s = minEdgeSep(cv, self.edges[i],
1425  self.vertices[i - 1], self.vertices[i])
1426  minSep = min(minSep, s)
1427  return minSep <= pr.getRadius()
1428  elif isinstance(pr, SphericalBox):
1429  minTheta = math.radians(pr.getMin()[0])
1430  maxTheta = math.radians(pr.getMax()[0])
1431  bzMin = math.sin(math.radians(pr.getMin()[1]))
1432  bzMax = math.sin(math.radians(pr.getMax()[1]))
1433  p = self.clip((-math.sin(minTheta), math.cos(minTheta), 0.0))
1434  if pr.getThetaExtent() > 180.0:
1435  if p is not None:
1436  zMin, zMax = p.getZRange()
1437  if zMin <= bzMax and zMax >= bzMin:
1438  return True
1439  p = self.clip((math.sin(maxTheta), -math.cos(maxTheta), 0.0))
1440  else:
1441  if p is not None:
1442  p = p.clip((math.sin(maxTheta), -math.cos(maxTheta), 0.0))
1443  if p is None:
1444  return False
1445  zMin, zMax = p.getZRange()
1446  return zMin <= bzMax and zMax >= bzMin
1447  else:
1448  return self.containsPoint(cartesianUnitVector(pr))
1449 
int min
Definition: Coord.cc:82
def minEdgeSep(p, n, v1, v2)
Definition: geometry.py:272
def cartesianUnitVector(args)
Definition: geometry.py:141

Member Data Documentation

◆ boundingBox

lsst.geom.geometry.SphericalConvexPolygon.boundingBox

Definition at line 1145 of file geometry.py.

◆ boundingCircle

lsst.geom.geometry.SphericalConvexPolygon.boundingCircle

Definition at line 1146 of file geometry.py.

◆ edges

lsst.geom.geometry.SphericalConvexPolygon.edges

Definition at line 1152 of file geometry.py.

◆ vertices

lsst.geom.geometry.SphericalConvexPolygon.vertices

Definition at line 1151 of file geometry.py.


The documentation for this class was generated from the following file: