core.bones.spatial ================== .. py:module:: core.bones.spatial .. autoapi-nested-parse:: `spatial` contains - The `SpatialBone` to handle coordinates - and `haversine` to calculate the distance between two points on earth using their latitude and longitude. Classes ------- .. autoapisummary:: core.bones.spatial.SpatialBone Functions --------- .. autoapisummary:: core.bones.spatial.haversine Module Contents --------------- .. py:function:: haversine(lat1, lng1, lat2, lng2) Calculate the distance between two points on Earth's surface in meters. This function uses the haversine formula to compute the great-circle distance between two points on Earth's surface, specified by their latitude and longitude coordinates. The haversine formula is particularly useful for small distances on the Earth's surface, as it provides accurate results with good performance. For more details on the haversine formula, see `Haversine formula `_. :param float lat1: Latitude of the first point in decimal degrees. :param float lng1: Longitude of the first point in decimal degrees. :param float lat2: Latitude of the second point in decimal degrees. :param float lng2: Longitude of the second point in decimal degrees. :return: Distance between the two points in meters. :rtype: float .. py:class:: SpatialBone(*, boundsLat, boundsLng, gridDimensions, **kwargs) Bases: :py:obj:`viur.core.bones.base.BaseBone` The "SpatialBone" is a specific type of data structure designed to handle spatial data, such as geographical coordinates or geometries. This bone would typically be used for representing and storing location-based data, like the coordinates of a point of interest on a map or the boundaries of a geographic region. This feature allows querying elements near a specific location. Before using, designate the map region for which the index should be constructed. To ensure the best accuracy, minimize the region size; using the entire world is not feasible since boundary wraps are not executed. GridDimensions indicates the number of sub-regions the map will be partitioned into. Results beyond the size of these sub-regions will not be considered during searches by this algorithm. .. note:: Example: When using this feature to find the nearest pubs, the algorithm could be set to consider results within 100km but not those 500km away. Setting the sub-region size to roughly 100km in width and height allows the algorithm to exclude results further than 200km away at the database-query-level, significantly enhancing performance and reducing query costs. Example region: Germany: ```boundsLat=(46.988, 55.022), boundsLng=(4.997, 15.148)``` :param Tuple[float, float] boundsLat: The outer bounds (Latitude) of the region we will search in :param Tuple[float, float] boundsLng: The outer bounds (Longitude) of the region we will search in :param gridDimensions: (Tuple[int, int]) The number of sub-regions the map will be divided in Initializes a new SpatialBone. :param boundsLat: Outer bounds (Latitude) of the region we will search in. :param boundsLng: Outer bounds (Longitude) of the region we will search in. :param gridDimensions: Number of sub-regions the map will be divided in .. py:attribute:: type :value: 'spatial' .. py:attribute:: boundsLat .. py:attribute:: boundsLng .. py:attribute:: gridDimensions .. py:method:: getGridSize() Calculate and return the size of the sub-regions in terms of fractions of latitude and longitude. :return: A tuple containing the size of the sub-regions as (fractions-of-latitude, fractions-of-longitude) :rtype: (float, float) .. py:method:: isInvalid(value) Validate if the given point (latitude, longitude) falls within the specified boundaries. Rejects all values outside the defined region. :param value: A tuple containing the location of the entry as (latitude, longitude) :return: An error description if the value is invalid or False if the value is valid :rtype: str | bool .. py:method:: singleValueSerialize(value, skel, name, parentIndexed) Serialize a single value (latitude, longitude) for storage. If the bone is indexed, calculate and add tile information for efficient querying. :param value: A tuple containing the location of the entry as (latitude, longitude) :param SkeletonInstance skel: The instance of the Skeleton this bone is attached to :param str name: The name of this bone :param bool parentIndexed: A boolean indicating if the parent bone is indexed :return: A dictionary containing the serialized data, including coordinates and tile information (if indexed) :rtype: dict | None .. py:method:: singleValueUnserialize(val) Deserialize a single value (latitude, longitude) from the stored data. :param val: A dictionary containing the serialized data, including coordinates :return: A tuple containing the location of the entry as (latitude, longitude) :rtype: Tuple[float, float] | None .. py:method:: parseSubfieldsFromClient() Determines if subfields (latitude and longitude) should be parsed from the client. :return: Always returns True, as latitude and longitude are required :rtype: bool .. py:method:: isEmpty(value) Check if the given raw value is considered empty (either not present or equal to the empty value). :param value: The raw value to be checked :return: True if the raw value is considered empty, False otherwise :rtype: bool .. py:method:: getEmptyValue() Returns an empty value for the bone, which represents an invalid position. Use 91.0, 181.0 as a special marker for empty, as they are both out of range for Latitude (-90, +90) and Longitude (-180, 180), but will be accepted by Vi and Admin. :return: A tuple representing an empty value for this bone (91.0, 181.0) :rtype: Tuple[float, float] .. py:method:: singleValueFromClient(value, skel, bone_name, client_data) Load a single value from a client :param value: The single value which should be loaded. :param skel: The SkeletonInstance where the value should be loaded into. :param bone_name: The bone name of this bone in the SkeletonInstance. :param client_data: The data taken from the client, a dictionary with usually bone names as key :return: A tuple. If the value is valid, the first element is the parsed value and the second is None. If the value is invalid or not parseable, the first element is a empty value and the second a list of *ReadFromClientError*. .. py:method:: buildDBFilter(name, skel, dbFilter, rawFilter, prefix = None) Parses the client's search filter specified in their request and converts it into a format understood by the datastore. - Ignore filters that do not target this bone. - Safely handle malformed data in rawFilter (this parameter is directly controlled by the client). For detailed information on how this geo-spatial search works, see the ViUR documentation. :param str name: The property name this bone has in its Skeleton (not the description!) :param SkeletonInstance skel: The skeleton this bone is part of :param db.Query dbFilter: The current `viur.core.db.Query` instance to which the filters should be applied :param dict rawFilter: The dictionary of filters the client wants to have applied :param prefix: Optional string, specifying a prefix for the bone's name (default is None) :return: The modified `viur.core.db.Query` instance :rtype: db.Query .. py:method:: calculateInternalMultiQueryLimit(dbQuery, targetAmount) Provides guidance to viur.core.db.Query on the number of entries that should be fetched in each subquery. :param dbQuery: The `viur.core.db.Query` instance :param targetAmount: The desired number of entries to be returned from the db.Query :return: The number of elements db.Query should fetch for each subquery :rtype: int .. py:method:: customMultiQueryMerge(name, lat, lng, dbFilter, result, targetAmount) Randomly returns 'targetAmount' elements from 'result'. :param str name: The property-name this bone has in its Skeleton (not the description!) :param lat: Latitude of the reference point :param lng: Longitude of the reference point :param dbFilter: The db.Query instance calling this function :param result: The list of results for each subquery that was executed :param int targetAmount: The desired number of results to be returned from db.Query :return: List of elements to be returned from db.Query :rtype: List[db.Entity] .. py:method:: setBoneValue(skel, boneName, value, append, language = None) Sets the value of the bone to the provided 'value'. Sanity checks are performed; if the value is invalid, the bone value will revert to its original (default) value and the function will return False. :param skel: Dictionary with the current values from the skeleton the bone belongs to :param boneName: The name of the bone that should be modified :param value: The value that should be assigned. Its type depends on the type of the bone :param append: If True, the given value will be appended to the existing bone values instead of replacing them. Only supported on bones with multiple=True :param language: Optional, the language of the value if the bone is language-aware :return: A boolean indicating whether the operation succeeded or not :rtype: bool .. py:method:: structure() Describes the bone and its settings as an JSON-serializable dict. This function has to be implemented for subsequent, specialized bone types.