示例#1
0
    def test_migration_seed_data_correctly(self):
        longitude = 120.1
        latitude = 23.234
        radius_km = 1

        distance = 6371 * ACos(
            Cos(Radians(latitude)) * Cos(Radians("lat")) *
            Cos(Radians("lng") - Radians(longitude)) +
            Sin(Radians(latitude)) * Sin(Radians("lat")))

        factories = Factory.objects.annotate(distance=distance).filter(
            distance__lt=radius_km)

        self.assertEqual(
            set([factory.name for factory in factories]),
            set([
                "既有違章工廠 No.2",
                "既有違章工廠 No.3",
                "既有違章工廠 No.8",
                "既有違章工廠 No.9",
                "既有違章工廠 No.10",
                "既有違章工廠 No.11",
                "既有違章工廠 No.12",
                "既有違章工廠 No.13",
                "既有違章工廠 No.22",
            ]),
        )
示例#2
0
文件: utils.py 项目: pm5/Disfactory
def _get_nearby_factories(latitude, longitude, radius):
    """Return nearby factories based on position and search range."""

    # ref: https://stackoverflow.com/questions/574691/mysql-great-circle-distance-haversine-formula
    distance = 6371 * ACos(
        Cos(Radians(latitude)) * Cos(Radians("lat")) *
        Cos(Radians("lng") - Radians(longitude)) +
        Sin(Radians(latitude)) * Sin(Radians("lat")))

    radius_km = radius
    ids = Factory.objects.annotate(distance=distance).only("id").filter(
        distance__lt=radius_km).order_by("id")

    if len(ids) > settings.MAX_FACTORY_PER_GET:
        ids = _sample(ids, settings.MAX_FACTORY_PER_GET)

    return (Factory.objects.filter(
        id__in=[obj.id for obj in ids]).prefetch_related(
            Prefetch('report_records',
                     queryset=ReportRecord.objects.only("created_at").all())
        ).prefetch_related(
            Prefetch(
                'images',
                queryset=Image.objects.only("id").all())).prefetch_related(
                    Prefetch('documents',
                             queryset=Document.objects.only(
                                 'created_at', 'display_status').all())).all())
示例#3
0
def test_migration_seed_data_correctly():
    longitude = 120.1
    latitude = 23.234
    radius_km = 1

    distance = 6371 * ACos(
        Cos(Radians(latitude)) * Cos(Radians("lat")) * Cos(Radians("lng") - Radians(longitude))
        + Sin(Radians(latitude)) * Sin(Radians("lat"))
    )

    factories = Factory.objects.annotate(distance=distance).filter(
        distance__lt=radius_km,
    )

    assert (
        list(factories.values_list('name', flat=True))
        == Unordered([
            "既有違章工廠 No.2",
            "既有違章工廠 No.3",
            "既有違章工廠 No.8",
            "既有違章工廠 No.9",
            "既有違章工廠 No.10",
            "既有違章工廠 No.11",
            "既有違章工廠 No.12",
            "既有違章工廠 No.13",
            "既有違章工廠 No.22",
        ])
    )
示例#4
0
 def perimeter(self,
               mid_point,
               radius,
               latitude='latitude',
               longitude='longitude'):
     """
     Returns a query set of locations in a specified radius (using the Haversine formula).
     :param mid_point: middle point coordinates of search radius (e.g. tuple of floats)
     :param radius: search radius in km (default) or miles depending on DISTANCE_UNIT
     :param latitude: query selector for latitude
     :param longitude: query selector for longitude
     :return: Annotated query set of found locations
     """
     earth_radius = dict(EARTH_RADIUS_CHOICES).get(self.DISTANCE_UNIT)
     distance = (earth_radius * ACos(
         Cos(Radians(latitude)) * Cos(Radians(mid_point[0])) *
         Cos(Radians(mid_point[1]) - Radians(longitude)) +
         Sin(Radians(latitude)) * Sin(Radians(mid_point[0]))))
     return self.annotate(distance=distance).filter(distance__lte=radius)
示例#5
0
    def filter_cone_search(self, queryset, name, value):
        """
        Executes cone search by annotating each target with separation distance from either the specified RA/Dec or
        the RA/Dec of the specified target. Formula is from Wikipedia: https://en.wikipedia.org/wiki/Angular_distance
        The result is converted to radians.

        Cone search is preceded by a square search to reduce the search radius before annotating the queryset, in
        order to make the query faster.
        """
        if name == 'cone_search':
            ra, dec, radius = value.split(',')
        elif name == 'target_cone_search':
            target_name, radius = value.split(',')
            targets = Target.objects.filter(
                Q(name__icontains=target_name)
                | Q(aliases__name__icontains=target_name)).distinct()
            if len(targets) == 1:
                ra = targets[0].ra
                dec = targets[0].dec
            else:
                return queryset.filter(name=None)

        ra = float(ra)
        dec = float(dec)

        double_radius = float(radius) * 2
        queryset = queryset.filter(ra__gte=ra - double_radius,
                                   ra__lte=ra + double_radius,
                                   dec__gte=dec - double_radius,
                                   dec__lte=dec + double_radius)

        separation = ExpressionWrapper(
            180 * ACos((Sin(radians(dec)) * Sin(Radians('dec'))) +
                       (Cos(radians(dec)) * Cos(Radians('dec')) *
                        Cos(radians(ra) - Radians('ra')))) / Pi(),
            FloatField())

        return queryset.annotate(separation=separation).filter(
            separation__lte=radius)
示例#6
0
def cone_search_filter(queryset, ra, dec, radius):
    """
    Executes cone search by annotating each target with separation distance from the specified RA/Dec.
    Formula is from Wikipedia: https://en.wikipedia.org/wiki/Angular_distance
    The result is converted to radians.

    Cone search is preceded by a square search to reduce the search radius before annotating the queryset, in
    order to make the query faster.

    :param queryset: Queryset of Target objects
    :type queryset: Target

    :param ra: Right ascension of center of cone.
    :type ra: float

    :param dec: Declination of center of cone.
    :type dec: float

    :param radius: Radius of cone search in degrees.
    :type radius: float
    """
    ra = float(ra)
    dec = float(dec)
    radius = float(radius)

    double_radius = radius * 2
    queryset = queryset.filter(ra__gte=ra - double_radius,
                               ra__lte=ra + double_radius,
                               dec__gte=dec - double_radius,
                               dec__lte=dec + double_radius)

    separation = ExpressionWrapper(
        180 * ACos((Sin(radians(dec)) * Sin(Radians('dec'))) +
                   (Cos(radians(dec)) * Cos(Radians('dec')) *
                    Cos(radians(ra) - Radians('ra')))) / Pi(), FloatField())

    return queryset.annotate(separation=separation).filter(
        separation__lte=radius)
示例#7
0
    def filter_cone_search(self, queryset, name, value):
        if name == 'cone_search':
            ra, dec, radius = value.split(',')
        elif name == 'target_cone_search':
            target_name, radius = value.split(',')
            targets = Target.objects.filter(
                Q(name__icontains=target_name)
                | Q(aliases__name__icontains=target_name)).distinct()
            if len(targets) == 1:
                ra = targets[0].ra
                dec = targets[0].dec
            else:
                return queryset.filter(name=None)

        half_pi = 90

        separation = ExpressionWrapper(
            ACos((Cos(half_pi - float(dec)) * Cos(half_pi - F('dec'))) +
                 (Sin(half_pi - float(dec)) * Sin(half_pi - F('dec')) *
                  Cos(float(ra) - F('ra')))), FloatField())

        return queryset.annotate(separation=separation).filter(
            separation__lte=radius)