3 Commits 0cef84bcaa ... 9062c9e6d0

Author SHA1 Message Date
  Christian Proust 9062c9e6d0 Add a function to see if a panorama is visible 9 years ago
  Christian Proust 98b4dc29e4 Add methods to find the cap_min and cap_max of a Panorama 9 years ago
  Christian Proust 7aaba09cbb Add str representation for Reference 9 years ago
1 changed files with 58 additions and 0 deletions
  1. 58 0
      panorama/models.py

+ 58 - 0
panorama/models.py

@@ -213,10 +213,61 @@ class Panorama(ReferencePoint):
                  "elevation": self.elevation(r.reference_point)}
                 for r in self.panorama_references.all()]
 
+    def is_visible(self, point):
+        """Return True if the Panorama can see the point."""
+        cap = self.bearing(point) % 360
+        cap_min = self.cap_min()
+        cap_max = self.cap_max()
+        if cap_min < cap_max:
+            # Nominal case
+            return cap_min <= cap <= cap_max
+        else:
+            return cap_min <= cap or cap <= cap_max
+
+    def cap_min(self):
+        return self._cap_minmax(True)
+
+    def cap_max(self):
+        return self._cap_minmax(False)
+
+    def _cap_minmax(self, ismin=True):
+        """Return the cap on the border of the image.
+
+        :param ismin: True if the min cap should be processed False if it is the
+        max.
+
+        @return None if the image is looping or if the image have less than two
+        references.
+        """
+        if self.loop:
+            return None
+
+        it = self.panorama_references.order_by(
+                'x' if ismin else '-x').iterator()
+
+        try:
+            ref1 = next(it)
+            ref2 = next(it)
+        except StopIteration:
+            return None
+
+        cap1 = self.bearing(ref1.reference_point)
+        cap2 = self.bearing(ref2.reference_point)
+        target_x = 0 if ismin else self.image_width
+
+        # For circulary issues
+        if cap2 < cap1:
+            cap2 += 360
+
+        target_cap =  cap1 + (target_x - ref1.x) * (cap2 - cap1) / \
+                (ref2.x - ref1.x)
+        return target_cap % 360
+
     def __str__(self):
         return "Panorama : " + self.name
 
 
+@python_2_unicode_compatible
 class Reference(models.Model):
     """A reference is made of a Panorama, a Reference Point, and the position
     (x, y) of the reference point inside the image.  With enough
@@ -251,3 +302,10 @@ class Reference(models.Model):
                                       y=self.y,
                                       width=w,
                                       height=h))
+
+    def __str__(self):
+        return '{ref}: at {xy} in {pano}'.format(
+                pano=self.panorama.name,
+                xy=(self.x, self.y),
+                ref=self.reference_point.name,
+                )