diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6101a2b02..e87a0f08c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -42,7 +42,7 @@ jobs: makepot: "true" services: postgres: - image: postgres:13 + image: postgis/postgis:14-3.5 env: POSTGRES_USER: odoo POSTGRES_PASSWORD: odoo diff --git a/base_geoengine/README.rst b/base_geoengine/README.rst new file mode 100644 index 000000000..758f90372 --- /dev/null +++ b/base_geoengine/README.rst @@ -0,0 +1,373 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +=========================== +Geospatial support for Odoo +=========================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:a22713167bb39e1995e9bc618b29382cd03bba76a910d58cf62993288b0a385b + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fgeospatial-lightgray.png?logo=github + :target: https://github.com/OCA/geospatial/tree/19.0/base_geoengine + :alt: OCA/geospatial +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/geospatial-19-0/geospatial-19-0-base_geoengine + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/geospatial&target_branch=19.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +GeoEngine is an Odoo module that adds spatial/GIS capabilites to Odoo. +It will allow you to : + +- Visualize and query your business information on map +- Perform GeoBI and spatial query +- Configure your spatial layers and spatial datasources +- Extend Odoo models with spatial columns + +GeoEngine relies on `OpenLayers `__ and +`PostGIS `__ technologies. + +Postgis is used to store spatial information in databases. OpenLayer is +used to represent spatial data in other words to show maps and the +different spatial layers. The GeoEngine module acts as a data provider +and as an OpenLayers configurator. It also provides a complete extension +to Odoo ORM. + +**Table of contents** + +.. contents:: + :local: + +Installation +============ + +To install this module, you need to have +`PostGIS `__ installed. + +On Ubuntu: + +.. code:: bash + + sudo apt-get install postgis + +The module also requires two additional python libs: + +- `Shapely `__ +- `geojson `__ + +These two additional libs will be installed automatically with the +module. + +For a complete documentation please refer to the `public +documentation `__ + +Usage +===== + +Geoengine Demo +-------------- + +1. As a user/admin, when I am in the Geoengine Demo module and I go to + the ZIP menu. When I click on an item in the list view, I get to the + form view showing me the different information about the ZIP. We can + see its ZIP, city, priority, total sales and his spatial + representation. +2. As a user, I can't modify the information in the form view. +3. As an admin, I can modify the information in the form view. I can + click on the bin button to clear the map and I can draw a new shape. +4. As a user, when I go the "Retail machines" tab and there are no + items to display, it does not show me anything. +5. As an admin, when I go the "Retail machines" tab and there are no + items to display, the list view of the retail machines suggests to + me to add a new line. +6. As a user/admin, if there are items to be displayed in the "Retail + machines" tab then I can click on an item and the retail machines + form view will be displayed. We can see its spatial representation + by going to "The point" tab and its attributes in "Attributes" tab. +7. As a user/admin, when I go to the geoengine zip view by clicking on + the map button at the top right of the screen. The geoengine view + appears with the first 80 results displayed on the map. The vector + layers selected are those defined as "active on startup" by the + admin. The selected raster layer is the first one that is not an + overlay layer. +8. As a user/admin, when I hover over an area on the map, the area + changes its style. +9. As a user/admin, when I click on an area, a popup appears an I can + see the different information about the area. If I click on the + cross, the popup will disappear. If I click somewhere else on the + map, the popup will also disappear. If I click on the about button, + then the form view will be displayed. +10. As a user/admin, when I use the paging system, then the results + displayed on the map are different (corresponding to the request). +11. As a user/admin, if we use the search bar, we can search results by + his zip or his city. +12. As an admin, if I change the sequence of layers with the handle + button then the change are persisted in database. +13. As a user, if I change the sequence of layers with the handle button + then the change are not persisted in database. There are just the + changes in the display. +14. As an admin, if I change the domain of a layer with the filter + button then the change are persisted in database. +15. As a user, if I change the domain of a layer with the filter button + then the change are not persisted in database. There are just the + changes in the display. +16. As an admin, I have the possibility to edit the layer with its + corresponding button. +17. As a user/admin, I can open/close LayerPanel with its button. +18. As a user/admin, I can open/close RecordsPanel with its button. +19. As a user/admin, when I click on a record in RecordsPanel, a move is + made on the map to the selected record. +20. As a user/admin, when I click on a record in RecordsPanel, I can + also click on the left magnifying glass to zoom on the record. +21. As a user/admin, when I click on a record in RecordsPanel, I can + also click on the right magnifying glass to get the original zoom. +22. As a user/admin, I can use the search bar to search in the + RecordsPanel. +23. As an admin,If the geoengine view is in edit mode, I can create new + records by drawing them in the view. +24. As an admin, If the geoengine view is in edit mode, I can modify its + spatial representation. + +Geoengine Backend +----------------- + +1. As an admin, if I go into the configuration of the raster layers and + it has elements, I can click on one and see its information. +2. As an admin, if I want to create a new raster layer, I can click on + "NEW" and fill out the form. The required fields for OpenStreetMap + type are "Layer Name" and "Related View". If we want to have a WMTS + (Web Map Tile Service) raster type. The required fields in addition + to the precedents are "Service URL", "Matrix set","Format", + "Projection" and "Resolutions". If we take WMS (Web Map Service) + raster type, then the required fields are "Layer Name", "Related + View", "Service URL", "Params", "Server Type". +3. As an admin,if I go into the configuration of the vector layers and + it has elements, I can click on one and see its information. +4. As an admin, if I want to create a new vector layer, I can click on + "NEW" and fill out the form. The required fields are "Layer Name", + "Related View", "Geo field" and "Representation mode". + +Known issues / Roadmap +====================== + + + +Changelog +========= + +19.0.1.0.1 +---------- + +- Migration to Odoo 19.0. +- Migrated JavaScript frontend to OWL/ESM architecture. +- Updated OpenLayers to version 10.5.0. +- Updated Chroma.js to version 3.1.2. +- Refactored domain handling for Odoo 19 ORM compatibility. + +16.0.1.0.0 (2023-03-20) +----------------------- + +- LayerSwitcher has been removed as it was not really practical. A + LayerPanel is now active. +- The geo_search method is now deprecated and replaced by the standard + odoo search method. +- The widget "geo_edit_map" attribute is no longer necessary as the + field is automatically detected by his type. We can also provide an + option attribute that allows us to pass an opacity and a color as + parameters. + +.. code:: xml + +
+ + + + + +
+ +- The method geo_search is now deprecated. We now need to use the + standard odoo search method. + +.. code:: python + + obj.search([("the_point","geo_intersect",{"dummy.zip.the_geom": [("id", "=", rec.id)]})]) + +- We can now pass to the geoengine view a template to display the + information we want to see when clicking on a feature. + +.. code:: xml + + + + + + + + + +
    +
  • ZIP : +
  • +
  • Total Sales: +
  • +
+
+
+
+ +- We can now pass a model to use to a layer to display other information + on the map. + +.. code:: xml + + + + [('state', '=', 'hs')] + + HS retail machines + + basic + + #FF0000 + + 0.8 + + +- There is some new features in the LayerPanel. + +1. If you are logged in as an admin, you have the possibility to edit + the layer by clicking on the edit button. This will open a dialog + box. Changes will appear in real time on the view. +2. If you are logged in as an admin, you can also change the domain of + the layer. If you are logged in as a user, changes will not be + persisted in the database. Changes will appear in real time on the + view. +3. If you are logged in as an admin, you can also change the sequence of + the layers by sliding them over each other. If you are logged in as a + user, changes will not be persisted in the database. + +- Widget domain is now implemented for geo field This means that the + geo-operators are also implemented and that there is the possibility + to add a sub-domain. If we want to add a domain that includes all the + records that are displayed in the geoengine view (active_ids). We can + use the two new operators : "in active_ids" and "not in active_ids". + These will automatically replace the marker with ids. Note that the + widget will indicate that the domain is invalid because of the marker. +- Creation of the RecordsPanel. This panel allows you to retrieve all + active records. You can click on record to get the movement to the + selected record. Two magnifying glass are also available. You can + click on the left one to zoom on the record. You can click on the + right one to get the original zoom. +- A search bar is also available. It allows you to perform a search into + the RecordsPanel. +- A button to open/close the panels is also available. +- The module has been translated in French. +- Now you can now make the geoengine view editable. Simply add editable + attribute in the geoengine view. + +.. code:: xml + + + + + + + + + + +
    +
  • ZIP : +
  • +
  • Total Sales: +
  • +
+
+
+
+ + Thanks to that, you can create new records by drawing them directly in the geoengine view. You can also edit record in the same view. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Camptocamp +* ACSONE SA/NV + +Contributors +------------ + +- Nicolas Bessi +- Frederic Junod +- Yannick Payot +- Sandy Carter +- Laurent Mignon +- Jonathan Nemry +- David Lasley +- Daniel Reis +- Matthieu Dietrich +- Alan Ramos +- Damien Crier +- Cyril Gaudin +- Pierre Verkest +- Benjamin Willig +- Devendra Kavthekar +- Emanuel Cino +- Thomas Nowicki +- Alexandre Saunier +- Sandip Mangukiya +- Samuel Kouff +- `APSL-Nagarro `__: + + - Antoni Marroig + - Miquel Alzanillas + +- Red Butay +- Sergio Sancho + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/geospatial `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/base_geoengine/__init__.py b/base_geoengine/__init__.py new file mode 100644 index 000000000..0174161f3 --- /dev/null +++ b/base_geoengine/__init__.py @@ -0,0 +1,10 @@ +# Copyright 2011-2012 Nicolas Bessi (Camptocamp SA) +# Copyright 2023 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from . import models +from . import expressions +from . import fields +from . import geo_convertion_helper +from . import geo_operators +from .geo_db import init_postgis +from . import domains diff --git a/base_geoengine/__manifest__.py b/base_geoengine/__manifest__.py new file mode 100644 index 000000000..b8358c8a0 --- /dev/null +++ b/base_geoengine/__manifest__.py @@ -0,0 +1,32 @@ +# Copyright 2011-2015 Nicolas Bessi (Camptocamp SA) +# Copyright 2016 Yannick Payot (Camptocamp SA) +# Copyright 2023 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +{ + "name": "Geospatial support for Odoo", + "version": "19.0.1.0.1", + "category": "GeoBI", + "author": "Camptocamp,ACSONE SA/NV,Odoo Community Association (OCA)", + "license": "AGPL-3", + "website": "https://github.com/OCA/geospatial", + "depends": ["base", "web"], + "data": [ + "security/data.xml", + "views/base_geoengine_view.xml", + "views/ir_model_view.xml", + "views/ir_view_view.xml", + "views/geo_raster_layer_view.xml", + "views/geo_vector_layer_view.xml", + "security/ir.model.access.csv", + ], + "assets": { + "web.assets_backend": [ + "base_geoengine/static/src/js/**/*", + "base_geoengine/static/src/css/style.css", + "base_geoengine/static/lib/geostats-2.1.0/geostats.css", + ], + }, + "external_dependencies": {"python": ["shapely", "geojson"]}, + "installable": True, + "pre_init_hook": "init_postgis", +} diff --git a/base_geoengine/domains.py b/base_geoengine/domains.py new file mode 100644 index 000000000..123475ff6 --- /dev/null +++ b/base_geoengine/domains.py @@ -0,0 +1,151 @@ +# Copyright 2023 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +import contextlib +import logging +import warnings + +from odoo.fields import Domain +from odoo.models import BaseModel +from odoo.orm import domains +from odoo.orm.domains import ( + CONDITION_OPERATORS, + NEGATIVE_CONDITION_OPERATORS, + SQL, + DomainCondition, + OptimizationLevel, + Query, +) +from odoo.orm.identifiers import NewId + +_logger = logging.getLogger(__name__) + +GEO_OPERATORS = frozenset( + [ + "geo_greater", + "geo_lesser", + "geo_equal", + "geo_touch", + "geo_within", + "geo_contains", + "geo_intersect", + ] +) + + +def checked(self) -> DomainCondition: + """Validate `self` and return it if correct, otherwise raise an exception.""" + if not isinstance(self.field_expr, str) or not self.field_expr: + self._raise("Empty field name", error=TypeError) + operator = self.operator.lower() + if operator != self.operator: + warnings.warn( + ( + f"Deprecated since 19.0, the domain condition " + f"{(self.field_expr, self.operator, self.value)!r} " + f"should have a lower-case operator" + ), + DeprecationWarning, + # + stacklevel=2, + # + ) + return DomainCondition(self.field_expr, operator, self.value).checked() + if operator not in CONDITION_OPERATORS: + # + if operator not in GEO_OPERATORS: + # + self._raise("Invalid operator") + + # check already the consistency for domain manipulation + # these are common mistakes and optimizations, + # do them here to avoid recreating the domain + # - NewId is not a value + # - records are not accepted, use values + # - Query and Domain values should be using a relational operator + # + # from .models import BaseModel # noqa: PLC0415 + # + + value = self.value + if value is None: + value = False + elif isinstance(value, NewId): + _logger.warning( + "Domains don't support NewId, use .ids instead, for %r", + (self.field_expr, self.operator, self.value), + ) + operator = "not in" if operator in NEGATIVE_CONDITION_OPERATORS else "in" + value = [] + elif isinstance(value, BaseModel): + _logger.warning( + "The domain condition %r should not have a value which is a model", + (self.field_expr, self.operator, self.value), + ) + value = value.ids + elif isinstance(value, (Domain, Query, SQL)) and operator not in ( + "any", + "not any", + "any!", + "not any!", + "in", + "not in", + ): + # accept SQL object in the right part for simple operators + # use case: compare 2 fields + _logger.warning( + "The domain condition %r should use the 'any' or 'not any' operator.", + (self.field_expr, self.operator, self.value), + ) + if value is not self.value: + return DomainCondition(self.field_expr, operator, value) + return self + + +def _to_sql(self, model: BaseModel, alias: str, query: Query) -> SQL: + """Enhanced _to_sql that handles geospatial operators.""" + field_expr, operator, value = self.field_expr, self.operator, self.value + + # Only handle geospatial operators here, delegate everything else to original method + if operator in GEO_OPERATORS: + # Ensure geospatial conditions are fully optimized + assert self._opt_level >= OptimizationLevel.FULL, ( + "Must fully optimize before generating the query " + f"{(field_expr, operator, value)}" + ) + + field = self._field(model) + model._check_field_access(field, "read") + return field.condition_to_sql(field_expr, operator, value, model, alias, query) + + # For all other operators, use the original method + return original__to_sql(self, model, alias, query) + + +def _optimize_step(self, model: BaseModel, level: OptimizationLevel) -> Domain: + """Optimization step for geospatial operators.""" + # For geospatial operators, we need to handle them specially during optimization + # If this is a geospatial operator, mark it as optimized at FULL level + if self.operator in GEO_OPERATORS: + # Perform basic validation and normalization + with contextlib.suppress(Exception): + field = self._field(model) + # Basic geospatial operator validation + if hasattr(field, "geo_type"): # It's a geospatial field + # Create optimized version with FULL level + optimized = DomainCondition(self.field_expr, self.operator, self.value) + object.__setattr__(optimized, "_opt_level", OptimizationLevel.FULL) + return optimized + + # Fall back to original optimization for non-geo operators + return original__optimize_step(self, model, level) + + +# Store original methods before monkey patching +original__optimize_step = DomainCondition._optimize_step +original__to_sql = DomainCondition._to_sql + +DomainCondition.checked = checked +DomainCondition._to_sql = _to_sql +DomainCondition._optimize_step = _optimize_step + +domains.CONDITION_OPERATORS = domains.CONDITION_OPERATORS.union(GEO_OPERATORS) diff --git a/base_geoengine/expressions.py b/base_geoengine/expressions.py new file mode 100644 index 000000000..edf8a592c --- /dev/null +++ b/base_geoengine/expressions.py @@ -0,0 +1,169 @@ +# Copyright 2023 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging +import random +import string + +from odoo import fields +from odoo.fields import Domain +from odoo.models import BaseModel +from odoo.tools import SQL, Query + +from .fields import GeoField +from .geo_operators import GeoOperator + +logger = logging.getLogger(__name__) + +original___condition_to_sql = fields.Field._condition_to_sql + +GEO_OPERATORS = { + "geo_greater": ">", + "geo_lesser": "<", + "geo_equal": "=", + "geo_touch": "ST_Touches", + "geo_within": "ST_Within", + "geo_contains": "ST_Contains", + "geo_intersect": "ST_Intersects", +} + +GEO_SQL_OPERATORS = { + "geo_greater": SQL(">"), + "geo_lesser": SQL("<"), + "geo_equal": SQL("="), + "geo_touch": SQL("ST_Touches"), + "geo_within": SQL("ST_Within"), + "geo_contains": SQL("ST_Contains"), + "geo_intersect": SQL("ST_Intersects"), +} + + +def _condition_to_sql( + self, + field_expr: str, + operator: str, + value, + model: BaseModel, + alias: str, + query: Query, +) -> SQL: + """ + This method has been monkey patched in order to be able to include + geo_operators into the Odoo search method. + """ + if operator in GEO_OPERATORS.keys(): + current_field = model._fields.get(field_expr) + current_operator = GeoOperator(current_field) + if current_field and isinstance(current_field, GeoField): + params = [] + if isinstance(value, dict): + # We are having indirect geo_operator like (‘geom’, ‘geo_...’, + # {‘res.zip.poly’: [‘id’, ‘in’, [1,2,3]] }) + ref_search = value + sub_queries = [] + for key in ref_search: + i = key.rfind(".") + rel_model_name = key[0:i] + rel_col = key[i + 1 :] + rel_model = model.env[rel_model_name] + # we compute the attributes search on spatial rel + if ref_search[key]: + rel_alias = ( + rel_model._table + + "_" + + "".join(random.choices(string.ascii_lowercase, k=5)) + ) + rel_query = where_calc( + rel_model, + ref_search[key], + active_test=True, + alias=rel_alias, + ) + model._check_field_access(current_field, "read") + if operator == "geo_equal": + rel_query.add_where( + f'"{alias}"."{field_expr}" {GEO_OPERATORS[operator]} ' + f"{rel_alias}.{rel_col}" + ) + elif operator in ("geo_greater", "geo_lesser"): + rel_query.add_where( + f"ST_Area({alias}.{field_expr}) " + f"{GEO_OPERATORS[operator]} " + f"ST_Area({rel_alias}.{rel_col})" + ) + else: + rel_query.add_where( + f'{GEO_OPERATORS[operator]}("{alias}"."{field_expr}", ' + f"{rel_alias}.{rel_col})" + ) + + subquery_sql = rel_query.subselect("1") + sub_query_mogrified = ( + model.env.cr.mogrify(subquery_sql.code, subquery_sql.params) + .decode("utf-8") + .replace(f"'{rel_model._table}'", f'"{rel_model._table}"') + .replace("%", "%%") + ) + sub_queries.append(f"EXISTS({sub_query_mogrified})") + query_str = " AND ".join(sub_queries) + else: + query_str = get_geo_func( + current_operator, operator, field_expr, value, params, model._table + ) + return SQL(query_str, *params) + return original___condition_to_sql( + self, + field_expr=field_expr, + operator=operator, + value=value, + model=model, + alias=alias, + query=query, + ) + + +fields.Field._condition_to_sql = _condition_to_sql + + +def get_geo_func(current_operator, operator, left, value, params, table): + """ + This method will call the SQL query corresponding to the requested geo operator + """ + geo_func_map = { + "geo_greater": current_operator.get_geo_greater_sql, + "geo_lesser": current_operator.get_geo_lesser_sql, + "geo_equal": current_operator.get_geo_equal_sql, + "geo_touch": current_operator.get_geo_touch_sql, + "geo_within": current_operator.get_geo_within_sql, + "geo_contains": current_operator.get_geo_contains_sql, + "geo_intersect": current_operator.get_geo_intersect_sql, + } + func = geo_func_map.get(operator) + if func is None: + raise NotImplementedError(f"The operator {operator} is not supported") + return func(table, left, value, params) + + +def where_calc(model, domain, active_test=True, alias=None): + """ + This method is copied from base, we need to create our own query. + """ + # if the object has an active field ('active', 'x_active'), filter out all + # inactive records unless they were explicitly asked for + if model._active_name and active_test and model._context.get("active_test", True): + # the item[0] trick below works for domain items and '&'/'|'/'!' + # operators too + if not any(item[0] == model._active_name for item in domain): + domain = [(model._active_name, "=", 1)] + domain + + query = Query(model.env, alias, model._table) + if domain: + # In Odoo 19, create Domain object and use its _to_sql method + domain_obj = Domain(domain) + optimized_domain = domain_obj.optimize_full(model) + sql_condition = optimized_domain._to_sql(model, alias, query) + query.add_where(sql_condition) + + return query + + return query diff --git a/base_geoengine/fields.py b/base_geoengine/fields.py new file mode 100644 index 000000000..1cd79f843 --- /dev/null +++ b/base_geoengine/fields.py @@ -0,0 +1,347 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. +# Copyright 2011-2012 Nicolas Bessi (Camptocamp SA) +# Copyright 2016 Yannick Payot (Camptocamp SA) +# Copyright 2023 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from __future__ import annotations + +import json +import logging +from operator import attrgetter + +from odoo import fields +from odoo.tools import sql + +from . import geo_convertion_helper as convert +from .geo_db import create_geo_column, create_geo_index + +logger = logging.getLogger(__name__) +try: + import geojson + from shapely.geometry import Point, shape + from shapely.geometry.base import BaseGeometry + from shapely.wkb import loads as wkbloads +except ImportError: + logger.warning("Shapely or geojson are not available in the sys path") + + +class GeoField(fields.Field): + """The field descriptor contains the field definition common to all + specialized fields for geolocalization. Subclasses must define a type + and a geo_type. The type is the name of the corresponding column type, + the geo_type is the name of the corresponding type in the GIS system. + """ + + geo_type = None + dim = "2" + srid = 3857 + gist_index = True + + @property + def column_type(self): + postgis_geom_type = self.geo_type.upper() if self.geo_type else "GEOMETRY" + if self.dim == "3": + postgis_geom_type += "Z" + elif self.dim == "4": + postgis_geom_type += "ZM" + return ("geometry", f"geometry({postgis_geom_type}, {self.srid})") + + def convert_to_column(self, value, record, values=None, validate=True): + """Convert value to database format + + value can be geojson, wkt, shapely geometry object. + If geo_direct_write in context you can pass diretly WKT""" + if not value: + return None + shape_to_write = self.entry_to_shape(value, same_type=True) + if shape_to_write.is_empty: + return None + else: + return f"SRID={self.srid};{shape_to_write.wkt}" + + def convert_to_cache(self, value, record, validate=True): + val = value + if isinstance(val, bytes | str): + try: + int(val, 16) + except Exception: + # not an hex value -> try to load from a sting + # representation of a geometry + value = convert.value_to_shape(value, use_wkb=False) + if isinstance(value, BaseGeometry): + val = value.wkb_hex + return val + + def convert_to_record(self, value, record): + """Value may be: + - a GeoJSON string when field onchange is triggered + - a geometry object hexcode from cache + - a unicode containing dict + """ + if not value: + return False + return convert.value_to_shape(value, use_wkb=True) + + def convert_to_read(self, value, record, use_display_name=True): + if not isinstance(value, BaseGeometry): + # read hexadecimal value from database + shape = self.load_geo(value) + else: + shape = value + if not shape or shape.is_empty: + return False + return geojson.dumps(shape) + + # + # Field description + # + + # properties used by get_description() + _description_dim = property(attrgetter("dim")) + _description_srid = property(attrgetter("srid")) + _description_gist_index = property(attrgetter("gist_index")) + + @classmethod + def load_geo(cls, wkb): + """Load geometry into browse record after read was done""" + if isinstance(wkb, BaseGeometry): + return wkb + return wkbloads(wkb, hex=True) if wkb else False + + def entry_to_shape(self, value, same_type=False): + """Transform input into an object""" + shape = convert.value_to_shape(value) + if same_type and not shape.is_empty: + if shape.geom_type.lower() != self.geo_type.lower(): + msg = self.env._( + "Geo Value %(geom_type)s must be of the same type %(geo_type)s \ + as fields", + geom_type=shape.geom_type.lower(), + geo_type=self.geo_type.lower(), + ) + raise TypeError(msg) + return shape + + def update_geo_db_column(self, model): + """Update the column type in the database.""" + cr = model.env.cr + query = """SELECT srid, type, coord_dimension + FROM geometry_columns + WHERE f_table_name = %s + AND f_geometry_column = %s""" + cr.execute(query, (model._table, self.name)) + check_data = cr.fetchone() + if not check_data: + raise TypeError( + self.env._( + "geometry_columns table seems to be corrupted." + " SRID check is not possible" + ) + ) + if check_data[0] != self.srid: + raise TypeError( + self.env._( + "Reprojection of column is not implemented." + " We can not change srid %(srid)s to %(data)s", + srid=self.srid, + data=check_data[0], + ) + ) + elif check_data[1] != self.geo_type.upper(): + raise TypeError( + self.env._( + "Geo type modification is not implemented." + " We can not change type %(data)s to %(geo_type)s", + data=check_data[1], + geo_type=self.geo_type.upper(), + ) + ) + elif check_data[2] != self.dim: + raise TypeError( + self.env._( + "Geo dimention modification is not implemented." + " We can not change dimention %(data)s to %(dim)s", + data=check_data[2], + dim=self.dim, + ) + ) + if self.gist_index: + create_geo_index(cr, self.name, model._table) + return True + + def update_db_column(self, model, column): + """Create/update the column corresponding to ``self``. + + For creation of geo column + + :param model: an instance of the field's model + :param column: the column's configuration (dict) + if it exists, or ``None`` + """ + # the column does not exist, create it + + if not column: + create_geo_column( + model.env.cr, + model._table, + self.name, + self.geo_type.upper(), + self.srid, + self.dim, + self.string, + ) + if self.gist_index: + create_geo_index(model.env.cr, self.name, model._table) + return + + if column["udt_name"] == self.column_type[0]: + if self.gist_index: + create_geo_index(model.env.cr, self.name, model._table) + return + + self.update_geo_db_column(model) + + if column["udt_name"] in self.column_cast_from: + sql.convert_column( + model.env.cr, model._table, self.name, self.column_type[1] + ) + else: + newname = (self.name + "_moved{}").format + i = 0 + while sql.column_exists(model.env.cr, model._table, newname(i)): + i += 1 + if column["is_nullable"] == "NO": + sql.drop_not_null(model.env.cr, model._table, self.name) + sql.rename_column(model.env.cr, model._table, self.name, newname(i)) + sql.create_column( + model.env.cr, model._table, self.name, self.column_type[1], self.string + ) + + +class GeoLine(GeoField): + """Field for POSTGIS geometry Line type""" + + type = "geo_line" + geo_type = "LineString" + + @classmethod + def from_points(cls, cr, point1, point2, srid=None): + """ + Converts given points in parameter to a line. + :param cr: DB cursor + :param point1: Point (BaseGeometry) + :param point2: Point (BaseGeometry) + :param srid: SRID + :return: LINESTRING Object + """ + sql = """ + SELECT + ST_MakeLine( + ST_GeomFromText(%(wkt1)s, %(srid)s), + ST_GeomFromText(%(wkt2)s, %(srid)s) + ) + """ + cr.execute( + sql, + { + "wkt1": point1.wkt, + "wkt2": point2.wkt, + "srid": srid or cls.srid, + }, + ) + res = cr.fetchone() + return cls.load_geo(res[0]) + + +class GeoPoint(GeoField): + """Field for POSTGIS geometry Point type""" + + type = "geo_point" + geo_type = "Point" + + @classmethod + def from_latlon(cls, cr, latitude, longitude): + """Convert a (latitude, longitude) into an UTM coordinate Point:""" + pt = Point(longitude, latitude) + cr.execute( + """ + SELECT + ST_Transform( + ST_GeomFromText(%(wkt)s, 4326), + %(srid)s) + """, + {"wkt": pt.wkt, "srid": cls.srid}, + ) + res = cr.fetchone() + return cls.load_geo(res[0]) + + @classmethod + def to_latlon(cls, cr, geopoint): + """Convert a UTM coordinate point to \ + (latitude, longitude):""" + # Line to execute to retrieve + # longitude, latitude from UTM in postgres command line: + # SELECT ST_X(geom), ST_Y(geom) FROM (SELECT ST_TRANSFORM(ST_SetSRID( + # ST_MakePoint(601179.61612, 6399375,681364), + # ..............900913), 4326) as geom) g; + if isinstance(geopoint, BaseGeometry): + geo_point_instance = geopoint + else: + geo_point_instance = shape(json.loads(geopoint)) + cr.execute( + """ + SELECT + ST_TRANSFORM( + ST_SetSRID( + ST_MakePoint( + %(coord_x)s, %(coord_y)s + ), + %(srid)s + ), 4326)""", + { + "coord_x": geo_point_instance.x, + "coord_y": geo_point_instance.y, + "srid": cls.srid, + }, + ) + + res = cr.fetchone() + point_latlon = cls.load_geo(res[0]) + return point_latlon.x, point_latlon.y + + +class GeoPolygon(GeoField): + """Field for POSTGIS geometry Polygon type""" + + type = "geo_polygon" + geo_type = "Polygon" + + +class GeoMultiLine(GeoField): + """Field for POSTGIS geometry MultiLine type""" + + type = "geo_multi_line" + geo_type = "MultiLineString" + + +class GeoMultiPoint(GeoField): + """Field for POSTGIS geometry MultiPoint type""" + + type = "geo_multi_point" + geo_type = "MultiPoint" + + +class GeoMultiPolygon(GeoField): + """Field for POSTGIS geometry MultiPolygon type""" + + type = "geo_multi_polygon" + geo_type = "MultiPolygon" + + +fields.GeoLine = GeoLine +fields.GeoPoint = GeoPoint +fields.GeoPolygon = GeoPolygon +fields.GeoMultiLine = GeoMultiLine +fields.GeoMultiPoint = GeoMultiPoint +fields.GeoMultiPolygon = GeoMultiPolygon diff --git a/base_geoengine/geo_convertion_helper.py b/base_geoengine/geo_convertion_helper.py new file mode 100644 index 000000000..cb8d542f8 --- /dev/null +++ b/base_geoengine/geo_convertion_helper.py @@ -0,0 +1,47 @@ +# Copyright 2011-2012 Nicolas Bessi (Camptocamp SA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +import logging +import re + +from odoo import _ + +logger = logging.getLogger(__name__) + +_HEX_RE = re.compile(r"^[0-9a-fA-F]+$") + +try: + import geojson + from shapely import wkb, wkt + from shapely.geometry import shape + from shapely.geometry.base import BaseGeometry +except ImportError: + logger = logging.getLogger(__name__) + logger.warning(_("Shapely or geojson are not available in the sys path")) # pylint: disable=prefer-env-translation + + +def value_to_shape(value, use_wkb=False): + """Transforms input into a Shapely object""" + if not value: + return wkt.loads("GEOMETRYCOLLECTION EMPTY") + if isinstance(value, str): + # We try to do this before parsing json exception + # exception are ressource costly + if "{" in value: + geo_dict = geojson.loads(value) + return shape(geo_dict) + elif use_wkb or _HEX_RE.match(value): + return wkb.loads(value, hex=True) + else: + return wkt.loads(value) + elif hasattr(value, "wkt"): + if isinstance(value, BaseGeometry): + return value + else: + return wkt.loads(value.wkt) + else: + raise TypeError( + _( # pylint: disable=prefer-env-translation + "Write/create/search geo type must be wkt/geojson " + "string or must respond to wkt" + ) + ) diff --git a/base_geoengine/geo_db.py b/base_geoengine/geo_db.py new file mode 100644 index 000000000..65221a019 --- /dev/null +++ b/base_geoengine/geo_db.py @@ -0,0 +1,89 @@ +# Copyright 2011-2012 Nicolas Bessi (Camptocamp SA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +"""Helper to setup Postgis""" + +import logging + +from odoo.exceptions import MissingError +from odoo.tools import sql + +logger = logging.getLogger("geoengine.sql") +_schema = logging.getLogger("odoo.schema") + + +def init_postgis(env): + """Initialize postgis + Add PostGIS support to the database. PostGIS is a spatial database + extender for PostgreSQL object-relational database. It adds support for + geographic objects allowing location queries to be run in SQL. + """ + cr = env.cr + cr.execute( + """ + SELECT + tablename + FROM + pg_tables + WHERE + tablename='spatial_ref_sys'; + """ + ) + check = cr.fetchone() + if check: + return {} + try: + cr.execute( + """ + CREATE EXTENSION postgis; + CREATE EXTENSION postgis_topology; + """ + ) + except Exception as exc: + raise MissingError( + env._( + "Error, can not automatically initialize spatial postgis" + " support. Database user may have to be superuser and" + " postgres/postgis extensions with their devel header have" + " to be installed. If you do not want Odoo to connect with a" + " super user you can manually prepare your database. To do" + " this, open a client to your database using a super user and" + " run:\n" + "CREATE EXTENSION postgis;\n" + "CREATE EXTENSION postgis_topology;\n" + ) + ) from exc + + +def create_geo_column(cr, tablename, columnname, geotype, srid, dim, comment=None): + """Create a geometry column with the given type. + + :params: srid: geometry's projection srid + :params: dim: geometry's dimension (2D or 3D) + """ + cr.execute( + "SELECT AddGeometryColumn( %s, %s, %s, %s, %s)", + (tablename, columnname, srid, geotype, dim), + ) + if comment: + # pylint: disable=E8103 + cr.execute( + f'COMMENT ON COLUMN "{tablename}"."{columnname}" IS %s', + (comment,), + ) + _schema.debug( + "Table %r: added geometry column %r of type %s", tablename, columnname, geotype + ) + + +def _postgis_index_name(table, col_name): + return f"{table}_{col_name}_gist_index" + + +def create_geo_index(cr, columnname, tablename): + """Create the given index unless it exists.""" + indexname = _postgis_index_name(tablename, columnname) + if sql.index_exists(cr, indexname): + return + # pylint: disable=E8103 + cr.execute(f"CREATE INDEX {indexname} ON {tablename} USING GIST ( {columnname} )") + _schema.debug("Table %r: created index %r", tablename, indexname) diff --git a/base_geoengine/geo_operators.py b/base_geoengine/geo_operators.py new file mode 100644 index 000000000..8be01f44e --- /dev/null +++ b/base_geoengine/geo_operators.py @@ -0,0 +1,75 @@ +# Copyright 2011-2012 Nicolas Bessi (Camptocamp SA) +# Copyright 2023 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + + +class GeoOperator: + def __init__(self, geo_field): + self.geo_field = geo_field + + def _get_direct_como_op_sql(self, table, col, value, params, op=""): + """provide raw sql for geater and lesser operators""" + if isinstance(value, int | float): + return f" ST_Area({table}.{col}) {op} {value}" + else: + base = self.geo_field.entry_to_shape(value, same_type=False) + params.append(base.wkt) + return f" ST_Area({table}.{col}) {op} ST_Area(ST_GeomFromText(%s))" + + def _get_postgis_comp_sql(self, table, col, value, params, op=""): + """return raw sql for all search based on St_**(a, b) posgis operator""" + base = self.geo_field.entry_to_shape(value, same_type=False) + srid = self.geo_field.srid + params.append(base.wkt) + params.append(srid) + return f"{op}({table}.{col}, ST_GeomFromText(%s, %s))" + + def get_geo_greater_sql(self, table, col, value, params): + """Returns raw sql for geo_greater operator + (used for area comparison) + """ + return self._get_direct_como_op_sql(table, col, value, params, op=">") + + def get_geo_lesser_sql(self, table, col, value, params): + """Returns raw sql for geo_lesser operator + (used for area comparison)""" + return self._get_direct_como_op_sql(table, col, value, params, op="<") + + def get_geo_equal_sql( + self, + table, + col, + value, + params, + ): + """Returns raw sql for geo_equal operator + (used for equality comparison) + """ + base = self.geo_field.entry_to_shape(value, same_type=False) + compare_to = "ST_GeomFromText(%s)" + params.append(base.wkt) + return f" {table}.{col} = {compare_to}" + + def get_geo_intersect_sql(self, table, col, value, params): + """Returns raw sql for geo_intersec operator + (used for spatial comparison) + """ + return self._get_postgis_comp_sql(table, col, value, params, op="ST_Intersects") + + def get_geo_touch_sql(self, table, col, value, params): + """Returns raw sql for geo_touch operator + (used for spatial comparison) + """ + return self._get_postgis_comp_sql(table, col, value, params, op="ST_Touches") + + def get_geo_within_sql(self, table, col, value, params): + """Returns raw sql for geo_within operator + (used for spatial comparison) + """ + return self._get_postgis_comp_sql(table, col, value, params, op="ST_Within") + + def get_geo_contains_sql(self, table, col, value, params): + """Returns raw sql for geo_contains operator + (used for spatial comparison) + """ + return self._get_postgis_comp_sql(table, col, value, params, op="ST_Contains") diff --git a/base_geoengine/i18n/base_geoengine.pot b/base_geoengine/i18n/base_geoengine.pot new file mode 100644 index 000000000..35bcde7b3 --- /dev/null +++ b/base_geoengine/i18n/base_geoengine.pot @@ -0,0 +1,946 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_geoengine +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +msgid "%s column does not exists or is not a geo field" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__active_on_startup +msgid "Active On Startup" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +msgid "Add new value" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +msgid "Add tag" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__attribute_field_id +msgid "Attribute field" +msgstr "" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_base +msgid "Base" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__basic +msgid "Basic" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__begin_color +msgid "Begin color class" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Classification" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__classification +msgid "Classification mode" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__type +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__code +msgid "Code" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__colored +msgid "Colored range/Chroma.js" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Colors" +msgstr "" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_base_view_menu +msgid "Configuration" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__gist_index +msgid "Create gist index" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__create_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__create_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__create_uid +msgid "Created by" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__create_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__create_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__create_date +msgid "Created on" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__custom +msgid "Custom" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__default_extent +msgid "Default map extent" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__default_zoom +msgid "Default map zoom" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__params +msgid "Dictiorary of values for dimensions as JSON" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__dimensions +msgid "Dimensions" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.xml:0 +msgid "Discard" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__display_polygon_labels +msgid "Display Labels on Polygon" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__display_name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__display_name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__display_name +msgid "Display Name" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__d_wms +msgid "Distant WMS" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +msgid "Domain editing" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +msgid "Editing Raster Layer" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +msgid "Editing vector layer" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__end_color +msgid "End color class" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_db.py:0 +msgid "" +"Error, can not automatically initialize spatial postgis support. Database user may have to be superuser and postgres/postgis extensions with their devel header have to be installed. If you do not want Odoo to connect with a super user you can manually prepare your database. To do this, open a client to your database using a super user and run:\n" +"CREATE EXTENSION postgis;\n" +"CREATE EXTENSION postgis_topology;\n" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__ttype +msgid "Field Type" +msgstr "" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_ir_model_fields +msgid "Fields" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__format_suffix +msgid "Format" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "General" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +msgid "" +"Geo Value %(geom_type)s must be of the same type %(geo_type)s" +" as fields" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +msgid "" +"Geo dimention modification is not implemented. We can not change dimention " +"%(data)s to %(dim)s" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__geo_field_id +msgid "Geo field" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +msgid "" +"Geo type modification is not implemented. We can not change type %(data)s to" +" %(geo_type)s" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_ui_view__type__geoengine +msgid "GeoEngine" +msgstr "" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_base_menu +msgid "GeoEngine Backend" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "GeoEngine Data" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_view.esm.js:0 +msgid "Geoengine" +msgstr "" + +#. module: base_geoengine +#: model:res.groups,name:base_geoengine.group_geoengine_admin +msgid "Geoengine Admin" +msgstr "" + +#. module: base_geoengine +#: model:res.groups,name:base_geoengine.group_geoengine_user +msgid "Geoengine User" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__has_type +msgid "Has Type" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__id +msgid "ID" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__interval +msgid "Interval" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__is_wms +msgid "Is Wms" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__is_wmts +msgid "Is Wmts" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__overlay +msgid "Is overlay layer?" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__write_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__write_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__write_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__write_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__write_date +msgid "Last Updated on" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__type_id +msgid "Layer" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__name +msgid "Layer Name" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__layer_opacity +msgid "Layer Opacity" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__sequence +msgid "Layer Priority" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__layer_transparent +msgid "Layer Transparent" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Layer data" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__readonly +msgid "Layer is read only" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__sequence +msgid "Layer priority" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__active_on_startup +msgid "Layer will be shown on startup if checked." +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +msgid "Layers (" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__linestring +msgid "LineString" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__dimensions +msgid "List of dimensions separated by ','" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__matrix_set +msgid "Matrix set" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__max_extent +msgid "Max extent" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_arch_parser.esm.js:0 +msgid "Missing ${INFO_BOX_ATTRIBUTE} template." +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_name +msgid "Model" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_domain +msgid "Model Domain" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_id +msgid "Model to use" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_view_id +msgid "Model view" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multilinestring +msgid "MultiLineString" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multipoint +msgid "MultiPoint" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multipolygon +msgid "MultiPolygon" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__name +msgid "Name" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__params_wms +msgid "Need to provide at least a LAYERS param" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +msgid "New record" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +msgid "" +"No GeoEngine view defined for the model %s. Please " +"create a view or modify view mode" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +msgid "No raster layer for view %s" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__nb_class +msgid "Number of class" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_renderer/geoengine_renderer.xml:0 +msgid "OPEN" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__odoo +msgid "Odoo field" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Odoo layer data (Not implemented)" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__field_id +msgid "Odoo layer field to use" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__opacity +msgid "Opacity" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__osm +msgid "OpenStreetMap" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__params +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Params" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__params_wms +msgid "Params Wms" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__point +msgid "Point" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__polygon +msgid "Polygon" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__dim +msgid "PostGIs Dimension" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__geo_type +msgid "PostGIs type" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__projection +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__projection +msgid "Projection" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__proportion +msgid "Proportional Symbol" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__quantile +msgid "Quantile" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "Raster (Background layers)" +msgstr "" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_form_view_raster_action +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_rater_action +#: model:ir.model,name:base_geoengine.model_geoengine_raster_layer +msgid "Raster Layer" +msgstr "" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_raster_layer_menu +msgid "Raster Layer Management" +msgstr "" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_geoengine_raster_layer_type +msgid "Raster Layer Type" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Raster Layer View" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__raster_type +msgid "Raster layer type" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__raster_layer_ids +msgid "Raster layers" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +msgid "Rasters" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/records_panel/records_panel.xml:0 +msgid "Records (" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Related Model" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__view_id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__view_id +msgid "Related View" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +msgid "Remove tag" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Representation" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__geo_repr +msgid "Representation mode" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +msgid "" +"Reprojection of column is not implemented. We can not change srid %(srid)s " +"to %(data)s" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__request_encoding +msgid "Request encoding" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__resolutions +msgid "Resolutions" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__restricted_extent +msgid "Restricted map extent" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.xml:0 +msgid "Save" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/records_panel/search_bar_records/search_bar_records.xml:0 +msgid "Search..." +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__server_type +msgid "Server Type" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__service +msgid "Service" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__url +msgid "Service URL" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_convertion_helper.py:0 +msgid "Shapely or geojson are not available in the sys path" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field_input/domain_selector_geo_field_input.esm.js:0 +msgid "Subdomain" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +msgid "The geo_field_id must be a field in %s model" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__server_type +msgid "" +"The type of the remote WMS server: mapserver, geoserver, " +"carmentaserver, or qgis" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__unique +msgid "Unique value" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__units +msgid "Units" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__use_to_edit +msgid "Use to edit" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Vector" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "Vector (Active layers)" +msgstr "" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_raster_action +#: model:ir.actions.act_window,name:base_geoengine.geo_vector_geoengine_view_action +#: model:ir.model,name:base_geoengine.model_geoengine_vector_layer +msgid "Vector Layer" +msgstr "" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_vector_layer_menu +msgid "Vector Layer Management" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__vector_layer_ids +msgid "Vector layers" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +msgid "Vectors" +msgstr "" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_ir_ui_view +msgid "View" +msgstr "" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_view_menu +msgid "View Management" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__type +msgid "View Type" +msgstr "" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_action +msgid "Views" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "WMS options" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__wmts +msgid "WMTS" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "WMTS options" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +msgid "Warning" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_convertion_helper.py:0 +msgid "" +"Write/create/search geo type must be wkt/geojson string or must respond to " +"wkt" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +msgid "" +"You are about to create a new record without having displayed all the " +"others. A risk of overlap could occur. Would you like to continue ?" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +msgid "You must at least provide one of domain or geo_domain" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +msgid "You need to provide an attribute that exists in %s model" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +msgid "You need to select a numeric field" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__projection +msgid "eg. EPSG:21781" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__request_encoding +msgid "eg. REST" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__units +msgid "eg. m" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__format_suffix +msgid "eg. png" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +msgid "geo_contains" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +msgid "geo_equal" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +msgid "geo_greater" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +msgid "geo_intersect" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +msgid "geo_lesser" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_line +msgid "geo_line" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_line +msgid "geo_multi_line" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_point +msgid "geo_multi_point" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_polygon +msgid "geo_multi_polygon" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_point +msgid "geo_point" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_polygon +msgid "geo_polygon" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +msgid "geo_search is deprecated: uses search method defined on base model" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +msgid "geo_touch" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +msgid "geo_within" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +msgid "" +"geometry_columns table seems to be corrupted. SRID check is not possible" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__begin_color +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__end_color +msgid "hex value" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_number_field/domain_selector_number_field.esm.js:0 +msgid "in active_ids" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_number_field/domain_selector_number_field.esm.js:0 +msgid "not in active_ids" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__srid +msgid "srid" +msgstr "" diff --git a/base_geoengine/i18n/es.po b/base_geoengine/i18n/es.po new file mode 100644 index 000000000..9c09f6137 --- /dev/null +++ b/base_geoengine/i18n/es.po @@ -0,0 +1,1044 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_geoengine +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-08-08 11:10+0000\n" +"Last-Translator: Ivorra78 \n" +"Language-Team: none\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "%s column does not exists or is not a geo field" +msgstr "La columna %s no existe o no es un campo geográfico" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__active_on_startup +msgid "Active On Startup" +msgstr "Activo en el arranque" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#, python-format +msgid "Add new value" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#, python-format +msgid "Add tag" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__attribute_field_id +msgid "Attribute field" +msgstr "Campo de atributo" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_base +msgid "Base" +msgstr "Base/Fuente" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__basic +msgid "Basic" +msgstr "Básico" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__begin_color +msgid "Begin color class" +msgstr "Iniciar clase de color" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Classification" +msgstr "Clasificación" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__classification +msgid "Classification mode" +msgstr "Modo de clasificación" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__type +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__code +msgid "Code" +msgstr "Código" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__colored +msgid "Colored range/Chroma.js" +msgstr "Gama de colores/Chroma.js" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Colors" +msgstr "Colores" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_base_view_menu +msgid "Configuration" +msgstr "Configuración" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__gist_index +msgid "Create gist index" +msgstr "Crear un índice gist" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__create_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__create_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__create_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__create_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__custom +msgid "Custom" +msgstr "Personalizar" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__default_extent +msgid "Default map extent" +msgstr "Extensión predeterminada del mapa" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__default_zoom +msgid "Default map zoom" +msgstr "Zoom predeterminado del mapa" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__params +msgid "Dictiorary of values for dimensions as JSON" +msgstr "Diccionario de valores de las dimensiones en formato JSON" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__dimensions +msgid "Dimensions" +msgstr "Dimensiones" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.xml:0 +#, python-format +msgid "Discard" +msgstr "Descartar" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__display_polygon_labels +msgid "Display Labels on Polygon" +msgstr "Mostrar etiquetas en el polígono" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__display_name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__display_name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__display_name +msgid "Display Name" +msgstr "Mostrar Nombre" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__d_wms +msgid "Distant WMS" +msgstr "Sistema de gestión de almacenes (SGA) a distancia" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +#, python-format +msgid "Domain editing" +msgstr "Editando Dominio" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +#, python-format +msgid "Editing Raster Layer" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +#, python-format +msgid "Editing vector layer" +msgstr "Edición de capas vectoriales" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__end_color +msgid "End color class" +msgstr "Fin de la clase de color" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_db.py:0 +#, python-format +msgid "" +"Error, can not automatically initialize spatial postgis support. Database " +"user may have to be superuser and postgres/postgis extensions with their " +"devel header have to be installed. If you do not want Odoo to connect with a " +"super user you can manually prepare your database. To do this, open a client " +"to your database using a super user and run:\n" +"CREATE EXTENSION postgis;\n" +"CREATE EXTENSION postgis_topology;\n" +msgstr "" +"Error, no se puede inicializar automáticamente el soporte espacial postgis. " +"El usuario de la base de datos debe ser superusuario y las extensiones " +"postgres/postgis con su cabecera devel deben estar instaladas. Si no quieres " +"que Odoo se conecte con un superusuario puedes preparar manualmente tu base " +"de datos. Para hacer esto, abre un cliente a tu base de datos usando un " +"superusuario y ejecuta\n" +"CREAR EXTENSIÓN postgis;\n" +"CREAR EXTENSIÓN postgis_topología;\n" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__ttype +msgid "Field Type" +msgstr "Tipo de campo" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_ir_model_fields +msgid "Fields" +msgstr "Campos" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__format_suffix +msgid "Format" +msgstr "Formato" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "General" +msgstr "General" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Geo Value %(geom_type)s must be of the same type " +"%(geo_type)s as fields" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Geo dimention modification is not implemented. We can not change dimention " +"%(data)s to %(dim)s" +msgstr "" +"La modificación de la dimensión geográfica no está implementada. No podemos " +"cambiar la dimensión %(data)s a %(dim)s" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__geo_field_id +msgid "Geo field" +msgstr "Campo geográfico" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Geo type modification is not implemented. We can not change type %(data)s to " +"%(geo_type)s" +msgstr "" +"La modificación del geotipo no está implementada. No podemos cambiar el tipo " +"%(data)s a %(geo_type)s" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_ui_view__type__geoengine +msgid "GeoEngine" +msgstr "GeoIngeniería" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_base_menu +msgid "GeoEngine Backend" +msgstr "Servidor de Geoingeniería" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "GeoEngine Data" +msgstr "Fecha de Geoingeniería" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_view.esm.js:0 +#, python-format +msgid "Geoengine" +msgstr "Geoingeniería" + +#. module: base_geoengine +#: model:res.groups,name:base_geoengine.group_geoengine_admin +msgid "Geoengine Admin" +msgstr "Administración de Geoingeniería" + +#. module: base_geoengine +#: model:res.groups,name:base_geoengine.group_geoengine_user +msgid "Geoengine User" +msgstr "Usuario de Geoingeniería" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__has_type +msgid "Has Type" +msgstr "Tiene Tipo" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__id +msgid "ID" +msgstr "ID (identificación)" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__interval +msgid "Interval" +msgstr "Intervalo" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__is_wms +msgid "Is Wms" +msgstr "Es Wms" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__is_wmts +msgid "Is Wmts" +msgstr "Es Wmts" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__overlay +msgid "Is overlay layer?" +msgstr "¿Es una capa de superposición?" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__write_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__write_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__write_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__write_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__write_date +msgid "Last Updated on" +msgstr "Última Actualización el" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__type_id +msgid "Layer" +msgstr "Capa" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__name +msgid "Layer Name" +msgstr "nombre de Capa" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__layer_opacity +msgid "Layer Opacity" +msgstr "Opacidad de la capa" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__sequence +msgid "Layer Priority" +msgstr "Prioridad de Capa" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__layer_transparent +msgid "Layer Transparent" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Layer data" +msgstr "Fecha de Capa" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__readonly +msgid "Layer is read only" +msgstr "La capa es de sólo lectura" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__sequence +msgid "Layer priority" +msgstr "Prioridad de Capa" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__active_on_startup +msgid "Layer will be shown on startup if checked." +msgstr "La capa se mostrará al inicio si está marcada." + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +#, python-format +msgid "Layers (" +msgstr "Capas (" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__linestring +msgid "LineString" +msgstr "Secuencia de líneas" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__dimensions +msgid "List of dimensions separated by ','" +msgstr "Lista de dimensiones separadas por ','" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__matrix_set +msgid "Matrix set" +msgstr "Conjunto matriz" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__max_extent +msgid "Max extent" +msgstr "Extensión máxima" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_arch_parser.esm.js:0 +#, python-format +msgid "Missing ${INFO_BOX_ATTRIBUTE} template." +msgstr "Falta la plantilla ${INFO_BOX_ATTRIBUTE}." + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_name +msgid "Model" +msgstr "Modelo" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_domain +msgid "Model Domain" +msgstr "Dominio del modelo" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_id +msgid "Model to use" +msgstr "Modelo a utilizar" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_view_id +msgid "Model view" +msgstr "Vista del modelo" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multilinestring +msgid "MultiLineString" +msgstr "Cadena multilínea" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multipoint +msgid "MultiPoint" +msgstr "Punto Múltiple" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multipolygon +msgid "MultiPolygon" +msgstr "Multipolígono" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__name +msgid "Name" +msgstr "Nombre" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__params_wms +msgid "Need to provide at least a LAYERS param" +msgstr "Necesidad de proporcionar al menos un parámetro de CAPAS" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +#, python-format +msgid "New record" +msgstr "Nuevo récord" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "" +"No GeoEngine view defined for the model %s. Please " +"create a view or modify view mode" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "No raster layer for view %s" +msgstr "No hay capa ráster para la vista %s" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__nb_class +msgid "Number of class" +msgstr "Número de clase" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_renderer/geoengine_renderer.xml:0 +#, python-format +msgid "OPEN" +msgstr "ABRIR" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__odoo +msgid "Odoo field" +msgstr "Campo de odoo" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Odoo layer data (Not implemented)" +msgstr "Datos de la capa Odoo (No implementado)" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__field_id +msgid "Odoo layer field to use" +msgstr "Campo de capa de Odoo a utilizar" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__opacity +msgid "Opacity" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__osm +msgid "OpenStreetMap" +msgstr "OpenStreetMap" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__params +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Params" +msgstr "Parámetros" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__params_wms +msgid "Params Wms" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__point +msgid "Point" +msgstr "Punto" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__polygon +msgid "Polygon" +msgstr "Polígono" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__dim +msgid "PostGIs Dimension" +msgstr "Dimensión PostGIs" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__geo_type +msgid "PostGIs type" +msgstr "Tipo PostGIs" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__projection +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__projection +msgid "Projection" +msgstr "Proyección" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__proportion +msgid "Proportional Symbol" +msgstr "Símbolo proporcional" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__quantile +msgid "Quantile" +msgstr "Cuantil" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "Raster (Background layers)" +msgstr "Ráster (capas de fondo)" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_form_view_raster_action +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_rater_action +#: model:ir.model,name:base_geoengine.model_geoengine_raster_layer +msgid "Raster Layer" +msgstr "Capa Ráster" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_raster_layer_menu +msgid "Raster Layer Management" +msgstr "Gestión de capas rasterizadas" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_geoengine_raster_layer_type +msgid "Raster Layer Type" +msgstr "Tipo de capa rasterizada" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Raster Layer View" +msgstr "Vista de capa rasterizada" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__raster_type +msgid "Raster layer type" +msgstr "Tipo de capa rasterizada" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__raster_layer_ids +msgid "Raster layers" +msgstr "Capas Ráster" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +#, python-format +msgid "Rasters" +msgstr "Rásteres" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/records_panel/records_panel.xml:0 +#, python-format +msgid "Records (" +msgstr "Registros (" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Related Model" +msgstr "Modelo relacionado" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__view_id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__view_id +msgid "Related View" +msgstr "Vista relacionada" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#, python-format +msgid "Remove tag" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Representation" +msgstr "Representación" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__geo_repr +msgid "Representation mode" +msgstr "Modo de representación" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Reprojection of column is not implemented. We can not change srid %(srid)s " +"to %(data)s" +msgstr "" +"La reproyección de columna no está implementada. No podemos cambiar srid " +"%(srid)s por %(data)s" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__request_encoding +msgid "Request encoding" +msgstr "Solicitar codificación" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__resolutions +msgid "Resolutions" +msgstr "Resoluciones" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__restricted_extent +msgid "Restricted map extent" +msgstr "Extensión de mapa restringida" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.xml:0 +#, python-format +msgid "Save" +msgstr "Guardar" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/records_panel/search_bar_records/search_bar_records.xml:0 +#, python-format +msgid "Search..." +msgstr "Buscar..." + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__server_type +msgid "Server Type" +msgstr "Tipo de servidor" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__service +msgid "Service" +msgstr "Servicio" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__url +msgid "Service URL" +msgstr "URL de servicio" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_convertion_helper.py:0 +#, python-format +msgid "Shapely or geojson are not available in the sys path" +msgstr "Shapely o geojson no están disponibles en la ruta del sistema" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field_input/domain_selector_geo_field_input.esm.js:0 +#, python-format +msgid "Subdomain" +msgstr "Subdominio" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +#, python-format +msgid "The geo_field_id must be a field in %s model" +msgstr "El geo_field_id debe ser un campo del modelo %s" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__server_type +msgid "" +"The type of the remote WMS server: mapserver, geoserver, " +"carmentaserver, or qgis" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__unique +msgid "Unique value" +msgstr "Valor único" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__units +msgid "Units" +msgstr "Unidades" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__use_to_edit +msgid "Use to edit" +msgstr "Utilizar para editar" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Vector" +msgstr "Vector" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "Vector (Active layers)" +msgstr "Vector (capas activas)" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_raster_action +#: model:ir.actions.act_window,name:base_geoengine.geo_vector_geoengine_view_action +#: model:ir.model,name:base_geoengine.model_geoengine_vector_layer +msgid "Vector Layer" +msgstr "Capa vectorial" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_vector_layer_menu +msgid "Vector Layer Management" +msgstr "Gestión de capas vectoriales" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__vector_layer_ids +msgid "Vector layers" +msgstr "Capas vectoriales" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +#, python-format +msgid "Vectors" +msgstr "Vectores" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_ir_ui_view +msgid "View" +msgstr "Vista" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_view_menu +msgid "View Management" +msgstr "Gestión de visualización" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__type +msgid "View Type" +msgstr "Tipo de vista" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_action +msgid "Views" +msgstr "Vistas" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "WMS options" +msgstr "Opciones WMS" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__wmts +msgid "WMTS" +msgstr "WMTS" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "WMTS options" +msgstr "Opciones WMTS" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +#, python-format +msgid "Warning" +msgstr "Aviso" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_convertion_helper.py:0 +#, python-format +msgid "" +"Write/create/search geo type must be wkt/geojson string or must respond to " +"wkt" +msgstr "" +"Write/create/search geo type debe ser wkt/geojson string o debe responder a " +"wkt" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +#, python-format +msgid "" +"You are about to create a new record without having displayed all the " +"others. A risk of overlap could occur. Would you like to continue ?" +msgstr "" +"Está a punto de crear un nuevo registro sin haber visualizado todos los " +"demás. Podría producirse un riesgo de solapamiento. ¿Desea continuar?" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "You must at least provide one of domain or geo_domain" +msgstr "Debe proporcionar al menos uno de los dominios o geo_domain" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +#, python-format +msgid "You need to provide an attribute that exists in %s model" +msgstr "Necesita proporcionar un atributo que existe en el modelo %s" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +#, python-format +msgid "You need to select a numeric field" +msgstr "Debe seleccionar un campo numérico" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__projection +msgid "eg. EPSG:21781" +msgstr "ej. EPSG:21781" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__request_encoding +msgid "eg. REST" +msgstr "ej. REST" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__units +msgid "eg. m" +msgstr "ej. m" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__format_suffix +msgid "eg. png" +msgstr "ej. png" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_contains" +msgstr "geo_contains (geo_contenedores)" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_equal" +msgstr "geo_equal (geo_igual)" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_greater" +msgstr "geo_greater (geo_mayor)" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_intersect" +msgstr "geo_intersect (geo_intersección)" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_lesser" +msgstr "geo_lesser (geo_menor)" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_line +msgid "geo_line" +msgstr "geo_line (geo_línea)" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_line +msgid "geo_multi_line" +msgstr "geo_multi_line (geo_multi_línea)" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_point +msgid "geo_multi_point" +msgstr "geo_multi_point (geo_multi_punto)" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_polygon +msgid "geo_multi_polygon" +msgstr "geo_multi_polygon (geo_multi_polígono)" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_point +msgid "geo_point" +msgstr "geo_point (geo_punto)" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_polygon +msgid "geo_polygon" +msgstr "geo_polygon (geo_polígono)" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "geo_search is deprecated: uses search method defined on base model" +msgstr "" +"geo_search está obsoleto: utiliza el método de búsqueda definido en el " +"modelo base" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_touch" +msgstr "geo_touch (geo_táctil)" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_within" +msgstr "geo_within (geo_interior)" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"geometry_columns table seems to be corrupted. SRID check is not possible" +msgstr "" +"La tabla geometry_columns parece estar dañada. No es posible comprobar el " +"SRID" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__begin_color +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__end_color +msgid "hex value" +msgstr "valor hexadecimal" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_number_field/domain_selector_number_field.esm.js:0 +#, python-format +msgid "in active_ids" +msgstr "En active_ids" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_number_field/domain_selector_number_field.esm.js:0 +#, python-format +msgid "not in active_ids" +msgstr "No en active_ids" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__srid +msgid "srid" +msgstr "srid" + +#, python-format +#~ msgid "" +#~ "Geo Value %(geom_type)s must be of the same type %(geo_type)s as fields" +#~ msgstr "" +#~ "Los valores geográficos %(geom_type)s deben ser del mismo tipo " +#~ "%(geo_type)s que los campos" + +#~ msgid "Last Modified on" +#~ msgstr "Última Modificación el" + +#, python-format +#~ msgid "No GeoEngine view defined for the model %s" +#~ msgstr "No se definió una vista de GeoIngeniería para el modelo %s" + +#, python-format +#~ msgid "Please create a view or modify view mode" +#~ msgstr "Por favor, cree una vista o modifique el modo de vista" + +#~ msgid "" +#~ "The type of the remote WMS server: mapserver, geoserver, carmentaserver, " +#~ "or qgis" +#~ msgstr "" +#~ "Tipo de servidor WMS remoto: mapserver, geoserver, carmentaserver o qgis" diff --git a/base_geoengine/i18n/fr_BE.po b/base_geoengine/i18n/fr_BE.po new file mode 100644 index 000000000..34ca132cd --- /dev/null +++ b/base_geoengine/i18n/fr_BE.po @@ -0,0 +1,1046 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_geoengine +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-05-15 06:18+0000\n" +"PO-Revision-Date: 2023-05-15 06:18+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "%s column does not exists or is not a geo field" +msgstr "%s la colonne n'existe pas ou n'est pas un champ géographique" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__active_on_startup +msgid "Active On Startup" +msgstr "Actif au démarrage" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#, python-format +msgid "Add new value" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#, python-format +msgid "Add tag" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__attribute_field_id +msgid "Attribute field" +msgstr "Attribut" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_base +msgid "Base" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__basic +msgid "Basic" +msgstr "Basique" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__begin_color +msgid "Begin color class" +msgstr "Début de la classe de couleur" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Classification" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__classification +msgid "Classification mode" +msgstr "Mode de classification" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__type +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__code +msgid "Code" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__colored +msgid "Colored range/Chroma.js" +msgstr "Plage de couleurs/Chroma.js" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Colors" +msgstr "Couleurs" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_base_view_menu +msgid "Configuration" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__gist_index +msgid "Create gist index" +msgstr "Création d'un index gist" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__create_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__create_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__create_uid +msgid "Created by" +msgstr "Créé par" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__create_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__create_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__create_date +msgid "Created on" +msgstr "Créé le" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__custom +msgid "Custom" +msgstr "Personnalisable" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__default_extent +msgid "Default map extent" +msgstr "Étendue de la carte par défaut" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__default_zoom +msgid "Default map zoom" +msgstr "Zoom par défaut de la carte" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__params +msgid "Dictiorary of values for dimensions as JSON" +msgstr "Liste de valeurs pour les dimensions sous forme de JSON" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__dimensions +msgid "Dimensions" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.xml:0 +#, python-format +msgid "Discard" +msgstr "Annuler" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__display_polygon_labels +msgid "Display Labels on Polygon" +msgstr "Afficher les étiquettes sur les polygones" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__display_name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__display_name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__display_name +msgid "Display Name" +msgstr "Nom d'affichage" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__d_wms +msgid "Distant WMS" +msgstr "WMS distant" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +#, python-format +msgid "Domain editing" +msgstr "Édition du domaine" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +#, python-format +msgid "Editing Raster Layer" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +#, python-format +msgid "Editing vector layer" +msgstr "Edition de la couche vectorielle" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__end_color +msgid "End color class" +msgstr "Fin de la classe de couleur" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_db.py:0 +#, python-format +msgid "" +"Error, can not automatically initialize spatial postgis support. Database " +"user may have to be superuser and postgres/postgis extensions with their " +"devel header have to be installed. If you do not want Odoo to connect with a " +"super user you can manually prepare your database. To do this, open a client " +"to your database using a super user and run:\n" +"CREATE EXTENSION postgis;\n" +"CREATE EXTENSION postgis_topology;\n" +msgstr "" +"Erreur, impossible d'initialiser automatiquement le support spatial postigs. " +"L'utilisateur de la base de données doit être un super utilisateur et les " +"extensions postgres/postgis doivent être installées avec leurs en-tête " +"devel. Si vous ne voulez pas qu'Odoo se connecte avec un super utilisateur, " +"vous pouvez préparer manuellement votre base de données. Pour ce faire, " +"ouvrez un client à votre base de données en utilisant un super utilisateur " +"et exécutez:\n" +"CREATE EXTENSION postgis;\n" +"CREATE EXTENSION postgis_topology;\n" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__ttype +msgid "Field Type" +msgstr "Type de champ" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_ir_model_fields +msgid "Fields" +msgstr "Champs" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__format_suffix +msgid "Format" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "General" +msgstr "Général" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Geo Value %(geom_type)s must be of the same type " +"%(geo_type)s as fields" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Geo dimention modification is not implemented. We can not change dimention " +"%(data)s to %(dim)s" +msgstr "" +"La modification de la dimension de la géométrie n'est pas implémentée. Nous " +"ne pouvons pas modifier la dimension %(data)s to %(dim)s" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__geo_field_id +msgid "Geo field" +msgstr "Champ géographique" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Geo type modification is not implemented. We can not change type %(data)s to " +"%(geo_type)s" +msgstr "" +"La modification du type de la géométrie n'est pas implémentée. Nous ne " +"pouvons pas changer le type %(data)s to %(geo_type)s" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_ui_view__type__geoengine +msgid "GeoEngine" +msgstr "" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_base_menu +msgid "GeoEngine Backend" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "GeoEngine Data" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_view.esm.js:0 +#, python-format +msgid "Geoengine" +msgstr "" + +#. module: base_geoengine +#: model:res.groups,name:base_geoengine.group_geoengine_admin +msgid "Geoengine Admin" +msgstr "Admin Geoengine" + +#. module: base_geoengine +#: model:res.groups,name:base_geoengine.group_geoengine_user +msgid "Geoengine User" +msgstr "Utilisateur GeoEngine" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__has_type +msgid "Has Type" +msgstr "A le type" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__id +msgid "ID" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__interval +msgid "Interval" +msgstr "Intervalle" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__is_wms +msgid "Is Wms" +msgstr "Est un Wms" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__is_wmts +msgid "Is Wmts" +msgstr "Est un Wmts" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__overlay +msgid "Is overlay layer?" +msgstr "S'agit-il d'une couche superposée ?" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__write_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__write_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__write_uid +msgid "Last Updated by" +msgstr "Dernière mise à jour par" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__write_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__write_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__write_date +msgid "Last Updated on" +msgstr "Dernière mise à jour le" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__type_id +msgid "Layer" +msgstr "Couche" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__name +msgid "Layer Name" +msgstr "Nom de la couche" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__layer_opacity +msgid "Layer Opacity" +msgstr "Opacité de la couche" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__sequence +msgid "Layer Priority" +msgstr "Priorité de la couche" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__layer_transparent +msgid "Layer Transparent" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Layer data" +msgstr "Données de la couche" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__readonly +msgid "Layer is read only" +msgstr "La couche est en lecture seule" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__sequence +msgid "Layer priority" +msgstr "Priorité de la couche" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__active_on_startup +msgid "Layer will be shown on startup if checked." +msgstr "Si cette case est cochée, la couche sera affichée au démarrage" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +#, python-format +msgid "Layers (" +msgstr "Couches (" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__linestring +msgid "LineString" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__dimensions +msgid "List of dimensions separated by ','" +msgstr "Liste des dimensions séparées par ','" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__matrix_set +msgid "Matrix set" +msgstr "Ensemble matriciel" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__max_extent +msgid "Max extent" +msgstr "Étendue maximum" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_arch_parser.esm.js:0 +#, python-format +msgid "Missing ${INFO_BOX_ATTRIBUTE} template." +msgstr "Template ${INFO_BOX_ATTRIBUTE} manquant." + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_name +msgid "Model" +msgstr "Modèle" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_domain +msgid "Model Domain" +msgstr "Domaine du modèle" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_id +msgid "Model to use" +msgstr "Modèle à utiliser" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_view_id +msgid "Model view" +msgstr "Vue du modèle" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multilinestring +msgid "MultiLineString" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multipoint +msgid "MultiPoint" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multipolygon +msgid "MultiPolygon" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__name +msgid "Name" +msgstr "Nom" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__params_wms +msgid "Need to provide at least a LAYERS param" +msgstr "Besoin de fournir au moins un paramètre LAYERS" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +#, python-format +msgid "New record" +msgstr "Nouvel enregistrement" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "" +"No GeoEngine view defined for the model %s. Please " +"create a view or modify view mode" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "No raster layer for view %s" +msgstr "Pas de couche d'arrière-plan pour la vue %s" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__nb_class +msgid "Number of class" +msgstr "Nombre de classe" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_renderer/geoengine_renderer.xml:0 +#, python-format +msgid "OPEN" +msgstr "OUVRIR" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__odoo +msgid "Odoo field" +msgstr "Champ Odoo" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Odoo layer data (Not implemented)" +msgstr "Données de couche Odoo (non implémenté)" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__field_id +msgid "Odoo layer field to use" +msgstr "Champ de couche Odoo à utiliser" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__opacity +msgid "Opacity" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__osm +msgid "OpenStreetMap" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__params +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Params" +msgstr "Paramètres" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__params_wms +msgid "Params Wms" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__point +msgid "Point" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__polygon +msgid "Polygon" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__dim +msgid "PostGIs Dimension" +msgstr "Dimension PostGIs" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__geo_type +msgid "PostGIs type" +msgstr "Type PostGIs" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__projection +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__projection +msgid "Projection" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__proportion +msgid "Proportional Symbol" +msgstr "Symbole proportionnel" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__quantile +msgid "Quantile" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "Raster (Background layers)" +msgstr "Raster (Couches d'arrière-plan)" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_form_view_raster_action +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_rater_action +#: model:ir.model,name:base_geoengine.model_geoengine_raster_layer +msgid "Raster Layer" +msgstr "Couche d'arrière-plan" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_raster_layer_menu +msgid "Raster Layer Management" +msgstr "Gestion des couches d'arrière-plan" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_geoengine_raster_layer_type +msgid "Raster Layer Type" +msgstr "Type de couche d'arrière-plan" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Raster Layer View" +msgstr "Vue de la couche d'arrière-plan" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__raster_type +msgid "Raster layer type" +msgstr "Type de couche d'arrière-plan" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__raster_layer_ids +msgid "Raster layers" +msgstr "Couches d'arrière-plan" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +#, python-format +msgid "Rasters" +msgstr "Couches d'arrière-plan" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/records_panel/records_panel.xml:0 +#, python-format +msgid "Records (" +msgstr "Enregistrements (" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Related Model" +msgstr "Modèle associé" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__view_id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__view_id +msgid "Related View" +msgstr "Vue associé" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#, python-format +msgid "Remove tag" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Representation" +msgstr "Représentation" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__geo_repr +msgid "Representation mode" +msgstr "Mode de représentation" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Reprojection of column is not implemented. We can not change srid %(srid)s " +"to %(data)s" +msgstr "" +"La reprojection de la colonne n'est pas mise en oeuvre. Nous ne pouvons pas " +"modifier le srid %(srid)s to %(data)s" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__request_encoding +msgid "Request encoding" +msgstr "Demande d'encodage" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__resolutions +msgid "Resolutions" +msgstr "Résolutions" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__restricted_extent +msgid "Restricted map extent" +msgstr "Limitation de l'étendue de la carte" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.xml:0 +#, python-format +msgid "Save" +msgstr "Sauvegarder" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/records_panel/search_bar_records/search_bar_records.xml:0 +#, python-format +msgid "Search..." +msgstr "Rechercher..." + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__server_type +msgid "Server Type" +msgstr "Type de serveur" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__service +msgid "Service" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__url +msgid "Service URL" +msgstr "URL du service" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_convertion_helper.py:0 +#, python-format +msgid "Shapely or geojson are not available in the sys path" +msgstr "" +"Shapely ou geojson ne sont pas disponibles dans le chemin d'accès système" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field_input/domain_selector_geo_field_input.esm.js:0 +#, python-format +msgid "Subdomain" +msgstr "Sous domaine" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +#, python-format +msgid "The geo_field_id must be a field in %s model" +msgstr "Le geo_field_id doit être un champ dans le modèle %s" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__server_type +msgid "" +"The type of the remote WMS server: mapserver, geoserver, " +"carmentaserver, or qgis" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__unique +msgid "Unique value" +msgstr "Valeur unique" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__units +msgid "Units" +msgstr "Unités" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__use_to_edit +msgid "Use to edit" +msgstr "Autorisation d'édition" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Vector" +msgstr "Vecteur" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "Vector (Active layers)" +msgstr "Vecteur (couche actives)" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_raster_action +#: model:ir.actions.act_window,name:base_geoengine.geo_vector_geoengine_view_action +#: model:ir.model,name:base_geoengine.model_geoengine_vector_layer +msgid "Vector Layer" +msgstr "Couche vectorielle" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_vector_layer_menu +msgid "Vector Layer Management" +msgstr "Gestion des couches vectorielles" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__vector_layer_ids +msgid "Vector layers" +msgstr "Couches vectorielles" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +#, python-format +msgid "Vectors" +msgstr "Couches vectorielles" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_ir_ui_view +msgid "View" +msgstr "Vue" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_view_menu +msgid "View Management" +msgstr "Gestion des vues" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__type +msgid "View Type" +msgstr "Type de vue" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_action +msgid "Views" +msgstr "Vues" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "WMS options" +msgstr "Options du WMS" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__wmts +msgid "WMTS" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "WMTS options" +msgstr "Options du WMTS" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +#, python-format +msgid "Warning" +msgstr "Attention" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_convertion_helper.py:0 +#, python-format +msgid "" +"Write/create/search geo type must be wkt/geojson string or must respond to " +"wkt" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +#, python-format +msgid "" +"You are about to create a new record without having displayed all the " +"others. A risk of overlap could occur. Would you like to continue ?" +msgstr "" +"Vous êtes sur le point de créer un nouvel enregistrement sans avoir affiché " +"tous les autres. Un risque de chevauchement pourrait se produire. Voulez-" +"vous continuer ?" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "You must at least provide one of domain or geo_domain" +msgstr "Vous devez fournir au moins un domaine ou un géo-domaine" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +#, python-format +msgid "You need to provide an attribute that exists in %s model" +msgstr "Vous devez fournir un attribut qui existe dans le modèle %s" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +#, python-format +msgid "You need to select a numeric field" +msgstr "Vous devez sélectionner un champ numérique" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__projection +msgid "eg. EPSG:21781" +msgstr "ex. EPSG:21781" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__request_encoding +msgid "eg. REST" +msgstr "ex. REST" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__units +msgid "eg. m" +msgstr "ex. m" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__format_suffix +msgid "eg. png" +msgstr "ex. png" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_contains" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_equal" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_greater" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_intersect" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_lesser" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_line +msgid "geo_line" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_line +msgid "geo_multi_line" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_point +msgid "geo_multi_point" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_polygon +msgid "geo_multi_polygon" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_point +msgid "geo_point" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_polygon +msgid "geo_polygon" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "geo_search is deprecated: uses search method defined on base model" +msgstr "" +"la méthode geo_search est dépréciée : utilisez la méthode search définie " +"dans le modèle de base" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_touch" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_within" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"geometry_columns table seems to be corrupted. SRID check is not possible" +msgstr "" +"La table geometry_columns semble être corrompue. La vérification de SRID " +"n'est pas possible" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__begin_color +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__end_color +msgid "hex value" +msgstr "valeur hexadécimale" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_number_field/domain_selector_number_field.esm.js:0 +#, python-format +msgid "in active_ids" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_number_field/domain_selector_number_field.esm.js:0 +#, python-format +msgid "not in active_ids" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__srid +msgid "srid" +msgstr "" + +#, python-format +#~ msgid "" +#~ "Geo Value %(geom_type)s must be of the same type %(geo_type)s as fields" +#~ msgstr "" +#~ "La valeur géographique %(geom_type)s doit être du même type %(geo_type)s " +#~ "queles champs" + +#~ msgid "Last Modified on" +#~ msgstr "Dernière modification le" + +#, python-format +#~ msgid "No GeoEngine view defined for the model %s" +#~ msgstr "Aucune vue GeoEngine n'est définie pour le modèle %s" + +#, python-format +#~ msgid "Please create a view or modify view mode" +#~ msgstr "Veuillez créer une vue ou modifier le mode de vue" + +#~ msgid "" +#~ "The type of the remote WMS server: mapserver, geoserver, carmentaserver, " +#~ "or qgis" +#~ msgstr "" +#~ "Le type du serveur WMS distant: mapserver, geoserver, camentaserver, " +#~ "orqgis" diff --git a/base_geoengine/i18n/it.po b/base_geoengine/i18n/it.po new file mode 100644 index 000000000..b7c259406 --- /dev/null +++ b/base_geoengine/i18n/it.po @@ -0,0 +1,1049 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_geoengine +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-09-27 15:06+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.6.2\n" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "%s column does not exists or is not a geo field" +msgstr "La colonna %s non esiste, o non è un campo geo" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__active_on_startup +msgid "Active On Startup" +msgstr "Attivo all'avvio" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#, python-format +msgid "Add new value" +msgstr "Aggiungi nuovo valore" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#, python-format +msgid "Add tag" +msgstr "Aggiungi etichetta" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__attribute_field_id +msgid "Attribute field" +msgstr "Campo attributo" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_base +msgid "Base" +msgstr "Base" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__basic +msgid "Basic" +msgstr "Base" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__begin_color +msgid "Begin color class" +msgstr "Classe colore inizio" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Classification" +msgstr "Classificazione" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__classification +msgid "Classification mode" +msgstr "Modo di classificazione" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__type +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__code +msgid "Code" +msgstr "Codice" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__colored +msgid "Colored range/Chroma.js" +msgstr "Intervallo colorato/Chroma.js" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Colors" +msgstr "Colori" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_base_view_menu +msgid "Configuration" +msgstr "Configurazione" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__gist_index +msgid "Create gist index" +msgstr "Crea indice gist" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__create_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__create_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__create_uid +msgid "Created by" +msgstr "Creato da" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__create_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__create_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__create_date +msgid "Created on" +msgstr "Creato il" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__custom +msgid "Custom" +msgstr "Personalizzato" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__default_extent +msgid "Default map extent" +msgstr "Estensione predefinita della mappa" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__default_zoom +msgid "Default map zoom" +msgstr "Zoom predefinito della mappa" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__params +msgid "Dictiorary of values for dimensions as JSON" +msgstr "Dizionario JSON di valori delle dimensioni" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__dimensions +msgid "Dimensions" +msgstr "Dimensioni" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.xml:0 +#, python-format +msgid "Discard" +msgstr "Abbandona" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__display_polygon_labels +msgid "Display Labels on Polygon" +msgstr "Mostra etichette sul poligono" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__display_name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__display_name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__d_wms +msgid "Distant WMS" +msgstr "WMS remoto" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +#, python-format +msgid "Domain editing" +msgstr "Modifica dminio" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +#, python-format +msgid "Editing Raster Layer" +msgstr "Modifica livello raster" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +#, python-format +msgid "Editing vector layer" +msgstr "Modifica livello vettore" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__end_color +msgid "End color class" +msgstr "Classe colore fine" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_db.py:0 +#, python-format +msgid "" +"Error, can not automatically initialize spatial postgis support. Database " +"user may have to be superuser and postgres/postgis extensions with their " +"devel header have to be installed. If you do not want Odoo to connect with a " +"super user you can manually prepare your database. To do this, open a client " +"to your database using a super user and run:\n" +"CREATE EXTENSION postgis;\n" +"CREATE EXTENSION postgis_topology;\n" +msgstr "" +"Errore, impossibile inizializzare automaticamente il supporto spaziale " +"postgis. L'utente database deve essere superutente e le estensioni postgres/" +"postgis con le loro intestazioni devono essere installate. Se non si vuole " +"che Odoo si connetta con un super utente si può preparare manualmente il " +"database. Per questo, aprire un client verso il database utilizzando un " +"super utente ed eseguendo:\n" +"CREATE EXTENSION postgis;\n" +"CREATE EXTENSION postgis_topology;\n" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__ttype +msgid "Field Type" +msgstr "Tipo campo" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_ir_model_fields +msgid "Fields" +msgstr "Campi" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__format_suffix +msgid "Format" +msgstr "Formato" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "General" +msgstr "Generale" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Geo Value %(geom_type)s must be of the same type " +"%(geo_type)s as fields" +msgstr "" +"Il valore geografico %(geom_type)s deve essere dello stesso tipo %(geo_type)" +"s come campo" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Geo dimention modification is not implemented. We can not change dimention " +"%(data)s to %(dim)s" +msgstr "" +"La modifica della dimensione geo non è implementata. Non si possono cambiare " +"le dimensioni %(data)s a %(dim)s" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__geo_field_id +msgid "Geo field" +msgstr "Campo geo" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Geo type modification is not implemented. We can not change type %(data)s to " +"%(geo_type)s" +msgstr "" +"La modifica del tipo geo non è implementata. Non si può cambiare il tipo " +"%(data)s a %(geo_type)s" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_ui_view__type__geoengine +msgid "GeoEngine" +msgstr "GeoEngine" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_base_menu +msgid "GeoEngine Backend" +msgstr "Backend GeoEngine" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "GeoEngine Data" +msgstr "Dati GeoEngine" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_view.esm.js:0 +#, python-format +msgid "Geoengine" +msgstr "GeoEngine" + +#. module: base_geoengine +#: model:res.groups,name:base_geoengine.group_geoengine_admin +msgid "Geoengine Admin" +msgstr "Amministratore Geoengine" + +#. module: base_geoengine +#: model:res.groups,name:base_geoengine.group_geoengine_user +msgid "Geoengine User" +msgstr "Utente GeoEngine" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__has_type +msgid "Has Type" +msgstr "Ha tipo" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__id +msgid "ID" +msgstr "ID" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__interval +msgid "Interval" +msgstr "Intervallo" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__is_wms +msgid "Is Wms" +msgstr "È WMS" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__is_wmts +msgid "Is Wmts" +msgstr "È WMTS" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__overlay +msgid "Is overlay layer?" +msgstr "È livello in sovraimpressione?" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__write_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__write_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__write_uid +msgid "Last Updated by" +msgstr "Ultimo aggiornamento di" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__write_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__write_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__write_date +msgid "Last Updated on" +msgstr "Ultimo aggiornamento il" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__type_id +msgid "Layer" +msgstr "Livello" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__name +msgid "Layer Name" +msgstr "Nome livello" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__layer_opacity +msgid "Layer Opacity" +msgstr "Opacità ivello" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__sequence +msgid "Layer Priority" +msgstr "Priorità livello" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__layer_transparent +msgid "Layer Transparent" +msgstr "Livello trasparente" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Layer data" +msgstr "Dati ivello" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__readonly +msgid "Layer is read only" +msgstr "Il ivello è in sola lettura" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__sequence +msgid "Layer priority" +msgstr "Priorità livello" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__active_on_startup +msgid "Layer will be shown on startup if checked." +msgstr "Il livello verrà mostrato all'avvio se selezionato." + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +#, python-format +msgid "Layers (" +msgstr "Livelli (" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__linestring +msgid "LineString" +msgstr "Stringa riga" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__dimensions +msgid "List of dimensions separated by ','" +msgstr "Elenco dimensioni separate da ','" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__matrix_set +msgid "Matrix set" +msgstr "Set matrice" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__max_extent +msgid "Max extent" +msgstr "Estensione massima" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_arch_parser.esm.js:0 +#, python-format +msgid "Missing ${INFO_BOX_ATTRIBUTE} template." +msgstr "Modello ${INFO_BOX_ATTRIBUTE} non trovato." + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_name +msgid "Model" +msgstr "Modello" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_domain +msgid "Model Domain" +msgstr "Dominio modello" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_id +msgid "Model to use" +msgstr "Modello da usare" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_view_id +msgid "Model view" +msgstr "Vista modello" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multilinestring +msgid "MultiLineString" +msgstr "Stringa multi riga" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multipoint +msgid "MultiPoint" +msgstr "Punto multiplo" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multipolygon +msgid "MultiPolygon" +msgstr "Poligono multiplo" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__name +msgid "Name" +msgstr "Nome" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__params_wms +msgid "Need to provide at least a LAYERS param" +msgstr "Serve fornire almeno un parametro LAYERS" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +#, python-format +msgid "New record" +msgstr "Nuovo record" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "" +"No GeoEngine view defined for the model %s. Please " +"create a view or modify view mode" +msgstr "" +"Nessuna vista GeoEngine definita per il modello %s. " +"Creare una vista o modificare il modo vista" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "No raster layer for view %s" +msgstr "Nessuno livello raster per la vista %s" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__nb_class +msgid "Number of class" +msgstr "Numero di classi" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_renderer/geoengine_renderer.xml:0 +#, python-format +msgid "OPEN" +msgstr "OPEN" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__odoo +msgid "Odoo field" +msgstr "Campo Odoo" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Odoo layer data (Not implemented)" +msgstr "Livello dati Odoo (non implementato)" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__field_id +msgid "Odoo layer field to use" +msgstr "Livello campo Odoo da usare" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__opacity +msgid "Opacity" +msgstr "Opacità" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__osm +msgid "OpenStreetMap" +msgstr "OpenStreetMap" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__params +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Params" +msgstr "Parametri" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__params_wms +msgid "Params Wms" +msgstr "Parametri WMS" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__point +msgid "Point" +msgstr "Punto" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__polygon +msgid "Polygon" +msgstr "Poligono" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__dim +msgid "PostGIs Dimension" +msgstr "Dimensione PostGIs" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__geo_type +msgid "PostGIs type" +msgstr "Tipo PostGIs" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__projection +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__projection +msgid "Projection" +msgstr "Proiezione" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__proportion +msgid "Proportional Symbol" +msgstr "Simbolo proporzionale" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__quantile +msgid "Quantile" +msgstr "Quantile" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "Raster (Background layers)" +msgstr "Raster (livello di sfondo)" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_form_view_raster_action +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_rater_action +#: model:ir.model,name:base_geoengine.model_geoengine_raster_layer +msgid "Raster Layer" +msgstr "Livello raster" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_raster_layer_menu +msgid "Raster Layer Management" +msgstr "Gestione livello raster" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_geoengine_raster_layer_type +msgid "Raster Layer Type" +msgstr "Tipo livello raster" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Raster Layer View" +msgstr "Vista livello raster" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__raster_type +msgid "Raster layer type" +msgstr "Tipo livello raster" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__raster_layer_ids +msgid "Raster layers" +msgstr "Livelli raster" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +#, python-format +msgid "Rasters" +msgstr "Raster" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/records_panel/records_panel.xml:0 +#, python-format +msgid "Records (" +msgstr "Record (" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Related Model" +msgstr "Modello correlato" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__view_id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__view_id +msgid "Related View" +msgstr "Viste correlata" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#, python-format +msgid "Remove tag" +msgstr "Rimuovi etichetta" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Representation" +msgstr "Rappresentazione" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__geo_repr +msgid "Representation mode" +msgstr "Modalità di rappresentazione" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Reprojection of column is not implemented. We can not change srid %(srid)s " +"to %(data)s" +msgstr "" +"Riproiezione della colonna nn implementata. Non si può modificare srid " +"%(srid)s a %(data)s" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__request_encoding +msgid "Request encoding" +msgstr "Codifica richiesta" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__resolutions +msgid "Resolutions" +msgstr "Risoluzione" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__restricted_extent +msgid "Restricted map extent" +msgstr "Estensione ristretta della mappa" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.xml:0 +#, python-format +msgid "Save" +msgstr "Salva" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/records_panel/search_bar_records/search_bar_records.xml:0 +#, python-format +msgid "Search..." +msgstr "Cerca..." + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__server_type +msgid "Server Type" +msgstr "Tipo server" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__service +msgid "Service" +msgstr "Servizio" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__url +msgid "Service URL" +msgstr "URL servizio" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_convertion_helper.py:0 +#, python-format +msgid "Shapely or geojson are not available in the sys path" +msgstr "Shapely o geojson non sono disponibili nel path di sistema" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field_input/domain_selector_geo_field_input.esm.js:0 +#, python-format +msgid "Subdomain" +msgstr "Sottodominio" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +#, python-format +msgid "The geo_field_id must be a field in %s model" +msgstr "Il geo_field_id deve essere un campo nel modello %s" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__server_type +msgid "" +"The type of the remote WMS server: mapserver, geoserver, " +"carmentaserver, or qgis" +msgstr "" +"Il tipo sel server WMS remoto: mapserver, geoserver, " +"carmentaserver, o qgis" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__unique +msgid "Unique value" +msgstr "Valore unico" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__units +msgid "Units" +msgstr "Unità" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__use_to_edit +msgid "Use to edit" +msgstr "Usa per modificare" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Vector" +msgstr "Vettore" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "Vector (Active layers)" +msgstr "Vettore (livelli attivi)" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_raster_action +#: model:ir.actions.act_window,name:base_geoengine.geo_vector_geoengine_view_action +#: model:ir.model,name:base_geoengine.model_geoengine_vector_layer +msgid "Vector Layer" +msgstr "Livello vettoriale" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_vector_layer_menu +msgid "Vector Layer Management" +msgstr "Gestione livello vettoriale" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__vector_layer_ids +msgid "Vector layers" +msgstr "Livelli vettoriali" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +#, python-format +msgid "Vectors" +msgstr "Vettori" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_ir_ui_view +msgid "View" +msgstr "Vista" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_view_menu +msgid "View Management" +msgstr "Gestione vista" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__type +msgid "View Type" +msgstr "Tipo vista" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_action +msgid "Views" +msgstr "Viste" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "WMS options" +msgstr "Opzioni WMS" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__wmts +msgid "WMTS" +msgstr "WMTS" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "WMTS options" +msgstr "Opzioni WMTS" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +#, python-format +msgid "Warning" +msgstr "Attenzione" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_convertion_helper.py:0 +#, python-format +msgid "" +"Write/create/search geo type must be wkt/geojson string or must respond to " +"wkt" +msgstr "" +"Il tipo geo scrittura/creazione/ricerca deve essere una stringa wkt/geojson " +"odeve rispondere a wkt" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +#, python-format +msgid "" +"You are about to create a new record without having displayed all the " +"others. A risk of overlap could occur. Would you like to continue ?" +msgstr "" +"Si sta per creare un nuovo record senza aver disabilitato tutti gli altri. " +"C'è il rischio di sovrapposizione. Si vuole continuare?" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "You must at least provide one of domain or geo_domain" +msgstr "Bisogna fornire almeno un dominio o un geo_domain" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +#, python-format +msgid "You need to provide an attribute that exists in %s model" +msgstr "Bisogna fornire un attributo che esista nel modello %s" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +#, python-format +msgid "You need to select a numeric field" +msgstr "Bisogna selezionare un campo numerico" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__projection +msgid "eg. EPSG:21781" +msgstr "es. EPSG:21781" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__request_encoding +msgid "eg. REST" +msgstr "es. REST" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__units +msgid "eg. m" +msgstr "es. m" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__format_suffix +msgid "eg. png" +msgstr "es. png" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_contains" +msgstr "geo_contains" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_equal" +msgstr "geo_equal" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_greater" +msgstr "geo_greater" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_intersect" +msgstr "geo_intersect" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_lesser" +msgstr "geo_lesser" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_line +msgid "geo_line" +msgstr "geo_line" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_line +msgid "geo_multi_line" +msgstr "geo_multi_line" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_point +msgid "geo_multi_point" +msgstr "geo_multi_point" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_polygon +msgid "geo_multi_polygon" +msgstr "geo_multi_polygon" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_point +msgid "geo_point" +msgstr "geo_point" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_polygon +msgid "geo_polygon" +msgstr "geo_polygon" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "geo_search is deprecated: uses search method defined on base model" +msgstr "" +"geo_search è deprecat: usare il motodo ricerca definito nel modello base" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_touch" +msgstr "geo_touch" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_within" +msgstr "geo_within" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"geometry_columns table seems to be corrupted. SRID check is not possible" +msgstr "" +"la tabella geometry_columns sembra corrotta.Il controllo SRID non è possibile" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__begin_color +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__end_color +msgid "hex value" +msgstr "valore esadecimale" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_number_field/domain_selector_number_field.esm.js:0 +#, python-format +msgid "in active_ids" +msgstr "in active_ids" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_number_field/domain_selector_number_field.esm.js:0 +#, python-format +msgid "not in active_ids" +msgstr "not in active_ids" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__srid +msgid "srid" +msgstr "srid" + +#, python-format +#~ msgid "" +#~ "Geo Value %(geom_type)s must be of the same type %(geo_type)s as fields" +#~ msgstr "" +#~ "Il valore geo %(geom_type)s deve essere dello stesso tipo %(geo_type)s " +#~ "come i campi" + +#~ msgid "Last Modified on" +#~ msgstr "Ultima modifica il" + +#, python-format +#~ msgid "No GeoEngine view defined for the model %s" +#~ msgstr "Nessuna vista GeoEngine definita per il modello %s" + +#, python-format +#~ msgid "Please create a view or modify view mode" +#~ msgstr "Creare una vista o modificare la modalità di visualizzazione" + +#~ msgid "" +#~ "The type of the remote WMS server: mapserver, geoserver, carmentaserver, " +#~ "or qgis" +#~ msgstr "" +#~ "Il tipo sel server WMS remoto: mapserver, geoserver, carmentaserver, o " +#~ "qgis" diff --git a/base_geoengine/i18n/sv.po b/base_geoengine/i18n/sv.po new file mode 100644 index 000000000..b02fbf617 --- /dev/null +++ b/base_geoengine/i18n/sv.po @@ -0,0 +1,1038 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_geoengine +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-11-02 13:38+0000\n" +"Last-Translator: jakobkrabbe \n" +"Language-Team: none\n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "%s column does not exists or is not a geo field" +msgstr "%s kolumnen finns inte eller är inte ett geofält" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__active_on_startup +msgid "Active On Startup" +msgstr "Aktiv vid uppstart" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#, python-format +msgid "Add new value" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#, python-format +msgid "Add tag" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__attribute_field_id +msgid "Attribute field" +msgstr "Attributfält" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_base +msgid "Base" +msgstr "Bas" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__basic +msgid "Basic" +msgstr "Grundläggande" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__begin_color +msgid "Begin color class" +msgstr "Börja färgklass" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Classification" +msgstr "Klassificering" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__classification +msgid "Classification mode" +msgstr "Klassificeringsläge" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__type +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__code +msgid "Code" +msgstr "Kod" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__colored +msgid "Colored range/Chroma.js" +msgstr "Färgat område/Chroma.js" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Colors" +msgstr "Färger" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_base_view_menu +msgid "Configuration" +msgstr "Konfiguration" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__gist_index +msgid "Create gist index" +msgstr "Skapa huvudindex" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__create_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__create_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__create_uid +msgid "Created by" +msgstr "Skapad av" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__create_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__create_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__create_date +msgid "Created on" +msgstr "Skapad på" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__custom +msgid "Custom" +msgstr "Anpassad" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__default_extent +msgid "Default map extent" +msgstr "Standard kartomfattning" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__default_zoom +msgid "Default map zoom" +msgstr "Standard kartzoom" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__params +msgid "Dictiorary of values for dimensions as JSON" +msgstr "Ordbok med värden för dimensioner som JSON" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__dimensions +msgid "Dimensions" +msgstr "Dimensioner" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.xml:0 +#, python-format +msgid "Discard" +msgstr "Kassera" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__display_polygon_labels +msgid "Display Labels on Polygon" +msgstr "Visa etiketter på polygon" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__display_name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__display_name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__display_name +msgid "Display Name" +msgstr "Visningsnamn" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__d_wms +msgid "Distant WMS" +msgstr "Avlägsen WMS" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +#, python-format +msgid "Domain editing" +msgstr "Domänredigering" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +#, python-format +msgid "Editing Raster Layer" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +#, python-format +msgid "Editing vector layer" +msgstr "Redigera vektorlager" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__end_color +msgid "End color class" +msgstr "Avsluta färgklass" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_db.py:0 +#, python-format +msgid "" +"Error, can not automatically initialize spatial postgis support. Database " +"user may have to be superuser and postgres/postgis extensions with their " +"devel header have to be installed. If you do not want Odoo to connect with a " +"super user you can manually prepare your database. To do this, open a client " +"to your database using a super user and run:\n" +"CREATE EXTENSION postgis;\n" +"CREATE EXTENSION postgis_topology;\n" +msgstr "" +"Fel, kan inte automatiskt initiera spatial postgis-stöd. Databasanvändare " +"kan behöva vara superanvändare och postgres/postgis-tillägg med deras " +"utvecklingshuvud måste installeras. Om du inte vill att Odoo ska ansluta " +"till en superanvändare kan du manuellt förbereda din databas. För att göra " +"detta, öppna en klient till din databas med en superanvändare och kör:\n" +"CREATE EXTENSION postgis;\n" +"CREATE EXTENSION postgis_topology;\n" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__ttype +msgid "Field Type" +msgstr "Fälttyp" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_ir_model_fields +msgid "Fields" +msgstr "Fält" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__format_suffix +msgid "Format" +msgstr "Format" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "General" +msgstr "Generell" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Geo Value %(geom_type)s must be of the same type " +"%(geo_type)s as fields" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Geo dimention modification is not implemented. We can not change dimention " +"%(data)s to %(dim)s" +msgstr "" +"Modifiering av geografisk dimension är inte implementerad. Vi kan inte ändra " +"dimension %(data)s till %(dim)s" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__geo_field_id +msgid "Geo field" +msgstr "Geofält" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Geo type modification is not implemented. We can not change type %(data)s to " +"%(geo_type)s" +msgstr "" +"Ändring av geotyp är inte implementerad. Vi kan inte ändra typ %(data)s till " +"%(geo_type)s" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_ui_view__type__geoengine +msgid "GeoEngine" +msgstr "GeoMotor" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_base_menu +msgid "GeoEngine Backend" +msgstr "GeoMotor Backend" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "GeoEngine Data" +msgstr "GeoMotor data" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_view.esm.js:0 +#, python-format +msgid "Geoengine" +msgstr "Geomotor" + +#. module: base_geoengine +#: model:res.groups,name:base_geoengine.group_geoengine_admin +msgid "Geoengine Admin" +msgstr "Geomotor Admin" + +#. module: base_geoengine +#: model:res.groups,name:base_geoengine.group_geoengine_user +msgid "Geoengine User" +msgstr "Geomotor användare" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__has_type +msgid "Has Type" +msgstr "Har typ" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__id +msgid "ID" +msgstr "ID" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__interval +msgid "Interval" +msgstr "Intervall" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__is_wms +msgid "Is Wms" +msgstr "Är Wms" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__is_wmts +msgid "Is Wmts" +msgstr "Är Wmts" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__overlay +msgid "Is overlay layer?" +msgstr "Är överläggslager?" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__write_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__write_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__write_uid +msgid "Last Updated by" +msgstr "Senast uppdaterad av" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__write_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__write_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__write_date +msgid "Last Updated on" +msgstr "Senast uppdaterad på" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__type_id +msgid "Layer" +msgstr "Lager" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__name +msgid "Layer Name" +msgstr "Lagernamn" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__layer_opacity +msgid "Layer Opacity" +msgstr "Lageropacitet" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__sequence +msgid "Layer Priority" +msgstr "Lagerprioritet" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__layer_transparent +msgid "Layer Transparent" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Layer data" +msgstr "Lagerdata" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__readonly +msgid "Layer is read only" +msgstr "Layer är skrivskyddad" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__sequence +msgid "Layer priority" +msgstr "Lagerprioritet" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__active_on_startup +msgid "Layer will be shown on startup if checked." +msgstr "Lager kommer att visas vid start om det är markerat." + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +#, python-format +msgid "Layers (" +msgstr "Lager (" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__linestring +msgid "LineString" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__dimensions +msgid "List of dimensions separated by ','" +msgstr "Lista över dimensioner avgränsade med ','" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__matrix_set +msgid "Matrix set" +msgstr "Matris set" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__max_extent +msgid "Max extent" +msgstr "Max omfattning" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_arch_parser.esm.js:0 +#, python-format +msgid "Missing ${INFO_BOX_ATTRIBUTE} template." +msgstr "${INFO_BOX_ATTRIBUTE} mall saknas." + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_name +msgid "Model" +msgstr "Modell" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_domain +msgid "Model Domain" +msgstr "Modelldomän" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_id +msgid "Model to use" +msgstr "Modell att använda" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_view_id +msgid "Model view" +msgstr "Modellvy" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multilinestring +msgid "MultiLineString" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multipoint +msgid "MultiPoint" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multipolygon +msgid "MultiPolygon" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__name +msgid "Name" +msgstr "Namn" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__params_wms +msgid "Need to provide at least a LAYERS param" +msgstr "Behöver tillhandahålla minst en LAGER parameter" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +#, python-format +msgid "New record" +msgstr "Ny post" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "" +"No GeoEngine view defined for the model %s. Please " +"create a view or modify view mode" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "No raster layer for view %s" +msgstr "Inget rasterlager för vyn %s" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__nb_class +msgid "Number of class" +msgstr "Nummer av klass" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_renderer/geoengine_renderer.xml:0 +#, python-format +msgid "OPEN" +msgstr "ÖPPNA" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__odoo +msgid "Odoo field" +msgstr "Odoofält" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Odoo layer data (Not implemented)" +msgstr "Odoo lagerdata (inte implementerad)" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__field_id +msgid "Odoo layer field to use" +msgstr "Odoo lagerfält att använda" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__opacity +msgid "Opacity" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__osm +msgid "OpenStreetMap" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__params +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Params" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__params_wms +msgid "Params Wms" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__point +msgid "Point" +msgstr "Peka" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__polygon +msgid "Polygon" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__dim +msgid "PostGIs Dimension" +msgstr "PostGIs dimension" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__geo_type +msgid "PostGIs type" +msgstr "PostGIs typ" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__projection +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__projection +msgid "Projection" +msgstr "Projektion" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__proportion +msgid "Proportional Symbol" +msgstr "Proportionell symbol" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__quantile +msgid "Quantile" +msgstr "Kvantil" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "Raster (Background layers)" +msgstr "Raster (bakgrundslager)" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_form_view_raster_action +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_rater_action +#: model:ir.model,name:base_geoengine.model_geoengine_raster_layer +msgid "Raster Layer" +msgstr "Raster lager" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_raster_layer_menu +msgid "Raster Layer Management" +msgstr "Rasterlagerhantering" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_geoengine_raster_layer_type +msgid "Raster Layer Type" +msgstr "Rasterlagertyp" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Raster Layer View" +msgstr "Rasterlagervy" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__raster_type +msgid "Raster layer type" +msgstr "Rasterlagertyp" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__raster_layer_ids +msgid "Raster layers" +msgstr "Rasterlager" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +#, python-format +msgid "Rasters" +msgstr "Raster" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/records_panel/records_panel.xml:0 +#, python-format +msgid "Records (" +msgstr "Poster (" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Related Model" +msgstr "Relaterad modell" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__view_id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__view_id +msgid "Related View" +msgstr "Relaterad vy" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#, python-format +msgid "Remove tag" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Representation" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__geo_repr +msgid "Representation mode" +msgstr "Representationsläge" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Reprojection of column is not implemented. We can not change srid %(srid)s " +"to %(data)s" +msgstr "" +"Omprojektering av kolumn är inte implementerad. Vi kan inte ändra srid " +"%(srid)s till %(data)s" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__request_encoding +msgid "Request encoding" +msgstr "Begär kodning" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__resolutions +msgid "Resolutions" +msgstr "Upplösningar" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__restricted_extent +msgid "Restricted map extent" +msgstr "Begränsad kartutsträckning" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.xml:0 +#, python-format +msgid "Save" +msgstr "Spara" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/records_panel/search_bar_records/search_bar_records.xml:0 +#, python-format +msgid "Search..." +msgstr "Sök..." + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__server_type +msgid "Server Type" +msgstr "Servertyp" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__service +msgid "Service" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__url +msgid "Service URL" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_convertion_helper.py:0 +#, python-format +msgid "Shapely or geojson are not available in the sys path" +msgstr "Shapely eller geojson är inte tillgängliga i sys-sökvägen" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field_input/domain_selector_geo_field_input.esm.js:0 +#, python-format +msgid "Subdomain" +msgstr "Subdomän" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +#, python-format +msgid "The geo_field_id must be a field in %s model" +msgstr "Värdet i geo_field_id fältet måste vara i %s modellen" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__server_type +msgid "" +"The type of the remote WMS server: mapserver, geoserver, " +"carmentaserver, or qgis" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__unique +msgid "Unique value" +msgstr "Unikt värde" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__units +msgid "Units" +msgstr "Enheter" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__use_to_edit +msgid "Use to edit" +msgstr "Använd för att redigera" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Vector" +msgstr "Vektor" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "Vector (Active layers)" +msgstr "Vektor (aktivt lager)" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_raster_action +#: model:ir.actions.act_window,name:base_geoengine.geo_vector_geoengine_view_action +#: model:ir.model,name:base_geoengine.model_geoengine_vector_layer +msgid "Vector Layer" +msgstr "Vektor lager" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_vector_layer_menu +msgid "Vector Layer Management" +msgstr "Vektor lagerhantering" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__vector_layer_ids +msgid "Vector layers" +msgstr "Vektor lager" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +#, python-format +msgid "Vectors" +msgstr "Vektorer" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_ir_ui_view +msgid "View" +msgstr "Vy" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_view_menu +msgid "View Management" +msgstr "Visningshanterare" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__type +msgid "View Type" +msgstr "Vytyp" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_action +msgid "Views" +msgstr "Vyer" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "WMS options" +msgstr "WMS alternativ" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__wmts +msgid "WMTS" +msgstr "" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "WMTS options" +msgstr "WMTS alternativ" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +#, python-format +msgid "Warning" +msgstr "Varning" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_convertion_helper.py:0 +#, python-format +msgid "" +"Write/create/search geo type must be wkt/geojson string or must respond to " +"wkt" +msgstr "" +"Skriv/skapa/sök geotyp måste vara wkt/geojson-sträng eller måste svara på wkt" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +#, python-format +msgid "" +"You are about to create a new record without having displayed all the " +"others. A risk of overlap could occur. Would you like to continue ?" +msgstr "" +"Du är på väg att skapa en ny post utan att ha visat alla de andra. Det kan " +"uppstå risk för överlappning. Vill du fortsätta?" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "You must at least provide one of domain or geo_domain" +msgstr "Du måste åtminstone tillhandahålla en av domän eller geo_domän" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +#, python-format +msgid "You need to provide an attribute that exists in %s model" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +#, python-format +msgid "You need to select a numeric field" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__projection +msgid "eg. EPSG:21781" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__request_encoding +msgid "eg. REST" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__units +msgid "eg. m" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__format_suffix +msgid "eg. png" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_contains" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_equal" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_greater" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_intersect" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_lesser" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_line +msgid "geo_line" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_line +msgid "geo_multi_line" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_point +msgid "geo_multi_point" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_polygon +msgid "geo_multi_polygon" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_point +msgid "geo_point" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_polygon +msgid "geo_polygon" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "geo_search is deprecated: uses search method defined on base model" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_touch" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_within" +msgstr "" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"geometry_columns table seems to be corrupted. SRID check is not possible" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__begin_color +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__end_color +msgid "hex value" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_number_field/domain_selector_number_field.esm.js:0 +#, python-format +msgid "in active_ids" +msgstr "" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_number_field/domain_selector_number_field.esm.js:0 +#, python-format +msgid "not in active_ids" +msgstr "" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__srid +msgid "srid" +msgstr "" + +#, python-format +#~ msgid "" +#~ "Geo Value %(geom_type)s must be of the same type %(geo_type)s as fields" +#~ msgstr "" +#~ "Geovärde %(geom_type)s måste vara av samma typ %(geo_type)s som fält" + +#~ msgid "Last Modified on" +#~ msgstr "Senast modifierad på" + +#, python-format +#~ msgid "No GeoEngine view defined for the model %s" +#~ msgstr "Ingen GeoMotor-vy definierad för modellen %s" + +#, python-format +#~ msgid "Please create a view or modify view mode" +#~ msgstr "Vänligen skapa en vy eller ändra visningsläge" + +#~ msgid "" +#~ "The type of the remote WMS server: mapserver, geoserver, carmentaserver, " +#~ "or qgis" +#~ msgstr "" +#~ "Typen av fjärr-WMS-servern: mapserver, geoserver, carmentaserver eller " +#~ "qgis" diff --git a/base_geoengine/i18n/zh_CN.po b/base_geoengine/i18n/zh_CN.po new file mode 100644 index 000000000..faaed618a --- /dev/null +++ b/base_geoengine/i18n/zh_CN.po @@ -0,0 +1,1005 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_geoengine +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-11-25 09:06+0000\n" +"Last-Translator: xtanuiha \n" +"Language-Team: none\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 5.6.2\n" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "%s column does not exists or is not a geo field" +msgstr "%s 列不存在或不是地理字段" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__active_on_startup +msgid "Active On Startup" +msgstr "启动时激活" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#, python-format +msgid "Add new value" +msgstr "添加新值" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#, python-format +msgid "Add tag" +msgstr "添加标签" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__attribute_field_id +msgid "Attribute field" +msgstr "属性字段" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_base +msgid "Base" +msgstr "基础" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__basic +msgid "Basic" +msgstr "基本" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__begin_color +msgid "Begin color class" +msgstr "开始颜色类别" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Classification" +msgstr "分类" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__classification +msgid "Classification mode" +msgstr "分类模式" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__type +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__code +msgid "Code" +msgstr "代码" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__colored +msgid "Colored range/Chroma.js" +msgstr "彩色范围/Chroma.js" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Colors" +msgstr "颜色" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_base_view_menu +msgid "Configuration" +msgstr "配置" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__gist_index +msgid "Create gist index" +msgstr "创建gist索引" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__create_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__create_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__create_uid +msgid "Created by" +msgstr "由...创建" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__create_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__create_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__create_date +msgid "Created on" +msgstr "创建于" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__custom +msgid "Custom" +msgstr "自定义" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__default_extent +msgid "Default map extent" +msgstr "默认地图范围" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__default_zoom +msgid "Default map zoom" +msgstr "默认地图缩放" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__params +msgid "Dictiorary of values for dimensions as JSON" +msgstr "维度值的字典作为JSON" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__dimensions +msgid "Dimensions" +msgstr "维度" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.xml:0 +#, python-format +msgid "Discard" +msgstr "放弃" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__display_polygon_labels +msgid "Display Labels on Polygon" +msgstr "在多边形上显示标签" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__display_name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__display_name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__display_name +msgid "Display Name" +msgstr "显示名称" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__d_wms +msgid "Distant WMS" +msgstr "远程WMS" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +#, python-format +msgid "Domain editing" +msgstr "域编辑" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +#, python-format +msgid "Editing Raster Layer" +msgstr "编辑栅格层" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.esm.js:0 +#, python-format +msgid "Editing vector layer" +msgstr "编辑矢量层" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__end_color +msgid "End color class" +msgstr "结束颜色类别" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_db.py:0 +#, python-format +msgid "" +"Error, can not automatically initialize spatial postgis support. Database user may have to be superuser and postgres/postgis extensions with their devel header have to be installed. If you do not want Odoo to connect with a super user you can manually prepare your database. To do this, open a client to your database using a super user and run:\n" +"CREATE EXTENSION postgis;\n" +"CREATE EXTENSION postgis_topology;\n" +msgstr "" +"错误,无法自动初始化空间postgis支持。数据库用户可能需要是超级用户,并且必须安" +"装postgres/postgis扩展及其开发头文件。如果您不希望Odoo与超级用户连接,您可以" +"手动准备数据库。为此,请使用超级用户打开数据库客户端并运行:\\n" +"CREATE EXTENSION postgis;\\n" +"CREATE EXTENSION postgis_topology;\\n" +"\n" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__ttype +msgid "Field Type" +msgstr "字段类型" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_ir_model_fields +msgid "Fields" +msgstr "字段" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__format_suffix +msgid "Format" +msgstr "格式" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "General" +msgstr "通用" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Geo Value %(geom_type)s must be of the same type %(geo_type)s" +" as fields" +msgstr "地理值%(geom_type)s必须与字段的类型%(geo_type)s相同" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Geo dimention modification is not implemented. We can not change dimention " +"%(data)s to %(dim)s" +msgstr "地理维度修改未实现。我们无法将维度%(data)s更改为%(dim)s" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__geo_field_id +msgid "Geo field" +msgstr "地理字段" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Geo type modification is not implemented. We can not change type %(data)s to" +" %(geo_type)s" +msgstr "地理类型修改未实现。我们无法将类型%(data)s更改为%(geo_type)s" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_ui_view__type__geoengine +msgid "GeoEngine" +msgstr "地理引擎" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_base_menu +msgid "GeoEngine Backend" +msgstr "地理引擎后端" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "GeoEngine Data" +msgstr "地理引擎数据" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_view.esm.js:0 +#, python-format +msgid "Geoengine" +msgstr "地理引擎" + +#. module: base_geoengine +#: model:res.groups,name:base_geoengine.group_geoengine_admin +msgid "Geoengine Admin" +msgstr "地理引擎管理员" + +#. module: base_geoengine +#: model:res.groups,name:base_geoengine.group_geoengine_user +msgid "Geoengine User" +msgstr "地理引擎用户" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__has_type +msgid "Has Type" +msgstr "具有类型" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__id +msgid "ID" +msgstr "ID" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__interval +msgid "Interval" +msgstr "间隔" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__is_wms +msgid "Is Wms" +msgstr "是否为WMS" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__is_wmts +msgid "Is Wmts" +msgstr "是否为WMTS" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__overlay +msgid "Is overlay layer?" +msgstr "是否为叠加层?" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__write_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__write_uid +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__write_uid +msgid "Last Updated by" +msgstr "最后更新者" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__write_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__write_date +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__write_date +msgid "Last Updated on" +msgstr "最后更新时间" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__type_id +msgid "Layer" +msgstr "图层" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__name +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__name +msgid "Layer Name" +msgstr "图层名称" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__layer_opacity +msgid "Layer Opacity" +msgstr "图层不透明度" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__sequence +msgid "Layer Priority" +msgstr "图层优先级" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__layer_transparent +msgid "Layer Transparent" +msgstr "图层透明度" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Layer data" +msgstr "图层数据" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__readonly +msgid "Layer is read only" +msgstr "只读图层" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__sequence +msgid "Layer priority" +msgstr "图层优先级" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__active_on_startup +msgid "Layer will be shown on startup if checked." +msgstr "如果选中,则图层将在启动时显示。" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +#, python-format +msgid "Layers (" +msgstr "图层 (" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__linestring +msgid "LineString" +msgstr "线字符串" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__dimensions +msgid "List of dimensions separated by ','" +msgstr "用逗号分隔的维度列表" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__matrix_set +msgid "Matrix set" +msgstr "矩阵集" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__max_extent +msgid "Max extent" +msgstr "最大范围" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_arch_parser.esm.js:0 +#, python-format +msgid "Missing ${INFO_BOX_ATTRIBUTE} template." +msgstr "缺少 \\${INFO_BOX_ATTRIBUTE} 模板。" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_name +msgid "Model" +msgstr "模型" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_domain +msgid "Model Domain" +msgstr "模型域" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_id +msgid "Model to use" +msgstr "要使用的模型" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__model_view_id +msgid "Model view" +msgstr "模型视图" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multilinestring +msgid "MultiLineString" +msgstr "多线字符串" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multipoint +msgid "MultiPoint" +msgstr "多点" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__multipolygon +msgid "MultiPolygon" +msgstr "多边形" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__name +msgid "Name" +msgstr "名称" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__params_wms +msgid "Need to provide at least a LAYERS param" +msgstr "至少需要提供一个 LAYERS 参数" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +#, python-format +msgid "New record" +msgstr "新记录" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "" +"No GeoEngine view defined for the model %s. Please " +"create a view or modify view mode" +msgstr "模型 %s 没有定义 GeoEngine 视图。请创建视图或修改视图模式" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "No raster layer for view %s" +msgstr "视图 %s 没有栅格图层" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__nb_class +msgid "Number of class" +msgstr "类别数量" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_renderer/geoengine_renderer.xml:0 +#, python-format +msgid "OPEN" +msgstr "打开" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__odoo +msgid "Odoo field" +msgstr "Odoo 字段" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Odoo layer data (Not implemented)" +msgstr "Odoo 层数据(未实现)" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__field_id +msgid "Odoo layer field to use" +msgstr "要使用的 Odoo 层字段" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__opacity +msgid "Opacity" +msgstr "不透明度" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__osm +msgid "OpenStreetMap" +msgstr "开放街图" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__params +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Params" +msgstr "参数" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__params_wms +msgid "Params Wms" +msgstr "Wms 参数" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__point +msgid "Point" +msgstr "点" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__geo_type__polygon +msgid "Polygon" +msgstr "多边形" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__dim +msgid "PostGIs Dimension" +msgstr "PostGIS 维度" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__geo_type +msgid "PostGIs type" +msgstr "PostGIS 类型" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__projection +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__projection +msgid "Projection" +msgstr "投影" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__geo_repr__proportion +msgid "Proportional Symbol" +msgstr "比例符号" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__quantile +msgid "Quantile" +msgstr "分位数" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "Raster (Background layers)" +msgstr "栅格(背景图层)" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_form_view_raster_action +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_rater_action +#: model:ir.model,name:base_geoengine.model_geoengine_raster_layer +msgid "Raster Layer" +msgstr "栅格图层" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_raster_layer_menu +msgid "Raster Layer Management" +msgstr "栅格图层管理" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_geoengine_raster_layer_type +msgid "Raster Layer Type" +msgstr "栅格图层类型" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "Raster Layer View" +msgstr "栅格图层视图" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__raster_type +msgid "Raster layer type" +msgstr "栅格图层类型" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__raster_layer_ids +msgid "Raster layers" +msgstr "栅格图层" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +#, python-format +msgid "Rasters" +msgstr "栅格数据" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/records_panel/records_panel.xml:0 +#, python-format +msgid "Records (" +msgstr "记录 (" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Related Model" +msgstr "相关模型" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__view_id +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__view_id +msgid "Related View" +msgstr "相关视图" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_field_input_with_tags/domain_selector_field_input_with_tags.xml:0 +#, python-format +msgid "Remove tag" +msgstr "移除标签" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_geoengine_view_form +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Representation" +msgstr "表示" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_vector_layer__geo_repr +msgid "Representation mode" +msgstr "表示模式" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"Reprojection of column is not implemented. We can not change srid %(srid)s " +"to %(data)s" +msgstr "列的重投影未实现。我们不能将srid %(srid)s更改为%(data)s" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__request_encoding +msgid "Request encoding" +msgstr "请求编码" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__resolutions +msgid "Resolutions" +msgstr "分辨率" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__restricted_extent +msgid "Restricted map extent" +msgstr "限制地图范围" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.xml:0 +#, python-format +msgid "Save" +msgstr "保存" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/records_panel/search_bar_records/search_bar_records.xml:0 +#: code:addons/base_geoengine/static/src/js/views/geoengine/records_panel/search_bar_records/search_bar_records.xml:0 +#: code:addons/base_geoengine/static/src/js/views/geoengine/records_panel/search_bar_records/search_bar_records.xml:0 +#, python-format +msgid "Search..." +msgstr "搜索..." + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__server_type +msgid "Server Type" +msgstr "服务器类型" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer_type__service +msgid "Service" +msgstr "服务" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__url +msgid "Service URL" +msgstr "服务URL" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_convertion_helper.py:0 +#, python-format +msgid "Shapely or geojson are not available in the sys path" +msgstr "sys路径中不可用Shapely或geojson" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field_input/domain_selector_geo_field_input.esm.js:0 +#, python-format +msgid "Subdomain" +msgstr "子域名" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +#, python-format +msgid "The geo_field_id must be a field in %s model" +msgstr "geo_field_id 必须是 %s 模型中的一个字段" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__server_type +msgid "" +"The type of the remote WMS server: mapserver, geoserver, " +"carmentaserver, or qgis" +msgstr "远程 WMS 服务器的类型:mapserver、geoserver、carmentaserver 或 qgis" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_vector_layer__classification__unique +msgid "Unique value" +msgstr "唯一值" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__units +msgid "Units" +msgstr "单位" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_geoengine_raster_layer__use_to_edit +msgid "Use to edit" +msgstr "用于编辑" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_vector_view_form +msgid "Vector" +msgstr "矢量" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geoengine_view_form +msgid "Vector (Active layers)" +msgstr "矢量(活动图层)" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_raster_action +#: model:ir.actions.act_window,name:base_geoengine.geo_vector_geoengine_view_action +#: model:ir.model,name:base_geoengine.model_geoengine_vector_layer +msgid "Vector Layer" +msgstr "矢量图层" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_vector_layer_menu +msgid "Vector Layer Management" +msgstr "矢量图层管理" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__vector_layer_ids +msgid "Vector layers" +msgstr "矢量图层" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/layers_panel/layers_panel.xml:0 +#, python-format +msgid "Vectors" +msgstr "矢量数据" + +#. module: base_geoengine +#: model:ir.model,name:base_geoengine.model_ir_ui_view +msgid "View" +msgstr "视图" + +#. module: base_geoengine +#: model:ir.ui.menu,name:base_geoengine.geoengine_view_menu +msgid "View Management" +msgstr "视图管理" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_ui_view__type +msgid "View Type" +msgstr "视图类型" + +#. module: base_geoengine +#: model:ir.actions.act_window,name:base_geoengine.geo_engine_view_action +msgid "Views" +msgstr "视图" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "WMS options" +msgstr "WMS 选项" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__geoengine_raster_layer__raster_type__wmts +msgid "WMTS" +msgstr "WMTS" + +#. module: base_geoengine +#: model_terms:ir.ui.view,arch_db:base_geoengine.geo_raster_view_form +msgid "WMTS options" +msgstr "WMTS 选项" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +#, python-format +msgid "Warning" +msgstr "警告" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/geo_convertion_helper.py:0 +#, python-format +msgid "" +"Write/create/search geo type must be wkt/geojson string or must respond to " +"wkt" +msgstr "写入/创建/搜索地理类型必须是 wkt/geojson 字符串或必须响应 wkt" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/views/geoengine/geoengine_controller/geoengine_controller.esm.js:0 +#, python-format +msgid "" +"You are about to create a new record without having displayed all the " +"others. A risk of overlap could occur. Would you like to continue ?" +msgstr "您即将创建一条新记录,而没有显示所有其他记录。可能会发生重叠的风险。您想要继" +"续吗?" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "You must at least provide one of domain or geo_domain" +msgstr "您至少需要提供一个域名或地理域名" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +#, python-format +msgid "You need to provide an attribute that exists in %s model" +msgstr "您需要提供一个存在于 %s 模型中的属性" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/geo_vector_layer.py:0 +#, python-format +msgid "You need to select a numeric field" +msgstr "您需要选择一个数值字段" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__projection +msgid "eg. EPSG:21781" +msgstr "例如 EPSG:21781" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__request_encoding +msgid "eg. REST" +msgstr "例如 REST" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__units +msgid "eg. m" +msgstr "例如 m" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_raster_layer__format_suffix +msgid "eg. png" +msgstr "例如 png" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_contains" +msgstr "地理包含" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_equal" +msgstr "地理相等" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_greater" +msgstr "地理大于" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_intersect" +msgstr "地理相交" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_lesser" +msgstr "地理小于" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_line +msgid "geo_line" +msgstr "地理线" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_line +msgid "geo_multi_line" +msgstr "地理多线" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_point +msgid "geo_multi_point" +msgstr "地理多点" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_multi_polygon +msgid "geo_multi_polygon" +msgstr "地理多边形" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_point +msgid "geo_point" +msgstr "地理点" + +#. module: base_geoengine +#: model:ir.model.fields.selection,name:base_geoengine.selection__ir_model_fields__ttype__geo_polygon +msgid "geo_polygon" +msgstr "地理多边形" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/models/base.py:0 +#, python-format +msgid "geo_search is deprecated: uses search method defined on base model" +msgstr "geo_search 已弃用:使用在基础模型上定义的搜索方法" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_touch" +msgstr "地理接触" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_geo_field/domain_selector_geo_field.esm.js:0 +#, python-format +msgid "geo_within" +msgstr "地理包含" + +#. module: base_geoengine +#. odoo-python +#: code:addons/base_geoengine/fields.py:0 +#, python-format +msgid "" +"geometry_columns table seems to be corrupted. SRID check is not possible" +msgstr "geometry_columns 表似乎已损坏。无法进行 SRID 检查" + +#. module: base_geoengine +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__begin_color +#: model:ir.model.fields,help:base_geoengine.field_geoengine_vector_layer__end_color +msgid "hex value" +msgstr "十六进制值" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_number_field/domain_selector_number_field.esm.js:0 +#, python-format +msgid "in active_ids" +msgstr "在 active_ids 中" + +#. module: base_geoengine +#. odoo-javascript +#: code:addons/base_geoengine/static/src/js/widgets/domain_selector_geo_field/domain_selector_number_field/domain_selector_number_field.esm.js:0 +#, python-format +msgid "not in active_ids" +msgstr "不在 active_ids 中" + +#. module: base_geoengine +#: model:ir.model.fields,field_description:base_geoengine.field_ir_model_fields__srid +msgid "srid" +msgstr "空间参考系统标识符" diff --git a/base_geoengine/images/map-hover.png b/base_geoengine/images/map-hover.png new file mode 100644 index 000000000..14799049f Binary files /dev/null and b/base_geoengine/images/map-hover.png differ diff --git a/base_geoengine/images/map.png b/base_geoengine/images/map.png new file mode 100644 index 000000000..17214344b Binary files /dev/null and b/base_geoengine/images/map.png differ diff --git a/base_geoengine/models/__init__.py b/base_geoengine/models/__init__.py new file mode 100644 index 000000000..9a2710cae --- /dev/null +++ b/base_geoengine/models/__init__.py @@ -0,0 +1,8 @@ +# Copyright 2011-2012 Nicolas Bessi (Camptocamp SA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import base +from . import geo_raster_layer +from . import geo_vector_layer +from . import ir_view +from . import ir_model diff --git a/base_geoengine/models/base.py b/base_geoengine/models/base.py new file mode 100644 index 000000000..f233be145 --- /dev/null +++ b/base_geoengine/models/base.py @@ -0,0 +1,201 @@ +# Copyright 2011-2012 Nicolas Bessi (Camptocamp SA) +# Copyright 2016 Yannick Payot (Camptocamp SA) +# Copyright 2023 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +import logging + +from odoo import api, models +from odoo.exceptions import MissingError, UserError +from odoo.fields import Domain + +from .. import fields as geo_fields + +DEFAULT_EXTENT = "-123164.85222423, 5574694.9538936, 1578017.6490538, 6186191.1800898" + +_logger = logging.getLogger(__name__) + + +class Base(models.AbstractModel): + """Extend Base class for to allow definition of geo fields.""" + + _inherit = "base" + + # Array of ash that define layer and data to use + _georepr = [] + + @api.model + def fields_get(self, allfields=None, attributes=None): + """Add geo_type definition for geo fields""" + res = super().fields_get(allfields=allfields, attributes=attributes) + for f_name in res: + field = self._fields.get(f_name) + if field and field.type.startswith("geo_"): + geo_type = { + "type": field.type, + "dim": int(field.dim), + "srid": field.srid, + "geo_type": field.geo_type, + } + # TODO + if field.compute or field.related: + if not field.dim: + geo_type["dim"] = 2 + if not field.srid: + geo_type["srid"] = 3857 + res[f_name]["geo_type"] = geo_type + return res + + @api.model + def _get_geo_view(self): + IrView = self.env["ir.ui.view"] + geo_view = IrView.sudo().search( + [("model", "=", self._name), ("type", "=", "geoengine")], + limit=1, + ) + if not geo_view: + message = self.env._( + "No GeoEngine view defined for the model %s. \ + Please create a view or modify view mode" + ) + raise UserError( + message % self._name, + ) + return geo_view + + @api.model + def set_field_real_name(self, in_tuple): + field_obj = self.env["ir.model.fields"] + if not in_tuple: + return in_tuple + field_id = None + display_name = None + + # Odoo may serialize many2one values as: + # - [id, display_name] + # - {"id": id, "display_name": "..."} (newer formats) + # - id + if isinstance(in_tuple, (list, tuple)): + if in_tuple: + field_id = in_tuple[0] + if len(in_tuple) > 1: + display_name = in_tuple[1] + elif isinstance(in_tuple, dict): + field_id = in_tuple.get("id") + display_name = in_tuple.get("display_name") or in_tuple.get("name") + elif isinstance(in_tuple, int): + field_id = in_tuple + + if not field_id: + return in_tuple + + field = field_obj.browse(field_id).exists() + technical_name = field.name if field else False + if display_name is None: + display_name = technical_name + + return (field_id, technical_name, display_name) + + @api.model + def get_geoengine_layers(self, view_id=None, view_type="geoengine", **options): + view_obj = self.env["ir.ui.view"] + + if not view_id: + view = self._get_geo_view() + else: + view = view_obj.browse(view_id) + geoengine_layers = { + "backgrounds": [], + "actives": [], + "projection": view.projection, + "restricted_extent": view.restricted_extent, + "default_extent": view.default_extent or DEFAULT_EXTENT, + "default_zoom": view.default_zoom, + } + + for layer in view.raster_layer_ids: + layer_dict = layer.read()[0] + geoengine_layers["backgrounds"].append(layer_dict) + for layer in view.vector_layer_ids: + layer_dict = layer.read()[0] + layer_dict["attribute_field_id"] = self.set_field_real_name( + layer_dict.get("attribute_field_id", False) + ) + layer_dict["geo_field_id"] = self.set_field_real_name( + layer_dict.get("geo_field_id", False) + ) + layer_dict["resModel"] = layer._name + layer_dict["model"] = layer.model_id.model + layer_dict["model_domain"] = layer.model_domain + geoengine_layers["actives"].append(layer_dict) + return geoengine_layers + + @api.model + def get_edit_info_for_geo_column(self, column): + raster_obj = self.env["geoengine.raster.layer"] + + field = self._fields.get(column) + if not field or not isinstance(field, geo_fields.GeoField): + message = self.env._("%s column does not exists or is not a geo field") + raise ValueError(message % column) + view = self._get_geo_view() + raster = raster_obj.search( + [("view_id", "=", view.id), ("use_to_edit", "=", True)], limit=1 + ) + if not raster: + raster = raster_obj.search([("view_id", "=", view.id)], limit=1) + if not raster: + message = self.env._("No raster layer for view %s") + raise MissingError(message % (view.name,)) + return { + "edit_raster": raster.read()[0], + "srid": field.srid, + "projection": view.projection, + "restricted_extent": view.restricted_extent, + "default_extent": view.default_extent or DEFAULT_EXTENT, + "default_zoom": view.default_zoom, + } + + @api.model + def geo_search( + self, domain=None, geo_domain=None, offset=0, limit=None, order=None + ): + """Perform a geo search it allows direct domain: + geo_search( + domain=[('name', 'ilike', 'toto']), + geo_domain=[('the_point', 'geo_intersect', + myshaply_obj or mywkt or mygeojson)]) + + We can also support indirect geo_domain ( + ‘geom’, ‘geo_operator’, {‘res.zip.poly’: [‘id’, ‘in’, [1,2,3]] }) + + The supported operators are : + * geo_greater + * geo_lesser + * geo_equal + * geo_touch + * geo_within + * geo_contains + * geo_intersect""" + # First we do a standard search in order to apply security rules + # and do a search on standard attributes + # Limit and offset are managed after, we may loose a lot of performance + # here + _logger.debug( + self.env._( + "geo_search is deprecated: uses search method defined on base model" + ) + ) + domain = domain or [] + geo_domain = geo_domain or [] + search_domain = domain or [] + if domain and geo_domain: + search_domain = Domain.AND([domain, geo_domain]) + elif geo_domain: + search_domain = geo_domain + + if not search_domain: + raise ValueError( + self.env._("You must at least provide one of domain or geo_domain") + ) + + return self.search(search_domain, limit=limit, offset=offset, order=order) diff --git a/base_geoengine/models/geo_raster_layer.py b/base_geoengine/models/geo_raster_layer.py new file mode 100644 index 000000000..c7d98662e --- /dev/null +++ b/base_geoengine/models/geo_raster_layer.py @@ -0,0 +1,90 @@ +# Copyright 2011-2012 Nicolas Bessi (Camptocamp SA) +# Copyright 2016 Yannick Payot (Camptocamp SA) +# Copyright 2023 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import api, fields, models + + +class GeoRasterLayerType(models.Model): + _name = "geoengine.raster.layer.type" + _description = "Raster Layer Type" + + name = fields.Char(translate=True, required=True) + code = fields.Char(required=True) + service = fields.Char(required=True) + + +class GeoRasterLayer(models.Model): + _name = "geoengine.raster.layer" + _description = "Raster Layer" + _order = "sequence ASC, name" + + raster_type = fields.Selection( + [ + ("osm", "OpenStreetMap"), + ("wmts", "WMTS"), + ("d_wms", "Distant WMS"), + ("odoo", "Odoo field"), + ], + string="Raster layer type", + default="osm", + required=True, + ) + name = fields.Char("Layer Name", translate=True, required=True) + url = fields.Char("Service URL") + + # technical field to display or not wmts options + is_wmts = fields.Boolean(compute="_compute_is_wmts") + # technical field to display or not wms options + is_wms = fields.Boolean(compute="_compute_is_wms") + # wmts options + matrix_set = fields.Char("Matrix set") + format_suffix = fields.Char("Format", help="eg. png") + request_encoding = fields.Char("Request encoding", help="eg. REST") + projection = fields.Char(help="eg. EPSG:21781") + units = fields.Char(help="eg. m") # Not used + resolutions = fields.Char() + max_extent = fields.Char("Max extent") + dimensions = fields.Char(help="List of dimensions separated by ','") + params = fields.Char(help="Dictiorary of values for dimensions as JSON") + + # wms options + params_wms = fields.Char(help="Need to provide at least a LAYERS param") + server_type = fields.Char( + help="The type of the remote WMS server: mapserver, \ + geoserver, carmentaserver, or qgis", + ) + + # technical field to display or not layer type -- Not used + has_type = fields.Boolean(compute="_compute_has_type") + type_id = fields.Many2one( + "geoengine.raster.layer.type", "Layer", domain="[('service', '=', raster_type)]" + ) + type = fields.Char(related="type_id.code") + sequence = fields.Integer("Layer priority", default=6) + overlay = fields.Boolean("Is overlay layer?") + field_id = fields.Many2one( + "ir.model.fields", + "Odoo layer field to use", + domain=[("ttype", "ilike", "geo_"), ("model", "=", "view_id.model")], + ) + view_id = fields.Many2one( + "ir.ui.view", "Related View", domain=[("type", "=", "geoengine")], required=True + ) + use_to_edit = fields.Boolean("Use to edit") + opacity = fields.Float(default=1.0) + + @api.depends("raster_type", "is_wmts") + def _compute_has_type(self): + for rec in self: + rec.has_type = rec.raster_type == "is_wmts" + + @api.depends("raster_type") + def _compute_is_wmts(self): + for rec in self: + rec.is_wmts = rec.raster_type == "wmts" + + @api.depends("raster_type") + def _compute_is_wms(self): + for rec in self: + rec.is_wms = rec.raster_type == "d_wms" diff --git a/base_geoengine/models/geo_vector_layer.py b/base_geoengine/models/geo_vector_layer.py new file mode 100644 index 000000000..0fc80c378 --- /dev/null +++ b/base_geoengine/models/geo_vector_layer.py @@ -0,0 +1,157 @@ +# Copyright 2011-2012 Nicolas Bessi (Camptocamp SA) +# Copyright 2016 Yannick Payot (Camptocamp SA) +# Copyright 2023 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models +from odoo.exceptions import ValidationError + +SUPPORTED_ATT = [ + "float", + "integer", + "integer_big", + "related", + "function", + "date", + "datetime", + "char", + "text", + "selection", +] + +NUMBER_ATT = ["float", "integer", "integer_big"] + + +class GeoVectorLayer(models.Model): + _name = "geoengine.vector.layer" + _description = "Vector Layer" + _order = "sequence ASC, name" + + geo_repr = fields.Selection( + [ + ("basic", "Basic"), + # Actually we have to think if we should separate it for colored + ("proportion", "Proportional Symbol"), + ("colored", "Colored range/Chroma.js"), + ], + string="Representation mode", + required=True, + ) + + classification = fields.Selection( + [ + ("unique", "Unique value"), + ("interval", "Interval"), + ("quantile", "Quantile"), + ("custom", "Custom"), + ], + string="Classification mode", + required=False, + ) + name = fields.Char("Layer Name", translate=True, required=True) + begin_color = fields.Char("Begin color class", required=False, help="hex value") + end_color = fields.Char( + "End color class", required=False, help="hex value", default="#FF680A" + ) + nb_class = fields.Integer("Number of class", default=1) + geo_field_id = fields.Many2one( + "ir.model.fields", + "Geo field", + required=True, + ondelete="cascade", + domain=[("ttype", "ilike", "geo_")], + ) + attribute_field_id = fields.Many2one( + "ir.model.fields", "Attribute field", domain=[("ttype", "in", SUPPORTED_ATT)] + ) + model_id = fields.Many2one( + "ir.model", + "Model to use", + store=True, + readonly=False, + compute="_compute_model_id", + ) + model_name = fields.Char(related="model_id.model", readonly=True) + + view_id = fields.Many2one( + "ir.ui.view", "Related View", domain=[("type", "=", "geoengine")], required=True + ) + sequence = fields.Integer("Layer Priority", default=6) + readonly = fields.Boolean("Layer is read only") + display_polygon_labels = fields.Boolean("Display Labels on Polygon") + active_on_startup = fields.Boolean( + help="Layer will be shown on startup if checked." + ) + layer_opacity = fields.Float(default=1.0) + model_domain = fields.Char(default="[]") + model_view_id = fields.Many2one( + "ir.ui.view", + "Model view", + domain=[("type", "=", "geoengine")], + compute="_compute_model_view_id", + readonly=False, + ) + layer_transparent = fields.Boolean() + + @api.constrains("geo_field_id", "model_id") + def _check_geo_field_id(self): + for rec in self: + if rec.model_id: + if not rec.geo_field_id.model_id == rec.model_id: + raise ValidationError( + self.env._( + "The geo_field_id must be a field in %s model", + rec.model_id.display_name, + ) + ) + + @api.constrains("geo_repr", "attribute_field_id") + def _check_geo_repr(self): + for rec in self: + if ( + rec.attribute_field_id + and rec.attribute_field_id.ttype not in NUMBER_ATT + ): + if ( + rec.geo_repr == "colored" + and rec.classification != "unique" + or rec.geo_repr == "proportion" + ): + raise ValidationError( + self.env._( + "You need to select a numeric field", + ) + ) + + @api.constrains("attribute_field_id", "geo_field_id") + def _check_if_attribute_in_geo_field(self): + for rec in self: + if rec.attribute_field_id and rec.geo_field_id: + if rec.attribute_field_id.model != rec.geo_field_id.model: + raise ValidationError( + self.env._( + "You need to provide an attribute that exists in %s model", + rec.geo_field_id.model_id.display_name, + ) + ) + + @api.depends("model_id") + def _compute_model_view_id(self): + for rec in self: + if rec.model_id: + for view in rec.model_id.view_ids: + if view.type == "geoengine": + rec.model_view_id = view + else: + rec.model_view_id = "" + + @api.depends("geo_field_id", "view_id") + def _compute_model_id(self): + for rec in self: + if rec.view_id and rec.geo_field_id: + if rec.view_id.model != rec.geo_field_id.model: + rec.model_id = rec.geo_field_id.model_id + else: + rec.model_id = "" + else: + rec.model_id = "" diff --git a/base_geoengine/models/ir_model.py b/base_geoengine/models/ir_model.py new file mode 100644 index 000000000..ba3f44218 --- /dev/null +++ b/base_geoengine/models/ir_model.py @@ -0,0 +1,51 @@ +# Copyright 2011-2012 Nicolas Bessi (Camptocamp SA) +# Copyright 2023 Yannick Payot (Camptocamp SA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import fields, models + +from odoo.addons import base + +if "geoengine" not in base.models.ir_actions.VIEW_TYPES: + base.models.ir_actions.VIEW_TYPES.append(("geoengine", "Geoengine")) + +GEO_TYPES = [ + ("geo_polygon", "geo_polygon"), + ("geo_multi_polygon", "geo_multi_polygon"), + ("geo_point", "geo_point"), + ("geo_multi_point", "geo_multi_point"), + ("geo_line", "geo_line"), + ("geo_multi_line", "geo_multi_line"), +] + +GEO_TYPES_ONDELETE = { + "geo_polygon": "cascade", + "geo_multi_polygon": "cascade", + "geo_point": "cascade", + "geo_multi_point": "cascade", + "geo_line": "cascade", + "geo_multi_line": "cascade", +} + +POSTGIS_GEO_TYPES = [ + ("Point", "Point"), + ("MultiPoint", "MultiPoint"), + ("LineString", "LineString"), + ("MultiLineString", "MultiLineString"), + ("Polygon", "Polygon"), + ("MultiPolygon", "MultiPolygon"), +] + + +class IrModelField(models.Model): + _inherit = "ir.model.fields" + + srid = fields.Integer("srid", required=False) + geo_type = fields.Selection(POSTGIS_GEO_TYPES, string="PostGIs type") + dim = fields.Selection( + [("2", "2"), ("3", "3"), ("4", "4")], string="PostGIs Dimension", default="2" + ) + gist_index = fields.Boolean("Create gist index") + ttype = fields.Selection( + selection_add=GEO_TYPES, + ondelete=GEO_TYPES_ONDELETE, + ) diff --git a/base_geoengine/models/ir_view.py b/base_geoengine/models/ir_view.py new file mode 100644 index 000000000..aaec60ac7 --- /dev/null +++ b/base_geoengine/models/ir_view.py @@ -0,0 +1,39 @@ +# Copyright 2011-2012 Nicolas Bessi (Camptocamp SA) +# Copyright 2016-2023 Yannick Payot (Camptocamp SA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import fields, models + + +class IrUIView(models.Model): + _inherit = "ir.ui.view" + + type = fields.Selection( + selection_add=[("geoengine", "GeoEngine")], + ondelete={"geoengine": "cascade"}, + ) + + raster_layer_ids = fields.One2many( + "geoengine.raster.layer", "view_id", "Raster layers", required=False + ) + + vector_layer_ids = fields.One2many( + "geoengine.vector.layer", "view_id", "Vector layers", required=True + ) + + projection = fields.Char(default="EPSG:3857", required=True) + default_extent = fields.Char( + "Default map extent", + default="-123164.85222423, 5574694.9538936, 1578017.6490538, 6186191.1800898", + ) + default_zoom = fields.Integer("Default map zoom") + restricted_extent = fields.Char("Restricted map extent") + + def _is_qweb_based_view(self, view_type): + if view_type == "geoengine": + return True + return super()._is_qweb_based_view(view_type) + + def _get_view_info(self): + res = super()._get_view_info() + res.update({"geoengine": {"icon": "fa fa-globe"}}) + return res diff --git a/base_geoengine/pyproject.toml b/base_geoengine/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/base_geoengine/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/base_geoengine/readme/CONTRIBUTORS.md b/base_geoengine/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..4097346e9 --- /dev/null +++ b/base_geoengine/readme/CONTRIBUTORS.md @@ -0,0 +1,25 @@ +- Nicolas Bessi \<\> +- Frederic Junod \<\> +- Yannick Payot \<\> +- Sandy Carter \<\> +- Laurent Mignon \<\> +- Jonathan Nemry \<\> +- David Lasley \<\> +- Daniel Reis \<\> +- Matthieu Dietrich \<\> +- Alan Ramos \<\> +- Damien Crier \<\> +- Cyril Gaudin \<\> +- Pierre Verkest \<\> +- Benjamin Willig \<\> +- Devendra Kavthekar \<\> +- Emanuel Cino \<\> +- Thomas Nowicki \<\> +- Alexandre Saunier \<\> +- Sandip Mangukiya \<\> +- Samuel Kouff \<\> +- [APSL-Nagarro](https://www.apsl.tech): + - Antoni Marroig \<\> + - Miquel Alzanillas \<\> +- Red Butay +- Sergio Sancho \<\> diff --git a/base_geoengine/readme/DESCRIPTION.md b/base_geoengine/readme/DESCRIPTION.md new file mode 100644 index 000000000..3ce3383e2 --- /dev/null +++ b/base_geoengine/readme/DESCRIPTION.md @@ -0,0 +1,16 @@ +GeoEngine is an Odoo module that adds spatial/GIS capabilites to Odoo. +It will allow you to : + +- Visualize and query your business information on map +- Perform GeoBI and spatial query +- Configure your spatial layers and spatial datasources +- Extend Odoo models with spatial columns + +GeoEngine relies on [OpenLayers](http://openlayers.org) and +[PostGIS](http://postgis.refractions.net/) technologies. + +Postgis is used to store spatial information in databases. OpenLayer is +used to represent spatial data in other words to show maps and the +different spatial layers. The GeoEngine module acts as a data provider +and as an OpenLayers configurator. It also provides a complete extension +to Odoo ORM. diff --git a/base_geoengine/readme/HISTORY.md b/base_geoengine/readme/HISTORY.md new file mode 100644 index 000000000..eb2ccddc3 --- /dev/null +++ b/base_geoengine/readme/HISTORY.md @@ -0,0 +1,131 @@ +## 19.0.1.0.1 + +- Migration to Odoo 19.0. +- Migrated JavaScript frontend to OWL/ESM architecture. +- Updated OpenLayers to version 10.5.0. +- Updated Chroma.js to version 3.1.2. +- Refactored domain handling for Odoo 19 ORM compatibility. + +## 16.0.1.0.0 (2023-03-20) + +- LayerSwitcher has been removed as it was not really practical. A + LayerPanel is now active. +- The geo_search method is now deprecated and replaced by the standard + odoo search method. +- The widget "geo_edit_map" attribute is no longer necessary as the + field is automatically detected by his type. We can also provide an + option attribute that allows us to pass an opacity and a color as + parameters. + +``` xml +
+ + + + + +
+``` + +- The method geo_search is now deprecated. We now need to use the + standard odoo search method. + +``` python +obj.search([("the_point","geo_intersect",{"dummy.zip.the_geom": [("id", "=", rec.id)]})]) +``` + +- We can now pass to the geoengine view a template to display the + information we want to see when clicking on a feature. + +``` xml + + + + + + + + +
    +
  • ZIP : +
  • +
  • Total Sales: +
  • +
+
+
+
+``` + +- We can now pass a model to use to a layer to display other information + on the map. + +``` xml + + + [('state', '=', 'hs')] + + HS retail machines + + basic + + #FF0000 + + 0.8 + +``` + +- There is some new features in the LayerPanel. + +1. If you are logged in as an admin, you have the possibility to edit + the layer by clicking on the edit button. This will open a dialog + box. Changes will appear in real time on the view. +2. If you are logged in as an admin, you can also change the domain of + the layer. If you are logged in as a user, changes will not be + persisted in the database. Changes will appear in real time on the + view. +3. If you are logged in as an admin, you can also change the sequence + of the layers by sliding them over each other. If you are logged in + as a user, changes will not be persisted in the database. + +- Widget domain is now implemented for geo field This means that the + geo-operators are also implemented and that there is the possibility + to add a sub-domain. If we want to add a domain that includes all the + records that are displayed in the geoengine view (active_ids). We can + use the two new operators : "in active_ids" and "not in active_ids". + These will automatically replace the marker with ids. Note that the + widget will indicate that the domain is invalid because of the marker. +- Creation of the RecordsPanel. This panel allows you to retrieve all + active records. You can click on record to get the movement to the + selected record. Two magnifying glass are also available. You can + click on the left one to zoom on the record. You can click on the + right one to get the original zoom. +- A search bar is also available. It allows you to perform a search into + the RecordsPanel. +- A button to open/close the panels is also available. +- The module has been translated in French. +- Now you can now make the geoengine view editable. Simply add editable + attribute in the geoengine view. + +``` xml + + + + + + + + + +
    +
  • ZIP : +
  • +
  • Total Sales: +
  • +
+
+
+
+ +Thanks to that, you can create new records by drawing them directly in the geoengine view. You can also edit record in the same view. +``` diff --git a/base_geoengine/readme/INSTALL.md b/base_geoengine/readme/INSTALL.md new file mode 100644 index 000000000..63db9ddc6 --- /dev/null +++ b/base_geoengine/readme/INSTALL.md @@ -0,0 +1,18 @@ +To install this module, you need to have [PostGIS](http://postgis.net/) +installed. + +On Ubuntu: + +```bash +sudo apt-get install postgis +``` + +The module also requires two additional python libs: + +- [Shapely](http://pypi.python.org/pypi/Shapely) +- [geojson](http://pypi.python.org/pypi/geojson) + +These two additional libs will be installed automatically with the module. + +For a complete documentation please refer to the [public +documentation](http://oca.github.io/geospatial/index.html) diff --git a/base_geoengine/readme/ROADMAP.md b/base_geoengine/readme/ROADMAP.md new file mode 100644 index 000000000..e69de29bb diff --git a/base_geoengine/readme/USAGE.md b/base_geoengine/readme/USAGE.md new file mode 100644 index 000000000..6ddda6d33 --- /dev/null +++ b/base_geoengine/readme/USAGE.md @@ -0,0 +1,80 @@ +## Geoengine Demo + +1. As a user/admin, when I am in the Geoengine Demo module and I go to + the ZIP menu. When I click on an item in the list view, I get to the + form view showing me the different information about the ZIP. We can + see its ZIP, city, priority, total sales and his spatial + representation. +2. As a user, I can't modify the information in the form view. +3. As an admin, I can modify the information in the form view. I can + click on the bin button to clear the map and I can draw a new shape. +4. As a user, when I go the "Retail machines" tab and there are no + items to display, it does not show me anything. +5. As an admin, when I go the "Retail machines" tab and there are no + items to display, the list view of the retail machines suggests to + me to add a new line. +6. As a user/admin, if there are items to be displayed in the "Retail + machines" tab then I can click on an item and the retail machines + form view will be displayed. We can see its spatial representation + by going to "The point" tab and its attributes in "Attributes" tab. +7. As a user/admin, when I go to the geoengine zip view by clicking on + the map button at the top right of the screen. The geoengine view + appears with the first 80 results displayed on the map. The vector + layers selected are those defined as "active on startup" by the + admin. The selected raster layer is the first one that is not an + overlay layer. +8. As a user/admin, when I hover over an area on the map, the area + changes its style. +9. As a user/admin, when I click on an area, a popup appears an I can + see the different information about the area. If I click on the + cross, the popup will disappear. If I click somewhere else on the + map, the popup will also disappear. If I click on the about button, + then the form view will be displayed. +10. As a user/admin, when I use the paging system, then the results + displayed on the map are different (corresponding to the request). +11. As a user/admin, if we use the search bar, we can search results by + his zip or his city. +12. As an admin, if I change the sequence of layers with the handle + button then the change are persisted in database. +13. As a user, if I change the sequence of layers with the handle button + then the change are not persisted in database. There are just the + changes in the display. +14. As an admin, if I change the domain of a layer with the filter + button then the change are persisted in database. +15. As a user, if I change the domain of a layer with the filter button + then the change are not persisted in database. There are just the + changes in the display. +16. As an admin, I have the possibility to edit the layer with its + corresponding button. +17. As a user/admin, I can open/close LayerPanel with its button. +18. As a user/admin, I can open/close RecordsPanel with its button. +19. As a user/admin, when I click on a record in RecordsPanel, a move is + made on the map to the selected record. +20. As a user/admin, when I click on a record in RecordsPanel, I can + also click on the left magnifying glass to zoom on the record. +21. As a user/admin, when I click on a record in RecordsPanel, I can + also click on the right magnifying glass to get the original zoom. +22. As a user/admin, I can use the search bar to search in the + RecordsPanel. +23. As an admin,If the geoengine view is in edit mode, I can create new + records by drawing them in the view. +24. As an admin, If the geoengine view is in edit mode, I can modify its + spatial representation. + +## Geoengine Backend + +1. As an admin, if I go into the configuration of the raster layers and + it has elements, I can click on one and see its information. +2. As an admin, if I want to create a new raster layer, I can click on + "NEW" and fill out the form. The required fields for OpenStreetMap + type are "Layer Name" and "Related View". If we want to have a WMTS + (Web Map Tile Service) raster type. The required fields in addition + to the precedents are "Service URL", "Matrix set","Format", + "Projection" and "Resolutions". If we take WMS (Web Map Service) + raster type, then the required fields are "Layer Name", "Related + View", "Service URL", "Params", "Server Type". +3. As an admin,if I go into the configuration of the vector layers and + it has elements, I can click on one and see its information. +4. As an admin, if I want to create a new vector layer, I can click on + "NEW" and fill out the form. The required fields are "Layer Name", + "Related View", "Geo field" and "Representation mode". diff --git a/base_geoengine/security/data.xml b/base_geoengine/security/data.xml new file mode 100644 index 000000000..f14235ee3 --- /dev/null +++ b/base_geoengine/security/data.xml @@ -0,0 +1,20 @@ + + + + Geoengine User + + + + Geoengine Admin + + + + + + + + + + + + diff --git a/base_geoengine/security/ir.model.access.csv b/base_geoengine/security/ir.model.access.csv new file mode 100644 index 000000000..44559f50e --- /dev/null +++ b/base_geoengine/security/ir.model.access.csv @@ -0,0 +1,9 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_geo_user_vector_user,geoengine.user.vector.layer,base_geoengine.model_geoengine_vector_layer,base_geoengine.group_geoengine_user,1,0,0,0 +access_geo_admin_vector_user,geoengine.admin.vector.layer,base_geoengine.model_geoengine_vector_layer,base_geoengine.group_geoengine_admin,1,1,1,1 +access_geo_user_raster_user,geoengine.user.raster.layer,base_geoengine.model_geoengine_raster_layer,base_geoengine.group_geoengine_user,1,0,0,0 +access_geo_admin_raster_user,geoengine.admin.raster.layer,base_geoengine.model_geoengine_raster_layer,base_geoengine.group_geoengine_admin,1,1,1,1 +access_geo_user_raster_type_user,geoengine.user.raster.layer.type,base_geoengine.model_geoengine_raster_layer_type,base_geoengine.group_geoengine_user,1,0,0,0 +access_geo_admin_raster_type_user,geoengine.admin.raster.layer.type,base_geoengine.model_geoengine_raster_layer_type,base_geoengine.group_geoengine_admin,1,1,1,1 +access_geo_user_allmodels,ir.model,base.model_ir_model,base_geoengine.group_geoengine_user,1,0,0,0 +access_geo_user_allviews,ir.ui.view,base.model_ir_ui_view,base_geoengine.group_geoengine_user,1,0,0,0 diff --git a/base_geoengine/static/description/icon.png b/base_geoengine/static/description/icon.png new file mode 100644 index 000000000..b698310ee Binary files /dev/null and b/base_geoengine/static/description/icon.png differ diff --git a/base_geoengine/static/description/index.html b/base_geoengine/static/description/index.html new file mode 100644 index 000000000..fa2c9f9ca --- /dev/null +++ b/base_geoengine/static/description/index.html @@ -0,0 +1,731 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Geospatial support for Odoo

+ +

Beta License: AGPL-3 OCA/geospatial Translate me on Weblate Try me on Runboat

+

GeoEngine is an Odoo module that adds spatial/GIS capabilites to Odoo. +It will allow you to :

+
    +
  • Visualize and query your business information on map
  • +
  • Perform GeoBI and spatial query
  • +
  • Configure your spatial layers and spatial datasources
  • +
  • Extend Odoo models with spatial columns
  • +
+

GeoEngine relies on OpenLayers and +PostGIS technologies.

+

Postgis is used to store spatial information in databases. OpenLayer is +used to represent spatial data in other words to show maps and the +different spatial layers. The GeoEngine module acts as a data provider +and as an OpenLayers configurator. It also provides a complete extension +to Odoo ORM.

+

Table of contents

+ +
+

Installation

+

To install this module, you need to have +PostGIS installed.

+

On Ubuntu:

+
+sudo apt-get install postgis
+
+

The module also requires two additional python libs:

+ +

These two additional libs will be installed automatically with the +module.

+

For a complete documentation please refer to the public +documentation

+
+
+

Usage

+
+

Geoengine Demo

+
    +
  1. As a user/admin, when I am in the Geoengine Demo module and I go to +the ZIP menu. When I click on an item in the list view, I get to the +form view showing me the different information about the ZIP. We can +see its ZIP, city, priority, total sales and his spatial +representation.
  2. +
  3. As a user, I can’t modify the information in the form view.
  4. +
  5. As an admin, I can modify the information in the form view. I can +click on the bin button to clear the map and I can draw a new shape.
  6. +
  7. As a user, when I go the “Retail machines” tab and there are no +items to display, it does not show me anything.
  8. +
  9. As an admin, when I go the “Retail machines” tab and there are no +items to display, the list view of the retail machines suggests to +me to add a new line.
  10. +
  11. As a user/admin, if there are items to be displayed in the “Retail +machines” tab then I can click on an item and the retail machines +form view will be displayed. We can see its spatial representation +by going to “The point” tab and its attributes in “Attributes” tab.
  12. +
  13. As a user/admin, when I go to the geoengine zip view by clicking on +the map button at the top right of the screen. The geoengine view +appears with the first 80 results displayed on the map. The vector +layers selected are those defined as “active on startup” by the +admin. The selected raster layer is the first one that is not an +overlay layer.
  14. +
  15. As a user/admin, when I hover over an area on the map, the area +changes its style.
  16. +
  17. As a user/admin, when I click on an area, a popup appears an I can +see the different information about the area. If I click on the +cross, the popup will disappear. If I click somewhere else on the +map, the popup will also disappear. If I click on the about button, +then the form view will be displayed.
  18. +
  19. As a user/admin, when I use the paging system, then the results +displayed on the map are different (corresponding to the request).
  20. +
  21. As a user/admin, if we use the search bar, we can search results by +his zip or his city.
  22. +
  23. As an admin, if I change the sequence of layers with the handle +button then the change are persisted in database.
  24. +
  25. As a user, if I change the sequence of layers with the handle button +then the change are not persisted in database. There are just the +changes in the display.
  26. +
  27. As an admin, if I change the domain of a layer with the filter +button then the change are persisted in database.
  28. +
  29. As a user, if I change the domain of a layer with the filter button +then the change are not persisted in database. There are just the +changes in the display.
  30. +
  31. As an admin, I have the possibility to edit the layer with its +corresponding button.
  32. +
  33. As a user/admin, I can open/close LayerPanel with its button.
  34. +
  35. As a user/admin, I can open/close RecordsPanel with its button.
  36. +
  37. As a user/admin, when I click on a record in RecordsPanel, a move is +made on the map to the selected record.
  38. +
  39. As a user/admin, when I click on a record in RecordsPanel, I can +also click on the left magnifying glass to zoom on the record.
  40. +
  41. As a user/admin, when I click on a record in RecordsPanel, I can +also click on the right magnifying glass to get the original zoom.
  42. +
  43. As a user/admin, I can use the search bar to search in the +RecordsPanel.
  44. +
  45. As an admin,If the geoengine view is in edit mode, I can create new +records by drawing them in the view.
  46. +
  47. As an admin, If the geoengine view is in edit mode, I can modify its +spatial representation.
  48. +
+
+
+

Geoengine Backend

+
    +
  1. As an admin, if I go into the configuration of the raster layers and +it has elements, I can click on one and see its information.
  2. +
  3. As an admin, if I want to create a new raster layer, I can click on +“NEW” and fill out the form. The required fields for OpenStreetMap +type are “Layer Name” and “Related View”. If we want to have a WMTS +(Web Map Tile Service) raster type. The required fields in addition +to the precedents are “Service URL”, “Matrix set”,”Format”, +“Projection” and “Resolutions”. If we take WMS (Web Map Service) +raster type, then the required fields are “Layer Name”, “Related +View”, “Service URL”, “Params”, “Server Type”.
  4. +
  5. As an admin,if I go into the configuration of the vector layers and +it has elements, I can click on one and see its information.
  6. +
  7. As an admin, if I want to create a new vector layer, I can click on +“NEW” and fill out the form. The required fields are “Layer Name”, +“Related View”, “Geo field” and “Representation mode”.
  8. +
+
+
+ +
+

Changelog

+
+

19.0.1.0.1

+
    +
  • Migration to Odoo 19.0.
  • +
  • Migrated JavaScript frontend to OWL/ESM architecture.
  • +
  • Updated OpenLayers to version 10.5.0.
  • +
  • Updated Chroma.js to version 3.1.2.
  • +
  • Refactored domain handling for Odoo 19 ORM compatibility.
  • +
+
+
+

16.0.1.0.0 (2023-03-20)

+
    +
  • LayerSwitcher has been removed as it was not really practical. A +LayerPanel is now active.
  • +
  • The geo_search method is now deprecated and replaced by the standard +odoo search method.
  • +
  • The widget “geo_edit_map” attribute is no longer necessary as the +field is automatically detected by his type. We can also provide an +option attribute that allows us to pass an opacity and a color as +parameters.
  • +
+
+<form>
+    <notebook colspan="4">
+        <page string="Geometry">
+            <field name="the_geom" options="{'opacity': 0.8, 'color': '#0000FF' }" />
+        </page>
+    </notebook>
+</form>
+
+
    +
  • The method geo_search is now deprecated. We now need to use the +standard odoo search method.
  • +
+
+obj.search([("the_point","geo_intersect",{"dummy.zip.the_geom": [("id", "=", rec.id)]})])
+
+
    +
  • We can now pass to the geoengine view a template to display the +information we want to see when clicking on a feature.
  • +
+
+<geoengine>
+    <field name="name" />
+    <field name="city" />
+    <field name="total_sales" />
+    <field name="the_geom" />
+    <templates>
+        <t t-name="info_box">
+            <field name="city" widget="badge" />
+            <ul>
+                <li>ZIP : <field name="name" />
+                </li>
+                <li>Total Sales: <field name="total_sales" />
+                </li>
+            </ul>
+        </t>
+    </templates>
+</geoengine>
+
+
    +
  • We can now pass a model to use to a layer to display other information +on the map.
  • +
+
+<record id="geoengine_vector_layer_hs_retail_machines" model="geoengine.vector.layer">
+    <field name="model_id" ref="base_geoengine_demo.model_geoengine_demo_automatic_retailing_machine"/>
+    <field name="model_domain">[('state', '=', 'hs')]</field>
+    <field name="geo_field_id" ref="base_geoengine_demo.field_geoengine_demo_automatic_retailing_machine__the_point"/>
+    <field name="name">HS retail machines</field>
+    <field name="view_id" ref="ir_ui_view_resbetterzipgeoview0" />
+    <field name="geo_repr">basic</field>
+    <field name="attribute_field_id" ref="base_geoengine_demo.field_geoengine_demo_automatic_retailing_machine__name"/>
+    <field name="begin_color">#FF0000</field>
+    <field name="display_polygon_labels" eval="0" />
+    <field name="layer_opacity">0.8</field>
+</record>
+
+
    +
  • There is some new features in the LayerPanel.
  • +
+
    +
  1. If you are logged in as an admin, you have the possibility to edit +the layer by clicking on the edit button. This will open a dialog +box. Changes will appear in real time on the view.
  2. +
  3. If you are logged in as an admin, you can also change the domain of +the layer. If you are logged in as a user, changes will not be +persisted in the database. Changes will appear in real time on the +view.
  4. +
  5. If you are logged in as an admin, you can also change the sequence of +the layers by sliding them over each other. If you are logged in as a +user, changes will not be persisted in the database.
  6. +
+
    +
  • Widget domain is now implemented for geo field This means that the +geo-operators are also implemented and that there is the possibility +to add a sub-domain. If we want to add a domain that includes all the +records that are displayed in the geoengine view (active_ids). We can +use the two new operators : “in active_ids” and “not in active_ids”. +These will automatically replace the marker with ids. Note that the +widget will indicate that the domain is invalid because of the marker.
  • +
  • Creation of the RecordsPanel. This panel allows you to retrieve all +active records. You can click on record to get the movement to the +selected record. Two magnifying glass are also available. You can +click on the left one to zoom on the record. You can click on the +right one to get the original zoom.
  • +
  • A search bar is also available. It allows you to perform a search into +the RecordsPanel.
  • +
  • A button to open/close the panels is also available.
  • +
  • The module has been translated in French.
  • +
  • Now you can now make the geoengine view editable. Simply add editable +attribute in the geoengine view.
  • +
+
+<geoengine editable="1">
+    <field name="name" />
+    <field name="city" />
+    <field name="total_sales" />
+    <field name="the_geom" />
+    <field name="display_name" />
+    <templates>
+      <t t-name="info_box">
+        <field name="city" widget="badge" />
+        <ul>
+          <li>ZIP : <field name="name" />
+          </li>
+          <li>Total Sales: <field name="total_sales" />
+          </li>
+        </ul>
+      </t>
+    </templates>
+  </geoengine>
+
+Thanks to that, you can create new records by drawing them directly in the geoengine view. You can also edit record in the same view.
+
+
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Camptocamp
  • +
  • ACSONE SA/NV
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/geospatial project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+
+ + diff --git a/base_geoengine/static/img/map-marker.png b/base_geoengine/static/img/map-marker.png new file mode 100644 index 000000000..096893583 Binary files /dev/null and b/base_geoengine/static/img/map-marker.png differ diff --git a/base_geoengine/static/lib/chromajs-3.2.0/LICENSE b/base_geoengine/static/lib/chromajs-3.2.0/LICENSE new file mode 100644 index 000000000..7c5937167 --- /dev/null +++ b/base_geoengine/static/lib/chromajs-3.2.0/LICENSE @@ -0,0 +1,28 @@ +chroma.js - JavaScript library for color conversions + +Copyright (c) 2011-2015, Gregor Aisch +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. The name Gregor Aisch may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL GREGOR AISCH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/base_geoengine/static/lib/chromajs-3.2.0/chroma.js b/base_geoengine/static/lib/chromajs-3.2.0/chroma.js new file mode 100644 index 000000000..21c2e1d10 --- /dev/null +++ b/base_geoengine/static/lib/chromajs-3.2.0/chroma.js @@ -0,0 +1,4029 @@ +/** + * chroma.js - JavaScript library for color conversions + * + * Copyright (c) 2011-2025, Gregor Aisch + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name Gregor Aisch may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL GREGOR AISCH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ------------------------------------------------------- + * + * chroma.js includes colors from colorbrewer2.org, which are released under + * the following license: + * + * Copyright (c) 2002 Cynthia Brewer, Mark Harrower, + * and The Pennsylvania State University. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + * ------------------------------------------------------ + * + * Named colors are taken from X11 Color Names. + * http://www.w3.org/TR/css3-color/#svg-color + * + * @preserve + */ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.chroma = factory()); +})(this, (function () { 'use strict'; + + var min$4 = Math.min; + var max$4 = Math.max; + + function limit (x, low, high) { + if ( low === void 0 ) low = 0; + if ( high === void 0 ) high = 1; + + return min$4(max$4(low, x), high); + } + + function clip_rgb (rgb) { + rgb._clipped = false; + rgb._unclipped = rgb.slice(0); + for (var i = 0; i <= 3; i++) { + if (i < 3) { + if (rgb[i] < 0 || rgb[i] > 255) { rgb._clipped = true; } + rgb[i] = limit(rgb[i], 0, 255); + } else if (i === 3) { + rgb[i] = limit(rgb[i], 0, 1); + } + } + return rgb; + } + + // ported from jQuery's $.type + var classToType = {}; + for (var i = 0, list = [ + 'Boolean', + 'Number', + 'String', + 'Function', + 'Array', + 'Date', + 'RegExp', + 'Undefined', + 'Null' + ]; i < list.length; i += 1) { + var name = list[i]; + + classToType[("[object " + name + "]")] = name.toLowerCase(); + } + function type (obj) { + return classToType[Object.prototype.toString.call(obj)] || 'object'; + } + + function unpack (args, keyOrder) { + if ( keyOrder === void 0 ) keyOrder = null; + + // if called with more than 3 arguments, we return the arguments + if (args.length >= 3) { return Array.prototype.slice.call(args); } + // with less than 3 args we check if first arg is object + // and use the keyOrder string to extract and sort properties + if (type(args[0]) == 'object' && keyOrder) { + return keyOrder + .split('') + .filter(function (k) { return args[0][k] !== undefined; }) + .map(function (k) { return args[0][k]; }); + } + // otherwise we just return the first argument + // (which we suppose is an array of args) + return args[0].slice(0); + } + + function last (args) { + if (args.length < 2) { return null; } + var l = args.length - 1; + if (type(args[l]) == 'string') { return args[l].toLowerCase(); } + return null; + } + + var PI$2 = Math.PI; + var min$3 = Math.min; + var max$3 = Math.max; + + var rnd2 = function (a) { return Math.round(a * 100) / 100; }; + var rnd3 = function (a) { return Math.round(a * 100) / 100; }; + + var TWOPI = PI$2 * 2; + var PITHIRD = PI$2 / 3; + var DEG2RAD = PI$2 / 180; + var RAD2DEG = 180 / PI$2; + + /** + * Reverse the first three elements of an array + * + * @param {any[]} arr + * @returns {any[]} + */ + function reverse3(arr) { + return arr.slice(0, 3).reverse().concat( arr.slice(3)); + } + + var input = { + format: {}, + autodetect: [] + }; + + var Color = function Color() { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var me = this; + if ( + type(args[0]) === 'object' && + args[0].constructor && + args[0].constructor === this.constructor + ) { + // the argument is already a Color instance + return args[0]; + } + // last argument could be the mode + var mode = last(args); + var autodetect = false; + if (!mode) { + autodetect = true; + + if (!input.sorted) { + input.autodetect = input.autodetect.sort(function (a, b) { return b.p - a.p; }); + input.sorted = true; + } + + // auto-detect format + for (var i = 0, list = input.autodetect; i < list.length; i += 1) { + var chk = list[i]; + + mode = chk.test.apply(chk, args); + if (mode) { break; } + } + } + if (input.format[mode]) { + var rgb = input.format[mode].apply( + null, + autodetect ? args : args.slice(0, -1) + ); + me._rgb = clip_rgb(rgb); + } else { + throw new Error('unknown format: ' + args); + } + // add alpha channel + if (me._rgb.length === 3) { me._rgb.push(1); } + }; + Color.prototype.toString = function toString () { + if (type(this.hex) == 'function') { return this.hex(); } + return ("[" + (this._rgb.join(',')) + "]"); + }; + + // this gets updated automatically + var version = '3.2.0'; + + var chroma = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args) )); + }; + + chroma.version = version; + + var cmyk2rgb = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, 'cmyk'); + var c = args[0]; + var m = args[1]; + var y = args[2]; + var k = args[3]; + var alpha = args.length > 4 ? args[4] : 1; + if (k === 1) { return [0, 0, 0, alpha]; } + return [ + c >= 1 ? 0 : 255 * (1 - c) * (1 - k), // r + m >= 1 ? 0 : 255 * (1 - m) * (1 - k), // g + y >= 1 ? 0 : 255 * (1 - y) * (1 - k), // b + alpha + ]; + }; + + var max$2 = Math.max; + + var rgb2cmyk = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var ref = unpack(args, 'rgb'); + var r = ref[0]; + var g = ref[1]; + var b = ref[2]; + r = r / 255; + g = g / 255; + b = b / 255; + var k = 1 - max$2(r, max$2(g, b)); + var f = k < 1 ? 1 / (1 - k) : 0; + var c = (1 - r - k) * f; + var m = (1 - g - k) * f; + var y = (1 - b - k) * f; + return [c, m, y, k]; + }; + + Color.prototype.cmyk = function () { + return rgb2cmyk(this._rgb); + }; + + var cmyk = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args, ['cmyk']) )); + }; + Object.assign(chroma, { cmyk: cmyk }); + + input.format.cmyk = cmyk2rgb; + + input.autodetect.push({ + p: 2, + test: function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, 'cmyk'); + if (type(args) === 'array' && args.length === 4) { + return 'cmyk'; + } + } + }); + + /* + * supported arguments: + * - hsl2css(h,s,l) + * - hsl2css(h,s,l,a) + * - hsl2css([h,s,l], mode) + * - hsl2css([h,s,l,a], mode) + * - hsl2css({h,s,l,a}, mode) + */ + var hsl2css = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var hsla = unpack(args, 'hsla'); + var mode = last(args) || 'lsa'; + hsla[0] = rnd2(hsla[0] || 0) + 'deg'; + hsla[1] = rnd2(hsla[1] * 100) + '%'; + hsla[2] = rnd2(hsla[2] * 100) + '%'; + if (mode === 'hsla' || (hsla.length > 3 && hsla[3] < 1)) { + hsla[3] = '/ ' + (hsla.length > 3 ? hsla[3] : 1); + mode = 'hsla'; + } else { + hsla.length = 3; + } + return ((mode.substr(0, 3)) + "(" + (hsla.join(' ')) + ")"); + }; + + /* + * supported arguments: + * - rgb2hsl(r,g,b) + * - rgb2hsl(r,g,b,a) + * - rgb2hsl([r,g,b]) + * - rgb2hsl([r,g,b,a]) + * - rgb2hsl({r,g,b,a}) + */ + var rgb2hsl$1 = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, 'rgba'); + var r = args[0]; + var g = args[1]; + var b = args[2]; + + r /= 255; + g /= 255; + b /= 255; + + var minRgb = min$3(r, g, b); + var maxRgb = max$3(r, g, b); + + var l = (maxRgb + minRgb) / 2; + var s, h; + + if (maxRgb === minRgb) { + s = 0; + h = Number.NaN; + } else { + s = + l < 0.5 + ? (maxRgb - minRgb) / (maxRgb + minRgb) + : (maxRgb - minRgb) / (2 - maxRgb - minRgb); + } + + if (r == maxRgb) { h = (g - b) / (maxRgb - minRgb); } + else if (g == maxRgb) { h = 2 + (b - r) / (maxRgb - minRgb); } + else if (b == maxRgb) { h = 4 + (r - g) / (maxRgb - minRgb); } + + h *= 60; + if (h < 0) { h += 360; } + if (args.length > 3 && args[3] !== undefined) { return [h, s, l, args[3]]; } + return [h, s, l]; + }; + + /* + * supported arguments: + * - lab2css(l,a,b) + * - lab2css(l,a,b,alpha) + * - lab2css([l,a,b], mode) + * - lab2css([l,a,b,alpha], mode) + */ + var lab2css = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var laba = unpack(args, 'lab'); + var mode = last(args) || 'lab'; + laba[0] = rnd2(laba[0]) + '%'; + laba[1] = rnd2(laba[1]); + laba[2] = rnd2(laba[2]); + if (mode === 'laba' || (laba.length > 3 && laba[3] < 1)) { + laba[3] = '/ ' + (laba.length > 3 ? laba[3] : 1); + } else { + laba.length = 3; + } + return ("lab(" + (laba.join(' ')) + ")"); + }; + + var labConstants = { + // Corresponds roughly to RGB brighter/darker + Kn: 18, + + // D65 standard referent + labWhitePoint: 'd65', + Xn: 0.95047, + Yn: 1, + Zn: 1.08883, + + kE: 216.0 / 24389.0, + kKE: 8.0, + kK: 24389.0 / 27.0, + + RefWhiteRGB: { + // sRGB + X: 0.95047, + Y: 1, + Z: 1.08883 + }, + + MtxRGB2XYZ: { + m00: 0.4124564390896922, + m01: 0.21267285140562253, + m02: 0.0193338955823293, + m10: 0.357576077643909, + m11: 0.715152155287818, + m12: 0.11919202588130297, + m20: 0.18043748326639894, + m21: 0.07217499330655958, + m22: 0.9503040785363679 + }, + + MtxXYZ2RGB: { + m00: 3.2404541621141045, + m01: -0.9692660305051868, + m02: 0.055643430959114726, + m10: -1.5371385127977166, + m11: 1.8760108454466942, + m12: -0.2040259135167538, + m20: -0.498531409556016, + m21: 0.041556017530349834, + m22: 1.0572251882231791 + }, + + // used in rgb2xyz + As: 0.9414285350000001, + Bs: 1.040417467, + Cs: 1.089532651, + + MtxAdaptMa: { + m00: 0.8951, + m01: -0.7502, + m02: 0.0389, + m10: 0.2664, + m11: 1.7135, + m12: -0.0685, + m20: -0.1614, + m21: 0.0367, + m22: 1.0296 + }, + + MtxAdaptMaI: { + m00: 0.9869929054667123, + m01: 0.43230526972339456, + m02: -0.008528664575177328, + m10: -0.14705425642099013, + m11: 0.5183602715367776, + m12: 0.04004282165408487, + m20: 0.15996265166373125, + m21: 0.0492912282128556, + m22: 0.9684866957875502 + } + }; + + // taken from https://de.mathworks.com/help/images/ref/whitepoint.html + var ILLUMINANTS = new Map([ + // ASTM E308-01 + ['a', [1.0985, 0.35585]], + // Wyszecki & Stiles, p. 769 + ['b', [1.0985, 0.35585]], + // C ASTM E308-01 + ['c', [0.98074, 1.18232]], + // D50 (ASTM E308-01) + ['d50', [0.96422, 0.82521]], + // D55 (ASTM E308-01) + ['d55', [0.95682, 0.92149]], + // D65 (ASTM E308-01) + ['d65', [0.95047, 1.08883]], + // E (ASTM E308-01) + ['e', [1, 1, 1]], + // F2 (ASTM E308-01) + ['f2', [0.99186, 0.67393]], + // F7 (ASTM E308-01) + ['f7', [0.95041, 1.08747]], + // F11 (ASTM E308-01) + ['f11', [1.00962, 0.6435]], + ['icc', [0.96422, 0.82521]] + ]); + + function setLabWhitePoint(name) { + var ill = ILLUMINANTS.get(String(name).toLowerCase()); + if (!ill) { + throw new Error('unknown Lab illuminant ' + name); + } + labConstants.labWhitePoint = name; + labConstants.Xn = ill[0]; + labConstants.Zn = ill[1]; + } + + function getLabWhitePoint() { + return labConstants.labWhitePoint; + } + + var rgb2lab = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var ref = unpack(args, 'rgb'); + var r = ref[0]; + var g = ref[1]; + var b = ref[2]; + var rest = ref.slice(3); + var ref$1 = rgb2xyz(r, g, b); + var x = ref$1[0]; + var y = ref$1[1]; + var z = ref$1[2]; + var ref$2 = xyz2lab(x, y, z); + var L = ref$2[0]; + var a = ref$2[1]; + var b_ = ref$2[2]; + return [L, a, b_ ].concat( (rest.length > 0 && rest[0] < 1 ? [rest[0]] : [])); + }; + + function xyz2lab(x, y, z) { + var Xn = labConstants.Xn; + var Yn = labConstants.Yn; + var Zn = labConstants.Zn; + var kE = labConstants.kE; + var kK = labConstants.kK; + var xr = x / Xn; + var yr = y / Yn; + var zr = z / Zn; + + var fx = xr > kE ? Math.pow(xr, 1.0 / 3.0) : (kK * xr + 16.0) / 116.0; + var fy = yr > kE ? Math.pow(yr, 1.0 / 3.0) : (kK * yr + 16.0) / 116.0; + var fz = zr > kE ? Math.pow(zr, 1.0 / 3.0) : (kK * zr + 16.0) / 116.0; + + return [116.0 * fy - 16.0, 500.0 * (fx - fy), 200.0 * (fy - fz)]; + } + + function gammaAdjustSRGB(companded) { + var sign = Math.sign(companded); + companded = Math.abs(companded); + var linear = + companded <= 0.04045 + ? companded / 12.92 + : Math.pow((companded + 0.055) / 1.055, 2.4); + return linear * sign; + } + + var rgb2xyz = function (r, g, b) { + // normalize and gamma adjust + r = gammaAdjustSRGB(r / 255); + g = gammaAdjustSRGB(g / 255); + b = gammaAdjustSRGB(b / 255); + + var MtxRGB2XYZ = labConstants.MtxRGB2XYZ; + var MtxAdaptMa = labConstants.MtxAdaptMa; + var MtxAdaptMaI = labConstants.MtxAdaptMaI; + var Xn = labConstants.Xn; + var Yn = labConstants.Yn; + var Zn = labConstants.Zn; + var As = labConstants.As; + var Bs = labConstants.Bs; + var Cs = labConstants.Cs; + + var x = r * MtxRGB2XYZ.m00 + g * MtxRGB2XYZ.m10 + b * MtxRGB2XYZ.m20; + var y = r * MtxRGB2XYZ.m01 + g * MtxRGB2XYZ.m11 + b * MtxRGB2XYZ.m21; + var z = r * MtxRGB2XYZ.m02 + g * MtxRGB2XYZ.m12 + b * MtxRGB2XYZ.m22; + + var Ad = Xn * MtxAdaptMa.m00 + Yn * MtxAdaptMa.m10 + Zn * MtxAdaptMa.m20; + var Bd = Xn * MtxAdaptMa.m01 + Yn * MtxAdaptMa.m11 + Zn * MtxAdaptMa.m21; + var Cd = Xn * MtxAdaptMa.m02 + Yn * MtxAdaptMa.m12 + Zn * MtxAdaptMa.m22; + + var X = x * MtxAdaptMa.m00 + y * MtxAdaptMa.m10 + z * MtxAdaptMa.m20; + var Y = x * MtxAdaptMa.m01 + y * MtxAdaptMa.m11 + z * MtxAdaptMa.m21; + var Z = x * MtxAdaptMa.m02 + y * MtxAdaptMa.m12 + z * MtxAdaptMa.m22; + + X *= Ad / As; + Y *= Bd / Bs; + Z *= Cd / Cs; + + x = X * MtxAdaptMaI.m00 + Y * MtxAdaptMaI.m10 + Z * MtxAdaptMaI.m20; + y = X * MtxAdaptMaI.m01 + Y * MtxAdaptMaI.m11 + Z * MtxAdaptMaI.m21; + z = X * MtxAdaptMaI.m02 + Y * MtxAdaptMaI.m12 + Z * MtxAdaptMaI.m22; + + return [x, y, z]; + }; + + /* + * supported arguments: + * - lab2css(l,a,b) + * - lab2css(l,a,b,alpha) + * - lab2css([l,a,b], mode) + * - lab2css([l,a,b,alpha], mode) + */ + var lch2css = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var lcha = unpack(args, 'lch'); + var mode = last(args) || 'lab'; + lcha[0] = rnd2(lcha[0]) + '%'; + lcha[1] = rnd2(lcha[1]); + lcha[2] = isNaN(lcha[2]) ? 'none' : rnd2(lcha[2]) + 'deg'; // add deg unit to hue + if (mode === 'lcha' || (lcha.length > 3 && lcha[3] < 1)) { + lcha[3] = '/ ' + (lcha.length > 3 ? lcha[3] : 1); + } else { + lcha.length = 3; + } + return ("lch(" + (lcha.join(' ')) + ")"); + }; + + var sqrt$4 = Math.sqrt; + var atan2$2 = Math.atan2; + var round$5 = Math.round; + + var lab2lch = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var ref = unpack(args, 'lab'); + var l = ref[0]; + var a = ref[1]; + var b = ref[2]; + var c = sqrt$4(a * a + b * b); + var h = (atan2$2(b, a) * RAD2DEG + 360) % 360; + if (round$5(c * 10000) === 0) { h = Number.NaN; } + return [l, c, h]; + }; + + var rgb2lch = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var ref = unpack(args, 'rgb'); + var r = ref[0]; + var g = ref[1]; + var b = ref[2]; + var rest = ref.slice(3); + var ref$1 = rgb2lab(r, g, b); + var l = ref$1[0]; + var a = ref$1[1]; + var b_ = ref$1[2]; + var ref$2 = lab2lch(l, a, b_); + var L = ref$2[0]; + var c = ref$2[1]; + var h = ref$2[2]; + return [L, c, h ].concat( (rest.length > 0 && rest[0] < 1 ? [rest[0]] : [])); + }; + + // from https://www.w3.org/TR/css-color-4/multiply-matrices.js + function multiplyMatrices(A, B) { + var m = A.length; + + if (!Array.isArray(A[0])) { + // A is vector, convert to [[a, b, c, ...]] + A = [A]; + } + + if (!Array.isArray(B[0])) { + // B is vector, convert to [[a], [b], [c], ...]] + B = B.map(function (x) { return [x]; }); + } + + var p = B[0].length; + var B_cols = B[0].map(function (_, i) { return B.map(function (x) { return x[i]; }); }); // transpose B + var product = A.map(function (row) { return B_cols.map(function (col) { + if (!Array.isArray(row)) { + return col.reduce(function (a, c) { return a + c * row; }, 0); + } + + return row.reduce(function (a, c, i) { return a + c * (col[i] || 0); }, 0); + }); } + ); + + if (m === 1) { + product = product[0]; // Avoid [[a, b, c, ...]] + } + + if (p === 1) { + return product.map(function (x) { return x[0]; }); // Avoid [[a], [b], [c], ...]] + } + + return product; + } + + var rgb2oklab = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var ref = unpack(args, 'rgb'); + var r = ref[0]; + var g = ref[1]; + var b = ref[2]; + var rest = ref.slice(3); + var xyz = rgb2xyz(r, g, b); + var oklab = XYZ_to_OKLab(xyz); + return oklab.concat( (rest.length > 0 && rest[0] < 1 ? [rest[0]] : [])); + }; + + // from https://www.w3.org/TR/css-color-4/#color-conversion-code + function XYZ_to_OKLab(XYZ) { + // Given XYZ relative to D65, convert to OKLab + var XYZtoLMS = [ + [0.819022437996703, 0.3619062600528904, -0.1288737815209879], + [0.0329836539323885, 0.9292868615863434, 0.0361446663506424], + [0.0481771893596242, 0.2642395317527308, 0.6335478284694309] + ]; + var LMStoOKLab = [ + [0.210454268309314, 0.7936177747023054, -0.0040720430116193], + [1.9779985324311684, -2.42859224204858, 0.450593709617411], + [0.0259040424655478, 0.7827717124575296, -0.8086757549230774] + ]; + + var LMS = multiplyMatrices(XYZtoLMS, XYZ); + // JavaScript Math.cbrt returns a sign-matched cube root + // beware if porting to other languages + // especially if tempted to use a general power function + return multiplyMatrices( + LMStoOKLab, + LMS.map(function (c) { return Math.cbrt(c); }) + ); + // L in range [0,1]. For use in CSS, multiply by 100 and add a percent + } + + var oklab2css = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var laba = unpack(args, 'lab'); + laba[0] = rnd2(laba[0] * 100) + '%'; + laba[1] = rnd3(laba[1]); + laba[2] = rnd3(laba[2]); + if (laba.length > 3 && laba[3] < 1) { + laba[3] = '/ ' + (laba.length > 3 ? laba[3] : 1); + } else { + laba.length = 3; + } + return ("oklab(" + (laba.join(' ')) + ")"); + }; + + var rgb2oklch = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var ref = unpack(args, 'rgb'); + var r = ref[0]; + var g = ref[1]; + var b = ref[2]; + var rest = ref.slice(3); + var ref$1 = rgb2oklab(r, g, b); + var l = ref$1[0]; + var a = ref$1[1]; + var b_ = ref$1[2]; + var ref$2 = lab2lch(l, a, b_); + var L = ref$2[0]; + var c = ref$2[1]; + var h = ref$2[2]; + return [L, c, h ].concat( (rest.length > 0 && rest[0] < 1 ? [rest[0]] : [])); + }; + + var oklch2css = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var lcha = unpack(args, 'lch'); + lcha[0] = rnd2(lcha[0] * 100) + '%'; + lcha[1] = rnd3(lcha[1]); + lcha[2] = isNaN(lcha[2]) ? 'none' : rnd2(lcha[2]) + 'deg'; // add deg unit to hue + if (lcha.length > 3 && lcha[3] < 1) { + lcha[3] = '/ ' + (lcha.length > 3 ? lcha[3] : 1); + } else { + lcha.length = 3; + } + return ("oklch(" + (lcha.join(' ')) + ")"); + }; + + var round$4 = Math.round; + + /* + * supported arguments: + * - rgb2css(r,g,b) + * - rgb2css(r,g,b,a) + * - rgb2css([r,g,b], mode) + * - rgb2css([r,g,b,a], mode) + * - rgb2css({r,g,b,a}, mode) + */ + var rgb2css = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var rgba = unpack(args, 'rgba'); + var mode = last(args) || 'rgb'; + if (mode.substr(0, 3) === 'hsl') { + return hsl2css(rgb2hsl$1(rgba), mode); + } + if (mode.substr(0, 3) === 'lab') { + // change to D50 lab whitepoint since this is what W3C is using for CSS Lab colors + var prevWhitePoint = getLabWhitePoint(); + setLabWhitePoint('d50'); + var cssColor = lab2css(rgb2lab(rgba), mode); + setLabWhitePoint(prevWhitePoint); + return cssColor; + } + if (mode.substr(0, 3) === 'lch') { + // change to D50 lab whitepoint since this is what W3C is using for CSS Lab colors + var prevWhitePoint$1 = getLabWhitePoint(); + setLabWhitePoint('d50'); + var cssColor$1 = lch2css(rgb2lch(rgba), mode); + setLabWhitePoint(prevWhitePoint$1); + return cssColor$1; + } + if (mode.substr(0, 5) === 'oklab') { + return oklab2css(rgb2oklab(rgba)); + } + if (mode.substr(0, 5) === 'oklch') { + return oklch2css(rgb2oklch(rgba)); + } + rgba[0] = round$4(rgba[0]); + rgba[1] = round$4(rgba[1]); + rgba[2] = round$4(rgba[2]); + if (mode === 'rgba' || (rgba.length > 3 && rgba[3] < 1)) { + rgba[3] = '/ ' + (rgba.length > 3 ? rgba[3] : 1); + mode = 'rgba'; + } + return ((mode.substr(0, 3)) + "(" + (rgba.slice(0, mode === 'rgb' ? 3 : 4).join(' ')) + ")"); + }; + + var hsl2rgb = function () { + var assign; + + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + args = unpack(args, 'hsl'); + var h = args[0]; + var s = args[1]; + var l = args[2]; + var r, g, b; + if (s === 0) { + r = g = b = l * 255; + } else { + var t3 = [0, 0, 0]; + var c = [0, 0, 0]; + var t2 = l < 0.5 ? l * (1 + s) : l + s - l * s; + var t1 = 2 * l - t2; + var h_ = h / 360; + t3[0] = h_ + 1 / 3; + t3[1] = h_; + t3[2] = h_ - 1 / 3; + for (var i = 0; i < 3; i++) { + if (t3[i] < 0) { t3[i] += 1; } + if (t3[i] > 1) { t3[i] -= 1; } + if (6 * t3[i] < 1) { c[i] = t1 + (t2 - t1) * 6 * t3[i]; } + else if (2 * t3[i] < 1) { c[i] = t2; } + else if (3 * t3[i] < 2) { c[i] = t1 + (t2 - t1) * (2 / 3 - t3[i]) * 6; } + else { c[i] = t1; } + } + (assign = [c[0] * 255, c[1] * 255, c[2] * 255], r = assign[0], g = assign[1], b = assign[2]); + } + if (args.length > 3) { + // keep alpha channel + return [r, g, b, args[3]]; + } + return [r, g, b, 1]; + }; + + /* + * L* [0..100] + * a [-100..100] + * b [-100..100] + */ + var lab2rgb = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, 'lab'); + var L = args[0]; + var a = args[1]; + var b = args[2]; + var ref = lab2xyz(L, a, b); + var x = ref[0]; + var y = ref[1]; + var z = ref[2]; + var ref$1 = xyz2rgb(x, y, z); + var r = ref$1[0]; + var g = ref$1[1]; + var b_ = ref$1[2]; + return [r, g, b_, args.length > 3 ? args[3] : 1]; + }; + + var lab2xyz = function (L, a, b) { + var kE = labConstants.kE; + var kK = labConstants.kK; + var kKE = labConstants.kKE; + var Xn = labConstants.Xn; + var Yn = labConstants.Yn; + var Zn = labConstants.Zn; + + var fy = (L + 16.0) / 116.0; + var fx = 0.002 * a + fy; + var fz = fy - 0.005 * b; + + var fx3 = fx * fx * fx; + var fz3 = fz * fz * fz; + + var xr = fx3 > kE ? fx3 : (116.0 * fx - 16.0) / kK; + var yr = L > kKE ? Math.pow((L + 16.0) / 116.0, 3.0) : L / kK; + var zr = fz3 > kE ? fz3 : (116.0 * fz - 16.0) / kK; + + var x = xr * Xn; + var y = yr * Yn; + var z = zr * Zn; + + return [x, y, z]; + }; + + var compand = function (linear) { + /* sRGB */ + var sign = Math.sign(linear); + linear = Math.abs(linear); + return ( + (linear <= 0.0031308 + ? linear * 12.92 + : 1.055 * Math.pow(linear, 1.0 / 2.4) - 0.055) * sign + ); + }; + + var xyz2rgb = function (x, y, z) { + var MtxAdaptMa = labConstants.MtxAdaptMa; + var MtxAdaptMaI = labConstants.MtxAdaptMaI; + var MtxXYZ2RGB = labConstants.MtxXYZ2RGB; + var RefWhiteRGB = labConstants.RefWhiteRGB; + var Xn = labConstants.Xn; + var Yn = labConstants.Yn; + var Zn = labConstants.Zn; + + var As = Xn * MtxAdaptMa.m00 + Yn * MtxAdaptMa.m10 + Zn * MtxAdaptMa.m20; + var Bs = Xn * MtxAdaptMa.m01 + Yn * MtxAdaptMa.m11 + Zn * MtxAdaptMa.m21; + var Cs = Xn * MtxAdaptMa.m02 + Yn * MtxAdaptMa.m12 + Zn * MtxAdaptMa.m22; + + var Ad = + RefWhiteRGB.X * MtxAdaptMa.m00 + + RefWhiteRGB.Y * MtxAdaptMa.m10 + + RefWhiteRGB.Z * MtxAdaptMa.m20; + var Bd = + RefWhiteRGB.X * MtxAdaptMa.m01 + + RefWhiteRGB.Y * MtxAdaptMa.m11 + + RefWhiteRGB.Z * MtxAdaptMa.m21; + var Cd = + RefWhiteRGB.X * MtxAdaptMa.m02 + + RefWhiteRGB.Y * MtxAdaptMa.m12 + + RefWhiteRGB.Z * MtxAdaptMa.m22; + + var X1 = + (x * MtxAdaptMa.m00 + y * MtxAdaptMa.m10 + z * MtxAdaptMa.m20) * + (Ad / As); + var Y1 = + (x * MtxAdaptMa.m01 + y * MtxAdaptMa.m11 + z * MtxAdaptMa.m21) * + (Bd / Bs); + var Z1 = + (x * MtxAdaptMa.m02 + y * MtxAdaptMa.m12 + z * MtxAdaptMa.m22) * + (Cd / Cs); + + var X2 = + X1 * MtxAdaptMaI.m00 + Y1 * MtxAdaptMaI.m10 + Z1 * MtxAdaptMaI.m20; + var Y2 = + X1 * MtxAdaptMaI.m01 + Y1 * MtxAdaptMaI.m11 + Z1 * MtxAdaptMaI.m21; + var Z2 = + X1 * MtxAdaptMaI.m02 + Y1 * MtxAdaptMaI.m12 + Z1 * MtxAdaptMaI.m22; + + var r = compand( + X2 * MtxXYZ2RGB.m00 + Y2 * MtxXYZ2RGB.m10 + Z2 * MtxXYZ2RGB.m20 + ); + var g = compand( + X2 * MtxXYZ2RGB.m01 + Y2 * MtxXYZ2RGB.m11 + Z2 * MtxXYZ2RGB.m21 + ); + var b = compand( + X2 * MtxXYZ2RGB.m02 + Y2 * MtxXYZ2RGB.m12 + Z2 * MtxXYZ2RGB.m22 + ); + + return [r * 255, g * 255, b * 255]; + }; + + var sin$3 = Math.sin; + var cos$4 = Math.cos; + + var lch2lab = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + /* + Convert from a qualitative parameter h and a quantitative parameter l to a 24-bit pixel. + These formulas were invented by David Dalrymple to obtain maximum contrast without going + out of gamut if the parameters are in the range 0-1. + + A saturation multiplier was added by Gregor Aisch + */ + var ref = unpack(args, 'lch'); + var l = ref[0]; + var c = ref[1]; + var h = ref[2]; + if (isNaN(h)) { h = 0; } + h = h * DEG2RAD; + return [l, cos$4(h) * c, sin$3(h) * c]; + }; + + var lch2rgb = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, 'lch'); + var l = args[0]; + var c = args[1]; + var h = args[2]; + var ref = lch2lab(l, c, h); + var L = ref[0]; + var a = ref[1]; + var b_ = ref[2]; + var ref$1 = lab2rgb(L, a, b_); + var r = ref$1[0]; + var g = ref$1[1]; + var b = ref$1[2]; + return [r, g, b, args.length > 3 ? args[3] : 1]; + }; + + var oklab2rgb = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, 'lab'); + var L = args[0]; + var a = args[1]; + var b = args[2]; + var rest = args.slice(3); + var ref = OKLab_to_XYZ([L, a, b]); + var X = ref[0]; + var Y = ref[1]; + var Z = ref[2]; + var ref$1 = xyz2rgb(X, Y, Z); + var r = ref$1[0]; + var g = ref$1[1]; + var b_ = ref$1[2]; + return [r, g, b_ ].concat( (rest.length > 0 && rest[0] < 1 ? [rest[0]] : [])); + }; + + // from https://www.w3.org/TR/css-color-4/#color-conversion-code + function OKLab_to_XYZ(OKLab) { + // Given OKLab, convert to XYZ relative to D65 + var LMStoXYZ = [ + [1.2268798758459243, -0.5578149944602171, 0.2813910456659647], + [-0.0405757452148008, 1.112286803280317, -0.0717110580655164], + [-0.0763729366746601, -0.4214933324022432, 1.5869240198367816] + ]; + var OKLabtoLMS = [ + [1.0, 0.3963377773761749, 0.2158037573099136], + [1.0, -0.1055613458156586, -0.0638541728258133], + [1.0, -0.0894841775298119, -1.2914855480194092] + ]; + + var LMSnl = multiplyMatrices(OKLabtoLMS, OKLab); + return multiplyMatrices( + LMStoXYZ, + LMSnl.map(function (c) { return Math.pow( c, 3 ); }) + ); + } + + var oklch2rgb = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, 'lch'); + var l = args[0]; + var c = args[1]; + var h = args[2]; + var rest = args.slice(3); + var ref = lch2lab(l, c, h); + var L = ref[0]; + var a = ref[1]; + var b_ = ref[2]; + var ref$1 = oklab2rgb(L, a, b_); + var r = ref$1[0]; + var g = ref$1[1]; + var b = ref$1[2]; + return [r, g, b ].concat( (rest.length > 0 && rest[0] < 1 ? [rest[0]] : [])); + }; + + var INT_OR_PCT = /((?:-?\d+)|(?:-?\d+(?:\.\d+)?)%|none)/.source; + var FLOAT_OR_PCT = /((?:-?(?:\d+(?:\.\d*)?|\.\d+)%?)|none)/.source; + var PCT = /((?:-?(?:\d+(?:\.\d*)?|\.\d+)%)|none)/.source; + var RE_S = /\s*/.source; + var SEP = /\s+/.source; + var COMMA = /\s*,\s*/.source; + var ANLGE = /((?:-?(?:\d+(?:\.\d*)?|\.\d+)(?:deg)?)|none)/.source; + var ALPHA = /\s*(?:\/\s*((?:[01]|[01]?\.\d+)|\d+(?:\.\d+)?%))?/.source; + + // e.g. rgb(250 20 0), rgb(100% 50% 20%), rgb(100% 50% 20% / 0.5) + var RE_RGB = new RegExp( + '^rgba?\\(' + + RE_S + + [INT_OR_PCT, INT_OR_PCT, INT_OR_PCT].join(SEP) + + ALPHA + + '\\)$' + ); + var RE_RGB_LEGACY = new RegExp( + '^rgb\\(' + + RE_S + + [INT_OR_PCT, INT_OR_PCT, INT_OR_PCT].join(COMMA) + + RE_S + + '\\)$' + ); + var RE_RGBA_LEGACY = new RegExp( + '^rgba\\(' + + RE_S + + [INT_OR_PCT, INT_OR_PCT, INT_OR_PCT, FLOAT_OR_PCT].join(COMMA) + + RE_S + + '\\)$' + ); + + var RE_HSL = new RegExp( + '^hsla?\\(' + RE_S + [ANLGE, PCT, PCT].join(SEP) + ALPHA + '\\)$' + ); + var RE_HSL_LEGACY = new RegExp( + '^hsl?\\(' + RE_S + [ANLGE, PCT, PCT].join(COMMA) + RE_S + '\\)$' + ); + var RE_HSLA_LEGACY = + /^hsla\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/; + + var RE_LAB = new RegExp( + '^lab\\(' + + RE_S + + [FLOAT_OR_PCT, FLOAT_OR_PCT, FLOAT_OR_PCT].join(SEP) + + ALPHA + + '\\)$' + ); + var RE_LCH = new RegExp( + '^lch\\(' + + RE_S + + [FLOAT_OR_PCT, FLOAT_OR_PCT, ANLGE].join(SEP) + + ALPHA + + '\\)$' + ); + var RE_OKLAB = new RegExp( + '^oklab\\(' + + RE_S + + [FLOAT_OR_PCT, FLOAT_OR_PCT, FLOAT_OR_PCT].join(SEP) + + ALPHA + + '\\)$' + ); + var RE_OKLCH = new RegExp( + '^oklch\\(' + + RE_S + + [FLOAT_OR_PCT, FLOAT_OR_PCT, ANLGE].join(SEP) + + ALPHA + + '\\)$' + ); + + var round$3 = Math.round; + + var roundRGB = function (rgb) { + return rgb.map(function (v, i) { return (i <= 2 ? limit(round$3(v), 0, 255) : v); }); + }; + + var percentToAbsolute = function (pct, min, max, signed) { + if ( min === void 0 ) min = 0; + if ( max === void 0 ) max = 100; + if ( signed === void 0 ) signed = false; + + if (typeof pct === 'string' && pct.endsWith('%')) { + pct = parseFloat(pct.substring(0, pct.length - 1)) / 100; + if (signed) { + // signed percentages are in the range -100% to 100% + pct = min + (pct + 1) * 0.5 * (max - min); + } else { + pct = min + pct * (max - min); + } + } + return +pct; + }; + + var noneToValue = function (v, noneValue) { + return v === 'none' ? noneValue : v; + }; + + var css2rgb = function (css) { + css = css.toLowerCase().trim(); + + if (css === 'transparent') { + return [0, 0, 0, 0]; + } + + var m; + + if (input.format.named) { + try { + return input.format.named(css); + // eslint-disable-next-line + } catch (e) {} + } + + // rgb(250 20 0) or rgb(250,20,0) + if ((m = css.match(RE_RGB)) || (m = css.match(RE_RGB_LEGACY))) { + var rgb = m.slice(1, 4); + for (var i = 0; i < 3; i++) { + rgb[i] = +percentToAbsolute(noneToValue(rgb[i], 0), 0, 255); + } + rgb = roundRGB(rgb); + var alpha = m[4] !== undefined ? +percentToAbsolute(m[4], 0, 1) : 1; + rgb[3] = alpha; // default alpha + return rgb; + } + + // rgba(250,20,0,0.4) + if ((m = css.match(RE_RGBA_LEGACY))) { + var rgb$1 = m.slice(1, 5); + for (var i$1 = 0; i$1 < 4; i$1++) { + rgb$1[i$1] = +percentToAbsolute(rgb$1[i$1], 0, 255); + } + return rgb$1; + } + + // hsl(0,100%,50%) + if ((m = css.match(RE_HSL)) || (m = css.match(RE_HSL_LEGACY))) { + var hsl = m.slice(1, 4); + hsl[0] = +noneToValue(hsl[0].replace('deg', ''), 0); + hsl[1] = +percentToAbsolute(noneToValue(hsl[1], 0), 0, 100) * 0.01; + hsl[2] = +percentToAbsolute(noneToValue(hsl[2], 0), 0, 100) * 0.01; + var rgb$2 = roundRGB(hsl2rgb(hsl)); + var alpha$1 = m[4] !== undefined ? +percentToAbsolute(m[4], 0, 1) : 1; + rgb$2[3] = alpha$1; + return rgb$2; + } + + // hsla(0,100%,50%,0.5) + if ((m = css.match(RE_HSLA_LEGACY))) { + var hsl$1 = m.slice(1, 4); + hsl$1[1] *= 0.01; + hsl$1[2] *= 0.01; + var rgb$3 = hsl2rgb(hsl$1); + for (var i$2 = 0; i$2 < 3; i$2++) { + rgb$3[i$2] = round$3(rgb$3[i$2]); + } + rgb$3[3] = +m[4]; // default alpha = 1 + return rgb$3; + } + + if ((m = css.match(RE_LAB))) { + var lab = m.slice(1, 4); + lab[0] = percentToAbsolute(noneToValue(lab[0], 0), 0, 100); + lab[1] = percentToAbsolute(noneToValue(lab[1], 0), -125, 125, true); + lab[2] = percentToAbsolute(noneToValue(lab[2], 0), -125, 125, true); + // convert to D50 Lab whitepoint + var wp = getLabWhitePoint(); + setLabWhitePoint('d50'); + var rgb$4 = roundRGB(lab2rgb(lab)); + // convert back to original Lab whitepoint + setLabWhitePoint(wp); + var alpha$2 = m[4] !== undefined ? +percentToAbsolute(m[4], 0, 1) : 1; + rgb$4[3] = alpha$2; + return rgb$4; + } + + if ((m = css.match(RE_LCH))) { + var lch = m.slice(1, 4); + lch[0] = percentToAbsolute(lch[0], 0, 100); + lch[1] = percentToAbsolute(noneToValue(lch[1], 0), 0, 150, false); + lch[2] = +noneToValue(lch[2].replace('deg', ''), 0); + // convert to D50 Lab whitepoint + var wp$1 = getLabWhitePoint(); + setLabWhitePoint('d50'); + var rgb$5 = roundRGB(lch2rgb(lch)); + // convert back to original Lab whitepoint + setLabWhitePoint(wp$1); + var alpha$3 = m[4] !== undefined ? +percentToAbsolute(m[4], 0, 1) : 1; + rgb$5[3] = alpha$3; + return rgb$5; + } + + if ((m = css.match(RE_OKLAB))) { + var oklab = m.slice(1, 4); + oklab[0] = percentToAbsolute(noneToValue(oklab[0], 0), 0, 1); + oklab[1] = percentToAbsolute(noneToValue(oklab[1], 0), -0.4, 0.4, true); + oklab[2] = percentToAbsolute(noneToValue(oklab[2], 0), -0.4, 0.4, true); + var rgb$6 = roundRGB(oklab2rgb(oklab)); + var alpha$4 = m[4] !== undefined ? +percentToAbsolute(m[4], 0, 1) : 1; + rgb$6[3] = alpha$4; + return rgb$6; + } + + if ((m = css.match(RE_OKLCH))) { + var oklch = m.slice(1, 4); + oklch[0] = percentToAbsolute(noneToValue(oklch[0], 0), 0, 1); + oklch[1] = percentToAbsolute(noneToValue(oklch[1], 0), 0, 0.4, false); + oklch[2] = +noneToValue(oklch[2].replace('deg', ''), 0); + var rgb$7 = roundRGB(oklch2rgb(oklch)); + var alpha$5 = m[4] !== undefined ? +percentToAbsolute(m[4], 0, 1) : 1; + rgb$7[3] = alpha$5; + return rgb$7; + } + }; + + css2rgb.test = function (s) { + return ( + // modern + RE_RGB.test(s) || + RE_HSL.test(s) || + RE_LAB.test(s) || + RE_LCH.test(s) || + RE_OKLAB.test(s) || + RE_OKLCH.test(s) || + // legacy + RE_RGB_LEGACY.test(s) || + RE_RGBA_LEGACY.test(s) || + RE_HSL_LEGACY.test(s) || + RE_HSLA_LEGACY.test(s) || + s === 'transparent' + ); + }; + + Color.prototype.css = function (mode) { + return rgb2css(this._rgb, mode); + }; + + var css = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args, ['css']) )); + }; + chroma.css = css; + + input.format.css = css2rgb; + + input.autodetect.push({ + p: 5, + test: function (h) { + var rest = [], len = arguments.length - 1; + while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ]; + + if (!rest.length && type(h) === 'string' && css2rgb.test(h)) { + return 'css'; + } + } + }); + + input.format.gl = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var rgb = unpack(args, 'rgba'); + rgb[0] *= 255; + rgb[1] *= 255; + rgb[2] *= 255; + return rgb; + }; + + var gl = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args, ['gl']) )); + }; + chroma.gl = gl; + + Color.prototype.gl = function () { + var rgb = this._rgb; + return [rgb[0] / 255, rgb[1] / 255, rgb[2] / 255, rgb[3]]; + }; + + var floor$3 = Math.floor; + + /* + * this is basically just HSV with some minor tweaks + * + * hue.. [0..360] + * chroma .. [0..1] + * grayness .. [0..1] + */ + + var hcg2rgb = function () { + var assign, assign$1, assign$2, assign$3, assign$4, assign$5; + + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + args = unpack(args, 'hcg'); + var h = args[0]; + var c = args[1]; + var _g = args[2]; + var r, g, b; + _g = _g * 255; + var _c = c * 255; + if (c === 0) { + r = g = b = _g; + } else { + if (h === 360) { h = 0; } + if (h > 360) { h -= 360; } + if (h < 0) { h += 360; } + h /= 60; + var i = floor$3(h); + var f = h - i; + var p = _g * (1 - c); + var q = p + _c * (1 - f); + var t = p + _c * f; + var v = p + _c; + switch (i) { + case 0: + (assign = [v, t, p], r = assign[0], g = assign[1], b = assign[2]); + break; + case 1: + (assign$1 = [q, v, p], r = assign$1[0], g = assign$1[1], b = assign$1[2]); + break; + case 2: + (assign$2 = [p, v, t], r = assign$2[0], g = assign$2[1], b = assign$2[2]); + break; + case 3: + (assign$3 = [p, q, v], r = assign$3[0], g = assign$3[1], b = assign$3[2]); + break; + case 4: + (assign$4 = [t, p, v], r = assign$4[0], g = assign$4[1], b = assign$4[2]); + break; + case 5: + (assign$5 = [v, p, q], r = assign$5[0], g = assign$5[1], b = assign$5[2]); + break; + } + } + return [r, g, b, args.length > 3 ? args[3] : 1]; + }; + + var rgb2hcg = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var ref = unpack(args, 'rgb'); + var r = ref[0]; + var g = ref[1]; + var b = ref[2]; + var minRgb = min$3(r, g, b); + var maxRgb = max$3(r, g, b); + var delta = maxRgb - minRgb; + var c = (delta * 100) / 255; + var _g = (minRgb / (255 - delta)) * 100; + var h; + if (delta === 0) { + h = Number.NaN; + } else { + if (r === maxRgb) { h = (g - b) / delta; } + if (g === maxRgb) { h = 2 + (b - r) / delta; } + if (b === maxRgb) { h = 4 + (r - g) / delta; } + h *= 60; + if (h < 0) { h += 360; } + } + return [h, c, _g]; + }; + + Color.prototype.hcg = function () { + return rgb2hcg(this._rgb); + }; + + var hcg$1 = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args, ['hcg']) )); + }; + chroma.hcg = hcg$1; + + input.format.hcg = hcg2rgb; + + input.autodetect.push({ + p: 1, + test: function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, 'hcg'); + if (type(args) === 'array' && args.length === 3) { + return 'hcg'; + } + } + }); + + var RE_HEX = /^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/; + var RE_HEXA = /^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$/; + + var hex2rgb = function (hex) { + if (hex.match(RE_HEX)) { + // remove optional leading # + if (hex.length === 4 || hex.length === 7) { + hex = hex.substr(1); + } + // expand short-notation to full six-digit + if (hex.length === 3) { + hex = hex.split(''); + hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; + } + var u = parseInt(hex, 16); + var r = u >> 16; + var g = (u >> 8) & 0xff; + var b = u & 0xff; + return [r, g, b, 1]; + } + + // match rgba hex format, eg #FF000077 + if (hex.match(RE_HEXA)) { + if (hex.length === 5 || hex.length === 9) { + // remove optional leading # + hex = hex.substr(1); + } + // expand short-notation to full eight-digit + if (hex.length === 4) { + hex = hex.split(''); + hex = + hex[0] + + hex[0] + + hex[1] + + hex[1] + + hex[2] + + hex[2] + + hex[3] + + hex[3]; + } + var u$1 = parseInt(hex, 16); + var r$1 = (u$1 >> 24) & 0xff; + var g$1 = (u$1 >> 16) & 0xff; + var b$1 = (u$1 >> 8) & 0xff; + var a = Math.round(((u$1 & 0xff) / 0xff) * 100) / 100; + return [r$1, g$1, b$1, a]; + } + + // we used to check for css colors here + // if _input.css? and rgb = _input.css hex + // return rgb + + throw new Error(("unknown hex color: " + hex)); + }; + + var round$2 = Math.round; + + var rgb2hex = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var ref = unpack(args, 'rgba'); + var r = ref[0]; + var g = ref[1]; + var b = ref[2]; + var a = ref[3]; + var mode = last(args) || 'auto'; + if (a === undefined) { a = 1; } + if (mode === 'auto') { + mode = a < 1 ? 'rgba' : 'rgb'; + } + r = round$2(r); + g = round$2(g); + b = round$2(b); + var u = (r << 16) | (g << 8) | b; + var str = '000000' + u.toString(16); //#.toUpperCase(); + str = str.substr(str.length - 6); + var hxa = '0' + round$2(a * 255).toString(16); + hxa = hxa.substr(hxa.length - 2); + switch (mode.toLowerCase()) { + case 'rgba': + return ("#" + str + hxa); + case 'argb': + return ("#" + hxa + str); + default: + return ("#" + str); + } + }; + + Color.prototype.hex = function (mode) { + return rgb2hex(this._rgb, mode); + }; + + var hex = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args, ['hex']) )); + }; + chroma.hex = hex; + + input.format.hex = hex2rgb; + input.autodetect.push({ + p: 4, + test: function (h) { + var rest = [], len = arguments.length - 1; + while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ]; + + if ( + !rest.length && + type(h) === 'string' && + [3, 4, 5, 6, 7, 8, 9].indexOf(h.length) >= 0 + ) { + return 'hex'; + } + } + }); + + var cos$3 = Math.cos; + + /* + * hue [0..360] + * saturation [0..1] + * intensity [0..1] + */ + var hsi2rgb = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + /* + borrowed from here: + http://hummer.stanford.edu/museinfo/doc/examples/humdrum/keyscape2/hsi2rgb.cpp + */ + args = unpack(args, 'hsi'); + var h = args[0]; + var s = args[1]; + var i = args[2]; + var r, g, b; + + if (isNaN(h)) { h = 0; } + if (isNaN(s)) { s = 0; } + // normalize hue + if (h > 360) { h -= 360; } + if (h < 0) { h += 360; } + h /= 360; + if (h < 1 / 3) { + b = (1 - s) / 3; + r = (1 + (s * cos$3(TWOPI * h)) / cos$3(PITHIRD - TWOPI * h)) / 3; + g = 1 - (b + r); + } else if (h < 2 / 3) { + h -= 1 / 3; + r = (1 - s) / 3; + g = (1 + (s * cos$3(TWOPI * h)) / cos$3(PITHIRD - TWOPI * h)) / 3; + b = 1 - (r + g); + } else { + h -= 2 / 3; + g = (1 - s) / 3; + b = (1 + (s * cos$3(TWOPI * h)) / cos$3(PITHIRD - TWOPI * h)) / 3; + r = 1 - (g + b); + } + r = limit(i * r * 3); + g = limit(i * g * 3); + b = limit(i * b * 3); + return [r * 255, g * 255, b * 255, args.length > 3 ? args[3] : 1]; + }; + + var min$2 = Math.min; + var sqrt$3 = Math.sqrt; + var acos = Math.acos; + + var rgb2hsi = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + /* + borrowed from here: + http://hummer.stanford.edu/museinfo/doc/examples/humdrum/keyscape2/rgb2hsi.cpp + */ + var ref = unpack(args, 'rgb'); + var r = ref[0]; + var g = ref[1]; + var b = ref[2]; + r /= 255; + g /= 255; + b /= 255; + var h; + var min_ = min$2(r, g, b); + var i = (r + g + b) / 3; + var s = i > 0 ? 1 - min_ / i : 0; + if (s === 0) { + h = NaN; + } else { + h = (r - g + (r - b)) / 2; + h /= sqrt$3((r - g) * (r - g) + (r - b) * (g - b)); + h = acos(h); + if (b > g) { + h = TWOPI - h; + } + h /= TWOPI; + } + return [h * 360, s, i]; + }; + + Color.prototype.hsi = function () { + return rgb2hsi(this._rgb); + }; + + var hsi$1 = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args, ['hsi']) )); + }; + chroma.hsi = hsi$1; + + input.format.hsi = hsi2rgb; + + input.autodetect.push({ + p: 2, + test: function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, 'hsi'); + if (type(args) === 'array' && args.length === 3) { + return 'hsi'; + } + } + }); + + Color.prototype.hsl = function () { + return rgb2hsl$1(this._rgb); + }; + + var hsl$1 = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args, ['hsl']) )); + }; + chroma.hsl = hsl$1; + + input.format.hsl = hsl2rgb; + + input.autodetect.push({ + p: 2, + test: function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, 'hsl'); + if (type(args) === 'array' && args.length === 3) { + return 'hsl'; + } + } + }); + + var floor$2 = Math.floor; + + var hsv2rgb = function () { + var assign, assign$1, assign$2, assign$3, assign$4, assign$5; + + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + args = unpack(args, 'hsv'); + var h = args[0]; + var s = args[1]; + var v = args[2]; + var r, g, b; + v *= 255; + if (s === 0) { + r = g = b = v; + } else { + if (h === 360) { h = 0; } + if (h > 360) { h -= 360; } + if (h < 0) { h += 360; } + h /= 60; + + var i = floor$2(h); + var f = h - i; + var p = v * (1 - s); + var q = v * (1 - s * f); + var t = v * (1 - s * (1 - f)); + + switch (i) { + case 0: + (assign = [v, t, p], r = assign[0], g = assign[1], b = assign[2]); + break; + case 1: + (assign$1 = [q, v, p], r = assign$1[0], g = assign$1[1], b = assign$1[2]); + break; + case 2: + (assign$2 = [p, v, t], r = assign$2[0], g = assign$2[1], b = assign$2[2]); + break; + case 3: + (assign$3 = [p, q, v], r = assign$3[0], g = assign$3[1], b = assign$3[2]); + break; + case 4: + (assign$4 = [t, p, v], r = assign$4[0], g = assign$4[1], b = assign$4[2]); + break; + case 5: + (assign$5 = [v, p, q], r = assign$5[0], g = assign$5[1], b = assign$5[2]); + break; + } + } + return [r, g, b, args.length > 3 ? args[3] : 1]; + }; + + var min$1 = Math.min; + var max$1 = Math.max; + + /* + * supported arguments: + * - rgb2hsv(r,g,b) + * - rgb2hsv([r,g,b]) + * - rgb2hsv({r,g,b}) + */ + var rgb2hsl = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, 'rgb'); + var r = args[0]; + var g = args[1]; + var b = args[2]; + var min_ = min$1(r, g, b); + var max_ = max$1(r, g, b); + var delta = max_ - min_; + var h, s, v; + v = max_ / 255.0; + if (max_ === 0) { + h = Number.NaN; + s = 0; + } else { + s = delta / max_; + if (r === max_) { h = (g - b) / delta; } + if (g === max_) { h = 2 + (b - r) / delta; } + if (b === max_) { h = 4 + (r - g) / delta; } + h *= 60; + if (h < 0) { h += 360; } + } + return [h, s, v]; + }; + + Color.prototype.hsv = function () { + return rgb2hsl(this._rgb); + }; + + var hsv$1 = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args, ['hsv']) )); + }; + chroma.hsv = hsv$1; + + input.format.hsv = hsv2rgb; + + input.autodetect.push({ + p: 2, + test: function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, 'hsv'); + if (type(args) === 'array' && args.length === 3) { + return 'hsv'; + } + } + }); + + Color.prototype.lab = function () { + return rgb2lab(this._rgb); + }; + + var lab$1 = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args, ['lab']) )); + }; + Object.assign(chroma, { lab: lab$1, getLabWhitePoint: getLabWhitePoint, setLabWhitePoint: setLabWhitePoint }); + + input.format.lab = lab2rgb; + + input.autodetect.push({ + p: 2, + test: function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, 'lab'); + if (type(args) === 'array' && args.length === 3) { + return 'lab'; + } + } + }); + + var hcl2rgb = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var hcl = reverse3(unpack(args, 'hcl')); + return lch2rgb.apply(void 0, hcl); + }; + + Color.prototype.lch = function () { + return rgb2lch(this._rgb); + }; + Color.prototype.hcl = function () { + return reverse3(rgb2lch(this._rgb)); + }; + + var lch$1 = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args, ['lch']) )); + }; + var hcl = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args, ['hcl']) )); + }; + + Object.assign(chroma, { lch: lch$1, hcl: hcl }); + + input.format.lch = lch2rgb; + input.format.hcl = hcl2rgb; + ['lch', 'hcl'].forEach(function (m) { return input.autodetect.push({ + p: 2, + test: function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, m); + if (type(args) === 'array' && args.length === 3) { + return m; + } + } + }); } + ); + + var num2rgb = function (num) { + if (type(num) == 'number' && num >= 0 && num <= 0xffffff) { + var r = num >> 16; + var g = (num >> 8) & 0xff; + var b = num & 0xff; + return [r, g, b, 1]; + } + throw new Error('unknown num color: ' + num); + }; + + var rgb2num = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var ref = unpack(args, 'rgb'); + var r = ref[0]; + var g = ref[1]; + var b = ref[2]; + return (r << 16) + (g << 8) + b; + }; + + Color.prototype.num = function () { + return rgb2num(this._rgb); + }; + + var num$1 = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args, ['num']) )); + }; + + Object.assign(chroma, { num: num$1 }); + + input.format.num = num2rgb; + + input.autodetect.push({ + p: 5, + test: function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + if ( + args.length === 1 && + type(args[0]) === 'number' && + args[0] >= 0 && + args[0] <= 0xffffff + ) { + return 'num'; + } + } + }); + + var round$1 = Math.round; + + Color.prototype.rgb = function (rnd) { + if ( rnd === void 0 ) rnd = true; + + if (rnd === false) { return this._rgb.slice(0, 3); } + return this._rgb.slice(0, 3).map(round$1); + }; + + Color.prototype.rgba = function (rnd) { + if ( rnd === void 0 ) rnd = true; + + return this._rgb.slice(0, 4).map(function (v, i) { + return i < 3 ? (rnd === false ? v : round$1(v)) : v; + }); + }; + + var rgb$1 = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args, ['rgb']) )); + }; + Object.assign(chroma, { rgb: rgb$1 }); + + input.format.rgb = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var rgba = unpack(args, 'rgba'); + if (rgba[3] === undefined) { rgba[3] = 1; } + return rgba; + }; + + input.autodetect.push({ + p: 3, + test: function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, 'rgba'); + if ( + type(args) === 'array' && + (args.length === 3 || + (args.length === 4 && + type(args[3]) == 'number' && + args[3] >= 0 && + args[3] <= 1)) + ) { + return 'rgb'; + } + } + }); + + /* + * Based on implementation by Neil Bartlett + * https://github.com/neilbartlett/color-temperature + */ + + var log$1 = Math.log; + + var temperature2rgb = function (kelvin) { + var temp = kelvin / 100; + var r, g, b; + if (temp < 66) { + r = 255; + g = + temp < 6 + ? 0 + : -155.25485562709179 - + 0.44596950469579133 * (g = temp - 2) + + 104.49216199393888 * log$1(g); + b = + temp < 20 + ? 0 + : -254.76935184120902 + + 0.8274096064007395 * (b = temp - 10) + + 115.67994401066147 * log$1(b); + } else { + r = + 351.97690566805693 + + 0.114206453784165 * (r = temp - 55) - + 40.25366309332127 * log$1(r); + g = + 325.4494125711974 + + 0.07943456536662342 * (g = temp - 50) - + 28.0852963507957 * log$1(g); + b = 255; + } + return [r, g, b, 1]; + }; + + /* + * Based on implementation by Neil Bartlett + * https://github.com/neilbartlett/color-temperature + **/ + + var round = Math.round; + + var rgb2temperature = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + var rgb = unpack(args, 'rgb'); + var r = rgb[0], + b = rgb[2]; + var minTemp = 1000; + var maxTemp = 40000; + var eps = 0.4; + var temp; + while (maxTemp - minTemp > eps) { + temp = (maxTemp + minTemp) * 0.5; + var rgb$1 = temperature2rgb(temp); + if (rgb$1[2] / rgb$1[0] >= b / r) { + maxTemp = temp; + } else { + minTemp = temp; + } + } + return round(temp); + }; + + Color.prototype.temp = + Color.prototype.kelvin = + Color.prototype.temperature = + function () { + return rgb2temperature(this._rgb); + }; + + var temp = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args, ['temp']) )); + }; + Object.assign(chroma, { temp: temp, kelvin: temp, temperature: temp }); + + input.format.temp = + input.format.kelvin = + input.format.temperature = + temperature2rgb; + + Color.prototype.oklab = function () { + return rgb2oklab(this._rgb); + }; + + var oklab$1 = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args, ['oklab']) )); + }; + Object.assign(chroma, { oklab: oklab$1 }); + + input.format.oklab = oklab2rgb; + + input.autodetect.push({ + p: 2, + test: function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, 'oklab'); + if (type(args) === 'array' && args.length === 3) { + return 'oklab'; + } + } + }); + + Color.prototype.oklch = function () { + return rgb2oklch(this._rgb); + }; + + var oklch$1 = function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + return new (Function.prototype.bind.apply( Color, [ null ].concat( args, ['oklch']) )); + }; + Object.assign(chroma, { oklch: oklch$1 }); + + input.format.oklch = oklch2rgb; + + input.autodetect.push({ + p: 2, + test: function () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + args = unpack(args, 'oklch'); + if (type(args) === 'array' && args.length === 3) { + return 'oklch'; + } + } + }); + + /** + X11 color names + + http://www.w3.org/TR/css3-color/#svg-color + */ + + var w3cx11 = { + aliceblue: '#f0f8ff', + antiquewhite: '#faebd7', + aqua: '#00ffff', + aquamarine: '#7fffd4', + azure: '#f0ffff', + beige: '#f5f5dc', + bisque: '#ffe4c4', + black: '#000000', + blanchedalmond: '#ffebcd', + blue: '#0000ff', + blueviolet: '#8a2be2', + brown: '#a52a2a', + burlywood: '#deb887', + cadetblue: '#5f9ea0', + chartreuse: '#7fff00', + chocolate: '#d2691e', + coral: '#ff7f50', + cornflowerblue: '#6495ed', + cornsilk: '#fff8dc', + crimson: '#dc143c', + cyan: '#00ffff', + darkblue: '#00008b', + darkcyan: '#008b8b', + darkgoldenrod: '#b8860b', + darkgray: '#a9a9a9', + darkgreen: '#006400', + darkgrey: '#a9a9a9', + darkkhaki: '#bdb76b', + darkmagenta: '#8b008b', + darkolivegreen: '#556b2f', + darkorange: '#ff8c00', + darkorchid: '#9932cc', + darkred: '#8b0000', + darksalmon: '#e9967a', + darkseagreen: '#8fbc8f', + darkslateblue: '#483d8b', + darkslategray: '#2f4f4f', + darkslategrey: '#2f4f4f', + darkturquoise: '#00ced1', + darkviolet: '#9400d3', + deeppink: '#ff1493', + deepskyblue: '#00bfff', + dimgray: '#696969', + dimgrey: '#696969', + dodgerblue: '#1e90ff', + firebrick: '#b22222', + floralwhite: '#fffaf0', + forestgreen: '#228b22', + fuchsia: '#ff00ff', + gainsboro: '#dcdcdc', + ghostwhite: '#f8f8ff', + gold: '#ffd700', + goldenrod: '#daa520', + gray: '#808080', + green: '#008000', + greenyellow: '#adff2f', + grey: '#808080', + honeydew: '#f0fff0', + hotpink: '#ff69b4', + indianred: '#cd5c5c', + indigo: '#4b0082', + ivory: '#fffff0', + khaki: '#f0e68c', + laserlemon: '#ffff54', + lavender: '#e6e6fa', + lavenderblush: '#fff0f5', + lawngreen: '#7cfc00', + lemonchiffon: '#fffacd', + lightblue: '#add8e6', + lightcoral: '#f08080', + lightcyan: '#e0ffff', + lightgoldenrod: '#fafad2', + lightgoldenrodyellow: '#fafad2', + lightgray: '#d3d3d3', + lightgreen: '#90ee90', + lightgrey: '#d3d3d3', + lightpink: '#ffb6c1', + lightsalmon: '#ffa07a', + lightseagreen: '#20b2aa', + lightskyblue: '#87cefa', + lightslategray: '#778899', + lightslategrey: '#778899', + lightsteelblue: '#b0c4de', + lightyellow: '#ffffe0', + lime: '#00ff00', + limegreen: '#32cd32', + linen: '#faf0e6', + magenta: '#ff00ff', + maroon: '#800000', + maroon2: '#7f0000', + maroon3: '#b03060', + mediumaquamarine: '#66cdaa', + mediumblue: '#0000cd', + mediumorchid: '#ba55d3', + mediumpurple: '#9370db', + mediumseagreen: '#3cb371', + mediumslateblue: '#7b68ee', + mediumspringgreen: '#00fa9a', + mediumturquoise: '#48d1cc', + mediumvioletred: '#c71585', + midnightblue: '#191970', + mintcream: '#f5fffa', + mistyrose: '#ffe4e1', + moccasin: '#ffe4b5', + navajowhite: '#ffdead', + navy: '#000080', + oldlace: '#fdf5e6', + olive: '#808000', + olivedrab: '#6b8e23', + orange: '#ffa500', + orangered: '#ff4500', + orchid: '#da70d6', + palegoldenrod: '#eee8aa', + palegreen: '#98fb98', + paleturquoise: '#afeeee', + palevioletred: '#db7093', + papayawhip: '#ffefd5', + peachpuff: '#ffdab9', + peru: '#cd853f', + pink: '#ffc0cb', + plum: '#dda0dd', + powderblue: '#b0e0e6', + purple: '#800080', + purple2: '#7f007f', + purple3: '#a020f0', + rebeccapurple: '#663399', + red: '#ff0000', + rosybrown: '#bc8f8f', + royalblue: '#4169e1', + saddlebrown: '#8b4513', + salmon: '#fa8072', + sandybrown: '#f4a460', + seagreen: '#2e8b57', + seashell: '#fff5ee', + sienna: '#a0522d', + silver: '#c0c0c0', + skyblue: '#87ceeb', + slateblue: '#6a5acd', + slategray: '#708090', + slategrey: '#708090', + snow: '#fffafa', + springgreen: '#00ff7f', + steelblue: '#4682b4', + tan: '#d2b48c', + teal: '#008080', + thistle: '#d8bfd8', + tomato: '#ff6347', + turquoise: '#40e0d0', + violet: '#ee82ee', + wheat: '#f5deb3', + white: '#ffffff', + whitesmoke: '#f5f5f5', + yellow: '#ffff00', + yellowgreen: '#9acd32' + }; + + Color.prototype.name = function () { + var hex = rgb2hex(this._rgb, 'rgb'); + for (var i = 0, list = Object.keys(w3cx11); i < list.length; i += 1) { + var n = list[i]; + + if (w3cx11[n] === hex) { return n.toLowerCase(); } + } + return hex; + }; + + input.format.named = function (name) { + name = name.toLowerCase(); + if (w3cx11[name]) { return hex2rgb(w3cx11[name]); } + throw new Error('unknown color name: ' + name); + }; + + input.autodetect.push({ + p: 5, + test: function (h) { + var rest = [], len = arguments.length - 1; + while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ]; + + if (!rest.length && type(h) === 'string' && w3cx11[h.toLowerCase()]) { + return 'named'; + } + } + }); + + Color.prototype.alpha = function (a, mutate) { + if ( mutate === void 0 ) mutate = false; + + if (a !== undefined && type(a) === 'number') { + if (mutate) { + this._rgb[3] = a; + return this; + } + return new Color([this._rgb[0], this._rgb[1], this._rgb[2], a], 'rgb'); + } + return this._rgb[3]; + }; + + Color.prototype.clipped = function () { + return this._rgb._clipped || false; + }; + + Color.prototype.darken = function (amount) { + if ( amount === void 0 ) amount = 1; + + var me = this; + var lab = me.lab(); + lab[0] -= labConstants.Kn * amount; + return new Color(lab, 'lab').alpha(me.alpha(), true); + }; + + Color.prototype.brighten = function (amount) { + if ( amount === void 0 ) amount = 1; + + return this.darken(-amount); + }; + + Color.prototype.darker = Color.prototype.darken; + Color.prototype.brighter = Color.prototype.brighten; + + Color.prototype.get = function (mc) { + var ref = mc.split('.'); + var mode = ref[0]; + var channel = ref[1]; + var src = this[mode](); + if (channel) { + var i = mode.indexOf(channel) - (mode.substr(0, 2) === 'ok' ? 2 : 0); + if (i > -1) { return src[i]; } + throw new Error(("unknown channel " + channel + " in mode " + mode)); + } else { + return src; + } + }; + + var pow$6 = Math.pow; + + var EPS = 1e-7; + var MAX_ITER = 20; + + Color.prototype.luminance = function (lum, mode) { + if ( mode === void 0 ) mode = 'rgb'; + + if (lum !== undefined && type(lum) === 'number') { + if (lum === 0) { + // return pure black + return new Color([0, 0, 0, this._rgb[3]], 'rgb'); + } + if (lum === 1) { + // return pure white + return new Color([255, 255, 255, this._rgb[3]], 'rgb'); + } + // compute new color using... + var cur_lum = this.luminance(); + var max_iter = MAX_ITER; + + var test = function (low, high) { + var mid = low.interpolate(high, 0.5, mode); + var lm = mid.luminance(); + if (Math.abs(lum - lm) < EPS || !max_iter--) { + // close enough + return mid; + } + return lm > lum ? test(low, mid) : test(mid, high); + }; + + var rgb = ( + cur_lum > lum + ? test(new Color([0, 0, 0]), this) + : test(this, new Color([255, 255, 255])) + ).rgb(); + return new Color(rgb.concat( [this._rgb[3]])); + } + return rgb2luminance.apply(void 0, this._rgb.slice(0, 3)); + }; + + var rgb2luminance = function (r, g, b) { + // relative luminance + // see http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef + r = luminance_x(r); + g = luminance_x(g); + b = luminance_x(b); + return 0.2126 * r + 0.7152 * g + 0.0722 * b; + }; + + var luminance_x = function (x) { + x /= 255; + return x <= 0.03928 ? x / 12.92 : pow$6((x + 0.055) / 1.055, 2.4); + }; + + var index = {}; + + function mix (col1, col2, f) { + if ( f === void 0 ) f = 0.5; + var rest = [], len = arguments.length - 3; + while ( len-- > 0 ) rest[ len ] = arguments[ len + 3 ]; + + var mode = rest[0] || 'lrgb'; + if (!index[mode] && !rest.length) { + // fall back to the first supported mode + mode = Object.keys(index)[0]; + } + if (!index[mode]) { + throw new Error(("interpolation mode " + mode + " is not defined")); + } + if (type(col1) !== 'object') { col1 = new Color(col1); } + if (type(col2) !== 'object') { col2 = new Color(col2); } + return index[mode](col1, col2, f).alpha( + col1.alpha() + f * (col2.alpha() - col1.alpha()) + ); + } + + Color.prototype.mix = Color.prototype.interpolate = function ( + col2, + f + ) { + if ( f === void 0 ) f = 0.5; + var rest = [], len = arguments.length - 2; + while ( len-- > 0 ) rest[ len ] = arguments[ len + 2 ]; + + return mix.apply(void 0, [ this, col2, f ].concat( rest )); + }; + + Color.prototype.premultiply = function (mutate) { + if ( mutate === void 0 ) mutate = false; + + var rgb = this._rgb; + var a = rgb[3]; + if (mutate) { + this._rgb = [rgb[0] * a, rgb[1] * a, rgb[2] * a, a]; + return this; + } else { + return new Color([rgb[0] * a, rgb[1] * a, rgb[2] * a, a], 'rgb'); + } + }; + + Color.prototype.saturate = function (amount) { + if ( amount === void 0 ) amount = 1; + + var me = this; + var lch = me.lch(); + lch[1] += labConstants.Kn * amount; + if (lch[1] < 0) { lch[1] = 0; } + return new Color(lch, 'lch').alpha(me.alpha(), true); + }; + + Color.prototype.desaturate = function (amount) { + if ( amount === void 0 ) amount = 1; + + return this.saturate(-amount); + }; + + Color.prototype.set = function (mc, value, mutate) { + if ( mutate === void 0 ) mutate = false; + + var ref = mc.split('.'); + var mode = ref[0]; + var channel = ref[1]; + var src = this[mode](); + if (channel) { + var i = mode.indexOf(channel) - (mode.substr(0, 2) === 'ok' ? 2 : 0); + if (i > -1) { + if (type(value) == 'string') { + switch (value.charAt(0)) { + case '+': + src[i] += +value; + break; + case '-': + src[i] += +value; + break; + case '*': + src[i] *= +value.substr(1); + break; + case '/': + src[i] /= +value.substr(1); + break; + default: + src[i] = +value; + } + } else if (type(value) === 'number') { + src[i] = value; + } else { + throw new Error("unsupported value for Color.set"); + } + var out = new Color(src, mode); + if (mutate) { + this._rgb = out._rgb; + return this; + } + return out; + } + throw new Error(("unknown channel " + channel + " in mode " + mode)); + } else { + return src; + } + }; + + Color.prototype.tint = function (f) { + if ( f === void 0 ) f = 0.5; + var rest = [], len = arguments.length - 1; + while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ]; + + return mix.apply(void 0, [ this, 'white', f ].concat( rest )); + }; + + Color.prototype.shade = function (f) { + if ( f === void 0 ) f = 0.5; + var rest = [], len = arguments.length - 1; + while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ]; + + return mix.apply(void 0, [ this, 'black', f ].concat( rest )); + }; + + var rgb = function (col1, col2, f) { + var xyz0 = col1._rgb; + var xyz1 = col2._rgb; + return new Color( + xyz0[0] + f * (xyz1[0] - xyz0[0]), + xyz0[1] + f * (xyz1[1] - xyz0[1]), + xyz0[2] + f * (xyz1[2] - xyz0[2]), + 'rgb' + ); + }; + + // register interpolator + index.rgb = rgb; + + var sqrt$2 = Math.sqrt; + var pow$5 = Math.pow; + + var lrgb = function (col1, col2, f) { + var ref = col1._rgb; + var x1 = ref[0]; + var y1 = ref[1]; + var z1 = ref[2]; + var ref$1 = col2._rgb; + var x2 = ref$1[0]; + var y2 = ref$1[1]; + var z2 = ref$1[2]; + return new Color( + sqrt$2(pow$5(x1, 2) * (1 - f) + pow$5(x2, 2) * f), + sqrt$2(pow$5(y1, 2) * (1 - f) + pow$5(y2, 2) * f), + sqrt$2(pow$5(z1, 2) * (1 - f) + pow$5(z2, 2) * f), + 'rgb' + ); + }; + + // register interpolator + index.lrgb = lrgb; + + var lab = function (col1, col2, f) { + var xyz0 = col1.lab(); + var xyz1 = col2.lab(); + return new Color( + xyz0[0] + f * (xyz1[0] - xyz0[0]), + xyz0[1] + f * (xyz1[1] - xyz0[1]), + xyz0[2] + f * (xyz1[2] - xyz0[2]), + 'lab' + ); + }; + + // register interpolator + index.lab = lab; + + function interpolate_hsx (col1, col2, f, m) { + var assign, assign$1; + + var xyz0, xyz1; + if (m === 'hsl') { + xyz0 = col1.hsl(); + xyz1 = col2.hsl(); + } else if (m === 'hsv') { + xyz0 = col1.hsv(); + xyz1 = col2.hsv(); + } else if (m === 'hcg') { + xyz0 = col1.hcg(); + xyz1 = col2.hcg(); + } else if (m === 'hsi') { + xyz0 = col1.hsi(); + xyz1 = col2.hsi(); + } else if (m === 'lch' || m === 'hcl') { + m = 'hcl'; + xyz0 = col1.hcl(); + xyz1 = col2.hcl(); + } else if (m === 'oklch') { + xyz0 = col1.oklch().reverse(); + xyz1 = col2.oklch().reverse(); + } + + var hue0, hue1, sat0, sat1, lbv0, lbv1; + if (m.substr(0, 1) === 'h' || m === 'oklch') { + (assign = xyz0, hue0 = assign[0], sat0 = assign[1], lbv0 = assign[2]); + (assign$1 = xyz1, hue1 = assign$1[0], sat1 = assign$1[1], lbv1 = assign$1[2]); + } + + var sat, hue, lbv, dh; + + if (!isNaN(hue0) && !isNaN(hue1)) { + // both colors have hue + if (hue1 > hue0 && hue1 - hue0 > 180) { + dh = hue1 - (hue0 + 360); + } else if (hue1 < hue0 && hue0 - hue1 > 180) { + dh = hue1 + 360 - hue0; + } else { + dh = hue1 - hue0; + } + hue = hue0 + f * dh; + } else if (!isNaN(hue0)) { + hue = hue0; + if ((lbv1 == 1 || lbv1 == 0) && m != 'hsv') { sat = sat0; } + } else if (!isNaN(hue1)) { + hue = hue1; + if ((lbv0 == 1 || lbv0 == 0) && m != 'hsv') { sat = sat1; } + } else { + hue = Number.NaN; + } + + if (sat === undefined) { sat = sat0 + f * (sat1 - sat0); } + lbv = lbv0 + f * (lbv1 - lbv0); + return m === 'oklch' + ? new Color([lbv, sat, hue], m) + : new Color([hue, sat, lbv], m); + } + + var lch = function (col1, col2, f) { + return interpolate_hsx(col1, col2, f, 'lch'); + }; + + // register interpolator + index.lch = lch; + index.hcl = lch; + + var num = function (col1, col2, f) { + var c1 = col1.num(); + var c2 = col2.num(); + return new Color(c1 + f * (c2 - c1), 'num'); + }; + + // register interpolator + index.num = num; + + var hcg = function (col1, col2, f) { + return interpolate_hsx(col1, col2, f, 'hcg'); + }; + + // register interpolator + index.hcg = hcg; + + var hsi = function (col1, col2, f) { + return interpolate_hsx(col1, col2, f, 'hsi'); + }; + + // register interpolator + index.hsi = hsi; + + var hsl = function (col1, col2, f) { + return interpolate_hsx(col1, col2, f, 'hsl'); + }; + + // register interpolator + index.hsl = hsl; + + var hsv = function (col1, col2, f) { + return interpolate_hsx(col1, col2, f, 'hsv'); + }; + + // register interpolator + index.hsv = hsv; + + var oklab = function (col1, col2, f) { + var xyz0 = col1.oklab(); + var xyz1 = col2.oklab(); + return new Color( + xyz0[0] + f * (xyz1[0] - xyz0[0]), + xyz0[1] + f * (xyz1[1] - xyz0[1]), + xyz0[2] + f * (xyz1[2] - xyz0[2]), + 'oklab' + ); + }; + + // register interpolator + index.oklab = oklab; + + var oklch = function (col1, col2, f) { + return interpolate_hsx(col1, col2, f, 'oklch'); + }; + + // register interpolator + index.oklch = oklch; + + var pow$4 = Math.pow; + var sqrt$1 = Math.sqrt; + var PI$1 = Math.PI; + var cos$2 = Math.cos; + var sin$2 = Math.sin; + var atan2$1 = Math.atan2; + + function average (colors, mode, weights) { + if ( mode === void 0 ) mode = 'lrgb'; + if ( weights === void 0 ) weights = null; + + var l = colors.length; + if (!weights) { weights = Array.from(new Array(l)).map(function () { return 1; }); } + // normalize weights + var k = + l / + weights.reduce(function (a, b) { + return a + b; + }); + weights.forEach(function (w, i) { + weights[i] *= k; + }); + // convert colors to Color objects + colors = colors.map(function (c) { return new Color(c); }); + if (mode === 'lrgb') { + return _average_lrgb(colors, weights); + } + var first = colors.shift(); + var xyz = first.get(mode); + var cnt = []; + var dx = 0; + var dy = 0; + // initial color + for (var i = 0; i < xyz.length; i++) { + xyz[i] = (xyz[i] || 0) * weights[0]; + cnt.push(isNaN(xyz[i]) ? 0 : weights[0]); + if (mode.charAt(i) === 'h' && !isNaN(xyz[i])) { + var A = (xyz[i] / 180) * PI$1; + dx += cos$2(A) * weights[0]; + dy += sin$2(A) * weights[0]; + } + } + + var alpha = first.alpha() * weights[0]; + colors.forEach(function (c, ci) { + var xyz2 = c.get(mode); + alpha += c.alpha() * weights[ci + 1]; + for (var i = 0; i < xyz.length; i++) { + if (!isNaN(xyz2[i])) { + cnt[i] += weights[ci + 1]; + if (mode.charAt(i) === 'h') { + var A = (xyz2[i] / 180) * PI$1; + dx += cos$2(A) * weights[ci + 1]; + dy += sin$2(A) * weights[ci + 1]; + } else { + xyz[i] += xyz2[i] * weights[ci + 1]; + } + } + } + }); + + for (var i$1 = 0; i$1 < xyz.length; i$1++) { + if (mode.charAt(i$1) === 'h') { + var A$1 = (atan2$1(dy / cnt[i$1], dx / cnt[i$1]) / PI$1) * 180; + while (A$1 < 0) { A$1 += 360; } + while (A$1 >= 360) { A$1 -= 360; } + xyz[i$1] = A$1; + } else { + xyz[i$1] = xyz[i$1] / cnt[i$1]; + } + } + alpha /= l; + return new Color(xyz, mode).alpha(alpha > 0.99999 ? 1 : alpha, true); + } + var _average_lrgb = function (colors, weights) { + var l = colors.length; + var xyz = [0, 0, 0, 0]; + for (var i = 0; i < colors.length; i++) { + var col = colors[i]; + var f = weights[i] / l; + var rgb = col._rgb; + xyz[0] += pow$4(rgb[0], 2) * f; + xyz[1] += pow$4(rgb[1], 2) * f; + xyz[2] += pow$4(rgb[2], 2) * f; + xyz[3] += rgb[3] * f; + } + xyz[0] = sqrt$1(xyz[0]); + xyz[1] = sqrt$1(xyz[1]); + xyz[2] = sqrt$1(xyz[2]); + if (xyz[3] > 0.9999999) { xyz[3] = 1; } + return new Color(clip_rgb(xyz)); + }; + + // minimal multi-purpose interface + + + var pow$3 = Math.pow; + + function scale (colors) { + // constructor + var _mode = 'rgb'; + var _nacol = chroma('#ccc'); + var _spread = 0; + // const _fixed = false; + var _positions = [0, 1]; + var _domain = [0, 1]; + var _pos = []; + var _padding = [0, 0]; + var _classes = false; + var _colors = []; + var _out = false; + var _min = 0; + var _max = 1; + var _correctLightness = false; + var _colorCache = {}; + var _useCache = true; + var _gamma = 1; + + // private methods + + var setColors = function (colors) { + colors = colors || ['#fff', '#000']; + if ( + colors && + type(colors) === 'string' && + chroma.brewer && + chroma.brewer[colors.toLowerCase()] + ) { + colors = chroma.brewer[colors.toLowerCase()]; + } + if (type(colors) === 'array') { + // handle single color + if (colors.length === 1) { + colors = [colors[0], colors[0]]; + } + // make a copy of the colors + colors = colors.slice(0); + // convert to chroma classes + for (var c = 0; c < colors.length; c++) { + colors[c] = chroma(colors[c]); + } + // auto-fill color position + _pos.length = 0; + for (var c$1 = 0; c$1 < colors.length; c$1++) { + _pos.push(c$1 / (colors.length - 1)); + } + } + resetCache(); + return (_colors = colors); + }; + + var getClass = function (value) { + if (_classes != null) { + var n = _classes.length - 1; + var i = 0; + while (i < n && value >= _classes[i]) { + i++; + } + return i - 1; + } + return 0; + }; + + var tMapLightness = function (t) { return t; }; + var tMapDomain = function (t) { return t; }; + + // const classifyValue = function(value) { + // let val = value; + // if (_classes.length > 2) { + // const n = _classes.length-1; + // const i = getClass(value); + // const minc = _classes[0] + ((_classes[1]-_classes[0]) * (0 + (_spread * 0.5))); // center of 1st class + // const maxc = _classes[n-1] + ((_classes[n]-_classes[n-1]) * (1 - (_spread * 0.5))); // center of last class + // val = _min + ((((_classes[i] + ((_classes[i+1] - _classes[i]) * 0.5)) - minc) / (maxc-minc)) * (_max - _min)); + // } + // return val; + // }; + + var getColor = function (val, bypassMap) { + var col, t; + if (bypassMap == null) { + bypassMap = false; + } + if (isNaN(val) || val === null) { + return _nacol; + } + if (!bypassMap) { + if (_classes && _classes.length > 2) { + // find the class + var c = getClass(val); + t = c / (_classes.length - 2); + } else if (_max !== _min) { + // just interpolate between min/max + t = (val - _min) / (_max - _min); + } else { + t = 1; + } + } else { + t = val; + } + + // domain map + t = tMapDomain(t); + + if (!bypassMap) { + t = tMapLightness(t); // lightness correction + } + + if (_gamma !== 1) { + t = pow$3(t, _gamma); + } + + t = _padding[0] + t * (1 - _padding[0] - _padding[1]); + + t = limit(t, 0, 1); + + var k = Math.floor(t * 10000); + + if (_useCache && _colorCache[k]) { + col = _colorCache[k]; + } else { + if (type(_colors) === 'array') { + //for i in [0.._pos.length-1] + for (var i = 0; i < _pos.length; i++) { + var p = _pos[i]; + if (t <= p) { + col = _colors[i]; + break; + } + if (t >= p && i === _pos.length - 1) { + col = _colors[i]; + break; + } + if (t > p && t < _pos[i + 1]) { + t = (t - p) / (_pos[i + 1] - p); + col = chroma.interpolate( + _colors[i], + _colors[i + 1], + t, + _mode + ); + break; + } + } + } else if (type(_colors) === 'function') { + col = _colors(t); + } + if (_useCache) { + _colorCache[k] = col; + } + } + return col; + }; + + var resetCache = function () { return (_colorCache = {}); }; + + setColors(colors); + + // public interface + + var f = function (v) { + var c = chroma(getColor(v)); + if (_out && c[_out]) { + return c[_out](); + } else { + return c; + } + }; + + f.classes = function (classes) { + if (classes != null) { + if (type(classes) === 'array') { + _classes = classes; + _positions = [classes[0], classes[classes.length - 1]]; + } else { + var d = chroma.analyze(_positions); + if (classes === 0) { + _classes = [d.min, d.max]; + } else { + _classes = chroma.limits(d, 'e', classes); + } + } + return f; + } + return _classes; + }; + + f.domain = function (domain) { + if (!arguments.length) { + // return original domain + return _domain; + } + // store original domain so we can return it later + _domain = domain.slice(0); + _min = domain[0]; + _max = domain[domain.length - 1]; + _pos = []; + var k = _colors.length; + if (domain.length === k && _min !== _max) { + // update positions + for (var i = 0, list = Array.from(domain); i < list.length; i += 1) { + var d = list[i]; + + _pos.push((d - _min) / (_max - _min)); + } + } else { + for (var c = 0; c < k; c++) { + _pos.push(c / (k - 1)); + } + if (domain.length > 2) { + // set domain map + var tOut = domain.map(function (d, i) { return i / (domain.length - 1); }); + var tBreaks = domain.map(function (d) { return (d - _min) / (_max - _min); }); + if (!tBreaks.every(function (val, i) { return tOut[i] === val; })) { + tMapDomain = function (t) { + if (t <= 0 || t >= 1) { return t; } + var i = 0; + while (t >= tBreaks[i + 1]) { i++; } + var f = + (t - tBreaks[i]) / (tBreaks[i + 1] - tBreaks[i]); + var out = tOut[i] + f * (tOut[i + 1] - tOut[i]); + return out; + }; + } + } + } + _positions = [_min, _max]; + return f; + }; + + f.mode = function (_m) { + if (!arguments.length) { + return _mode; + } + _mode = _m; + resetCache(); + return f; + }; + + f.range = function (colors, _pos) { + setColors(colors); + return f; + }; + + f.out = function (_o) { + _out = _o; + return f; + }; + + f.spread = function (val) { + if (!arguments.length) { + return _spread; + } + _spread = val; + return f; + }; + + f.correctLightness = function (v) { + if (v == null) { + v = true; + } + _correctLightness = v; + resetCache(); + if (_correctLightness) { + tMapLightness = function (t) { + var L0 = getColor(0, true).lab()[0]; + var L1 = getColor(1, true).lab()[0]; + var pol = L0 > L1; + var L_actual = getColor(t, true).lab()[0]; + var L_ideal = L0 + (L1 - L0) * t; + var L_diff = L_actual - L_ideal; + var t0 = 0; + var t1 = 1; + var max_iter = 20; + while (Math.abs(L_diff) > 1e-2 && max_iter-- > 0) { + (function () { + if (pol) { + L_diff *= -1; + } + if (L_diff < 0) { + t0 = t; + t += (t1 - t) * 0.5; + } else { + t1 = t; + t += (t0 - t) * 0.5; + } + L_actual = getColor(t, true).lab()[0]; + return (L_diff = L_actual - L_ideal); + })(); + } + return t; + }; + } else { + tMapLightness = function (t) { return t; }; + } + return f; + }; + + f.padding = function (p) { + if (p != null) { + if (type(p) === 'number') { + p = [p, p]; + } + _padding = p; + return f; + } else { + return _padding; + } + }; + + f.colors = function (numColors, out) { + // If no arguments are given, return the original colors that were provided + if (arguments.length < 2) { + out = 'hex'; + } + var result = []; + + if (arguments.length === 0) { + result = _colors.slice(0); + } else if (numColors === 1) { + result = [f(0.5)]; + } else if (numColors > 1) { + var dm = _positions[0]; + var dd = _positions[1] - dm; + result = __range__(0, numColors).map(function (i) { return f(dm + (i / (numColors - 1)) * dd); } + ); + } else { + // returns all colors based on the defined classes + colors = []; + var samples = []; + if (_classes && _classes.length > 2) { + for ( + var i = 1, end = _classes.length, asc = 1 <= end; + asc ? i < end : i > end; + asc ? i++ : i-- + ) { + samples.push((_classes[i - 1] + _classes[i]) * 0.5); + } + } else { + samples = _positions; + } + result = samples.map(function (v) { return f(v); }); + } + + if (chroma[out]) { + result = result.map(function (c) { return c[out](); }); + } + return result; + }; + + f.cache = function (c) { + if (c != null) { + _useCache = c; + return f; + } else { + return _useCache; + } + }; + + f.gamma = function (g) { + if (g != null) { + _gamma = g; + return f; + } else { + return _gamma; + } + }; + + f.nodata = function (d) { + if (d != null) { + _nacol = chroma(d); + return f; + } else { + return _nacol; + } + }; + + return f; + } + + function __range__(left, right, inclusive) { + var range = []; + var ascending = left < right; + var end = right ; + for (var i = left; ascending ? i < end : i > end; ascending ? i++ : i--) { + range.push(i); + } + return range; + } + + // + // interpolates between a set of colors uzing a bezier spline + // + + + // nth row of the pascal triangle + var binom_row = function (n) { + var row = [1, 1]; + for (var i = 1; i < n; i++) { + var newrow = [1]; + for (var j = 1; j <= row.length; j++) { + newrow[j] = (row[j] || 0) + row[j - 1]; + } + row = newrow; + } + return row; + }; + + var bezier = function (colors) { + var assign, assign$1, assign$2; + + var I, lab0, lab1, lab2; + colors = colors.map(function (c) { return new Color(c); }); + if (colors.length === 2) { + // linear interpolation + (assign = colors.map(function (c) { return c.lab(); }), lab0 = assign[0], lab1 = assign[1]); + I = function (t) { + var lab = [0, 1, 2].map(function (i) { return lab0[i] + t * (lab1[i] - lab0[i]); }); + return new Color(lab, 'lab'); + }; + } else if (colors.length === 3) { + // quadratic bezier interpolation + (assign$1 = colors.map(function (c) { return c.lab(); }), lab0 = assign$1[0], lab1 = assign$1[1], lab2 = assign$1[2]); + I = function (t) { + var lab = [0, 1, 2].map( + function (i) { return (1 - t) * (1 - t) * lab0[i] + + 2 * (1 - t) * t * lab1[i] + + t * t * lab2[i]; } + ); + return new Color(lab, 'lab'); + }; + } else if (colors.length === 4) { + // cubic bezier interpolation + var lab3; + (assign$2 = colors.map(function (c) { return c.lab(); }), lab0 = assign$2[0], lab1 = assign$2[1], lab2 = assign$2[2], lab3 = assign$2[3]); + I = function (t) { + var lab = [0, 1, 2].map( + function (i) { return (1 - t) * (1 - t) * (1 - t) * lab0[i] + + 3 * (1 - t) * (1 - t) * t * lab1[i] + + 3 * (1 - t) * t * t * lab2[i] + + t * t * t * lab3[i]; } + ); + return new Color(lab, 'lab'); + }; + } else if (colors.length >= 5) { + // general case (degree n bezier) + var labs, row, n; + labs = colors.map(function (c) { return c.lab(); }); + n = colors.length - 1; + row = binom_row(n); + I = function (t) { + var u = 1 - t; + var lab = [0, 1, 2].map(function (i) { return labs.reduce( + function (sum, el, j) { return sum + row[j] * Math.pow( u, (n - j) ) * Math.pow( t, j ) * el[i]; }, + 0 + ); } + ); + return new Color(lab, 'lab'); + }; + } else { + throw new RangeError('No point in running bezier with only one color.'); + } + return I; + }; + + function bezier$1 (colors) { + var f = bezier(colors); + f.scale = function () { return scale(f); }; + return f; + } + + /* + * interpolates between a set of colors uzing a bezier spline + * blend mode formulas taken from https://web.archive.org/web/20180110014946/http://www.venture-ware.com/kevin/coding/lets-learn-math-photoshop-blend-modes/ + */ + + + var blend = function (bottom, top, mode) { + if (!blend[mode]) { + throw new Error('unknown blend mode ' + mode); + } + return blend[mode](bottom, top); + }; + + var blend_f = function (f) { return function (bottom, top) { + var c0 = chroma(top).rgb(); + var c1 = chroma(bottom).rgb(); + return chroma.rgb(f(c0, c1)); + }; }; + + var each = function (f) { return function (c0, c1) { + var out = []; + out[0] = f(c0[0], c1[0]); + out[1] = f(c0[1], c1[1]); + out[2] = f(c0[2], c1[2]); + return out; + }; }; + + var normal = function (a) { return a; }; + var multiply = function (a, b) { return (a * b) / 255; }; + var darken = function (a, b) { return (a > b ? b : a); }; + var lighten = function (a, b) { return (a > b ? a : b); }; + var screen = function (a, b) { return 255 * (1 - (1 - a / 255) * (1 - b / 255)); }; + var overlay = function (a, b) { return b < 128 ? (2 * a * b) / 255 : 255 * (1 - 2 * (1 - a / 255) * (1 - b / 255)); }; + var burn = function (a, b) { return 255 * (1 - (1 - b / 255) / (a / 255)); }; + var dodge = function (a, b) { + if (a === 255) { return 255; } + a = (255 * (b / 255)) / (1 - a / 255); + return a > 255 ? 255 : a; + }; + + // # add = (a,b) -> + // # if (a + b > 255) then 255 else a + b + + blend.normal = blend_f(each(normal)); + blend.multiply = blend_f(each(multiply)); + blend.screen = blend_f(each(screen)); + blend.overlay = blend_f(each(overlay)); + blend.darken = blend_f(each(darken)); + blend.lighten = blend_f(each(lighten)); + blend.dodge = blend_f(each(dodge)); + blend.burn = blend_f(each(burn)); + + // cubehelix interpolation + // based on D.A. Green "A colour scheme for the display of astronomical intensity images" + // http://astron-soc.in/bulletin/11June/289392011.pdf + var pow$2 = Math.pow; + var sin$1 = Math.sin; + var cos$1 = Math.cos; + + function cubehelix ( + start, + rotations, + hue, + gamma, + lightness + ) { + if ( start === void 0 ) start = 300; + if ( rotations === void 0 ) rotations = -1.5; + if ( hue === void 0 ) hue = 1; + if ( gamma === void 0 ) gamma = 1; + if ( lightness === void 0 ) lightness = [0, 1]; + + var dh = 0, + dl; + if (type(lightness) === 'array') { + dl = lightness[1] - lightness[0]; + } else { + dl = 0; + lightness = [lightness, lightness]; + } + var f = function (fract) { + var a = TWOPI * ((start + 120) / 360 + rotations * fract); + var l = pow$2(lightness[0] + dl * fract, gamma); + var h = dh !== 0 ? hue[0] + fract * dh : hue; + var amp = (h * l * (1 - l)) / 2; + var cos_a = cos$1(a); + var sin_a = sin$1(a); + var r = l + amp * (-0.14861 * cos_a + 1.78277 * sin_a); + var g = l + amp * (-0.29227 * cos_a - 0.90649 * sin_a); + var b = l + amp * (1.97294 * cos_a); + return chroma(clip_rgb([r * 255, g * 255, b * 255, 1])); + }; + f.start = function (s) { + if (s == null) { + return start; + } + start = s; + return f; + }; + f.rotations = function (r) { + if (r == null) { + return rotations; + } + rotations = r; + return f; + }; + f.gamma = function (g) { + if (g == null) { + return gamma; + } + gamma = g; + return f; + }; + f.hue = function (h) { + if (h == null) { + return hue; + } + hue = h; + if (type(hue) === 'array') { + dh = hue[1] - hue[0]; + if (dh === 0) { + hue = hue[1]; + } + } else { + dh = 0; + } + return f; + }; + f.lightness = function (h) { + if (h == null) { + return lightness; + } + if (type(h) === 'array') { + lightness = h; + dl = h[1] - h[0]; + } else { + lightness = [h, h]; + dl = 0; + } + return f; + }; + f.scale = function () { return chroma.scale(f); }; + f.hue(hue); + return f; + } + + var digits = '0123456789abcdef'; + + var floor$1 = Math.floor; + var random = Math.random; + + /** + * Generates a random color. + * @param {() => number} rng - A random number generator function. + */ + function random$1 (rng) { + if ( rng === void 0 ) rng = random; + + var code = '#'; + for (var i = 0; i < 6; i++) { + code += digits.charAt(floor$1(rng() * 16)); + } + return new Color(code, 'hex'); + } + + var log = Math.log; + var pow$1 = Math.pow; + var floor = Math.floor; + var abs$1 = Math.abs; + + function analyze(data, key) { + if ( key === void 0 ) key = null; + + var r = { + min: Number.MAX_VALUE, + max: Number.MAX_VALUE * -1, + sum: 0, + values: [], + count: 0 + }; + if (type(data) === 'object') { + data = Object.values(data); + } + data.forEach(function (val) { + if (key && type(val) === 'object') { val = val[key]; } + if (val !== undefined && val !== null && !isNaN(val)) { + r.values.push(val); + r.sum += val; + if (val < r.min) { r.min = val; } + if (val > r.max) { r.max = val; } + r.count += 1; + } + }); + + r.domain = [r.min, r.max]; + + r.limits = function (mode, num) { return limits(r, mode, num); }; + + return r; + } + + function limits(data, mode, num) { + if ( mode === void 0 ) mode = 'equal'; + if ( num === void 0 ) num = 7; + + if (type(data) == 'array') { + data = analyze(data); + } + var min = data.min; + var max = data.max; + var values = data.values.sort(function (a, b) { return a - b; }); + + if (num === 1) { + return [min, max]; + } + + var limits = []; + + if (mode.substr(0, 1) === 'c') { + // continuous + limits.push(min); + limits.push(max); + } + + if (mode.substr(0, 1) === 'e') { + // equal interval + limits.push(min); + for (var i = 1; i < num; i++) { + limits.push(min + (i / num) * (max - min)); + } + limits.push(max); + } else if (mode.substr(0, 1) === 'l') { + // log scale + if (min <= 0) { + throw new Error( + 'Logarithmic scales are only possible for values > 0' + ); + } + var min_log = Math.LOG10E * log(min); + var max_log = Math.LOG10E * log(max); + limits.push(min); + for (var i$1 = 1; i$1 < num; i$1++) { + limits.push(pow$1(10, min_log + (i$1 / num) * (max_log - min_log))); + } + limits.push(max); + } else if (mode.substr(0, 1) === 'q') { + // quantile scale + limits.push(min); + for (var i$2 = 1; i$2 < num; i$2++) { + var p = ((values.length - 1) * i$2) / num; + var pb = floor(p); + if (pb === p) { + limits.push(values[pb]); + } else { + // p > pb + var pr = p - pb; + limits.push(values[pb] * (1 - pr) + values[pb + 1] * pr); + } + } + limits.push(max); + } else if (mode.substr(0, 1) === 'k') { + // k-means clustering + /* + implementation based on + http://code.google.com/p/figue/source/browse/trunk/figue.js#336 + simplified for 1-d input values + */ + var cluster; + var n = values.length; + var assignments = new Array(n); + var clusterSizes = new Array(num); + var repeat = true; + var nb_iters = 0; + var centroids = null; + + // get seed values + centroids = []; + centroids.push(min); + for (var i$3 = 1; i$3 < num; i$3++) { + centroids.push(min + (i$3 / num) * (max - min)); + } + centroids.push(max); + + while (repeat) { + // assignment step + for (var j = 0; j < num; j++) { + clusterSizes[j] = 0; + } + for (var i$4 = 0; i$4 < n; i$4++) { + var value = values[i$4]; + var mindist = Number.MAX_VALUE; + var best = (void 0); + for (var j$1 = 0; j$1 < num; j$1++) { + var dist = abs$1(centroids[j$1] - value); + if (dist < mindist) { + mindist = dist; + best = j$1; + } + clusterSizes[best]++; + assignments[i$4] = best; + } + } + + // update centroids step + var newCentroids = new Array(num); + for (var j$2 = 0; j$2 < num; j$2++) { + newCentroids[j$2] = null; + } + for (var i$5 = 0; i$5 < n; i$5++) { + cluster = assignments[i$5]; + if (newCentroids[cluster] === null) { + newCentroids[cluster] = values[i$5]; + } else { + newCentroids[cluster] += values[i$5]; + } + } + for (var j$3 = 0; j$3 < num; j$3++) { + newCentroids[j$3] *= 1 / clusterSizes[j$3]; + } + + // check convergence + repeat = false; + for (var j$4 = 0; j$4 < num; j$4++) { + if (newCentroids[j$4] !== centroids[j$4]) { + repeat = true; + break; + } + } + + centroids = newCentroids; + nb_iters++; + + if (nb_iters > 200) { + repeat = false; + } + } + + // finished k-means clustering + // the next part is borrowed from gabrielflor.it + var kClusters = {}; + for (var j$5 = 0; j$5 < num; j$5++) { + kClusters[j$5] = []; + } + for (var i$6 = 0; i$6 < n; i$6++) { + cluster = assignments[i$6]; + kClusters[cluster].push(values[i$6]); + } + var tmpKMeansBreaks = []; + for (var j$6 = 0; j$6 < num; j$6++) { + tmpKMeansBreaks.push(kClusters[j$6][0]); + tmpKMeansBreaks.push(kClusters[j$6][kClusters[j$6].length - 1]); + } + tmpKMeansBreaks = tmpKMeansBreaks.sort(function (a, b) { return a - b; }); + limits.push(tmpKMeansBreaks[0]); + for (var i$7 = 1; i$7 < tmpKMeansBreaks.length; i$7 += 2) { + var v = tmpKMeansBreaks[i$7]; + if (!isNaN(v) && limits.indexOf(v) === -1) { + limits.push(v); + } + } + } + return limits; + } + + function contrast (a, b) { + // WCAG contrast ratio + // see http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef + a = new Color(a); + b = new Color(b); + var l1 = a.luminance(); + var l2 = b.luminance(); + return l1 > l2 ? (l1 + 0.05) / (l2 + 0.05) : (l2 + 0.05) / (l1 + 0.05); + } + + /** + * @license + * + * The APCA contrast prediction algorithm is based of the formulas published + * in the APCA-1.0.98G specification by Myndex. The specification is available at: + * https://raw.githubusercontent.com/Myndex/apca-w3/master/images/APCAw3_0.1.17_APCA0.0.98G.svg + * + * Note that the APCA implementation is still beta, so please update to + * future versions of chroma.js when they become available. + * + * You can read more about the APCA Readability Criterion at + * https://readtech.org/ARC/ + */ + + // constants + var W_offset = 0.027; + var P_in = 0.0005; + var P_out = 0.1; + var R_scale = 1.14; + var B_threshold = 0.022; + var B_exp = 1.414; + + function contrastAPCA (text, bg) { + // parse input colors + text = new Color(text); + bg = new Color(bg); + // if text color has alpha, blend against background + if (text.alpha() < 1) { + text = mix(bg, text, text.alpha(), 'rgb'); + } + var l_text = lum.apply(void 0, text.rgb()); + var l_bg = lum.apply(void 0, bg.rgb()); + + // soft clamp black levels + var Y_text = + l_text >= B_threshold + ? l_text + : l_text + Math.pow(B_threshold - l_text, B_exp); + var Y_bg = + l_bg >= B_threshold ? l_bg : l_bg + Math.pow(B_threshold - l_bg, B_exp); + + // normal polarity (dark text on light background) + var S_norm = Math.pow(Y_bg, 0.56) - Math.pow(Y_text, 0.57); + // reverse polarity (light text on dark background) + var S_rev = Math.pow(Y_bg, 0.65) - Math.pow(Y_text, 0.62); + // clamp noise then scale + var C = + Math.abs(Y_bg - Y_text) < P_in + ? 0 + : Y_text < Y_bg + ? S_norm * R_scale + : S_rev * R_scale; + // clamp minimum contrast then offset + var S_apc = Math.abs(C) < P_out ? 0 : C > 0 ? C - W_offset : C + W_offset; + // scale to 100 + return S_apc * 100; + } + function lum(r, g, b) { + return ( + 0.2126729 * Math.pow(r / 255, 2.4) + + 0.7151522 * Math.pow(g / 255, 2.4) + + 0.072175 * Math.pow(b / 255, 2.4) + ); + } + + var sqrt = Math.sqrt; + var pow = Math.pow; + var min = Math.min; + var max = Math.max; + var atan2 = Math.atan2; + var abs = Math.abs; + var cos = Math.cos; + var sin = Math.sin; + var exp = Math.exp; + var PI = Math.PI; + + function deltaE (a, b, Kl, Kc, Kh) { + if ( Kl === void 0 ) Kl = 1; + if ( Kc === void 0 ) Kc = 1; + if ( Kh === void 0 ) Kh = 1; + + // Delta E (CIE 2000) + // see http://www.brucelindbloom.com/index.html?Eqn_DeltaE_CIE2000.html + var rad2deg = function (rad) { + return (360 * rad) / (2 * PI); + }; + var deg2rad = function (deg) { + return (2 * PI * deg) / 360; + }; + a = new Color(a); + b = new Color(b); + var ref = Array.from(a.lab()); + var L1 = ref[0]; + var a1 = ref[1]; + var b1 = ref[2]; + var ref$1 = Array.from(b.lab()); + var L2 = ref$1[0]; + var a2 = ref$1[1]; + var b2 = ref$1[2]; + var avgL = (L1 + L2) / 2; + var C1 = sqrt(pow(a1, 2) + pow(b1, 2)); + var C2 = sqrt(pow(a2, 2) + pow(b2, 2)); + var avgC = (C1 + C2) / 2; + var G = 0.5 * (1 - sqrt(pow(avgC, 7) / (pow(avgC, 7) + pow(25, 7)))); + var a1p = a1 * (1 + G); + var a2p = a2 * (1 + G); + var C1p = sqrt(pow(a1p, 2) + pow(b1, 2)); + var C2p = sqrt(pow(a2p, 2) + pow(b2, 2)); + var avgCp = (C1p + C2p) / 2; + var arctan1 = rad2deg(atan2(b1, a1p)); + var arctan2 = rad2deg(atan2(b2, a2p)); + var h1p = arctan1 >= 0 ? arctan1 : arctan1 + 360; + var h2p = arctan2 >= 0 ? arctan2 : arctan2 + 360; + var avgHp = + abs(h1p - h2p) > 180 ? (h1p + h2p + 360) / 2 : (h1p + h2p) / 2; + var T = + 1 - + 0.17 * cos(deg2rad(avgHp - 30)) + + 0.24 * cos(deg2rad(2 * avgHp)) + + 0.32 * cos(deg2rad(3 * avgHp + 6)) - + 0.2 * cos(deg2rad(4 * avgHp - 63)); + var deltaHp = h2p - h1p; + deltaHp = + abs(deltaHp) <= 180 + ? deltaHp + : h2p <= h1p + ? deltaHp + 360 + : deltaHp - 360; + deltaHp = 2 * sqrt(C1p * C2p) * sin(deg2rad(deltaHp) / 2); + var deltaL = L2 - L1; + var deltaCp = C2p - C1p; + var sl = 1 + (0.015 * pow(avgL - 50, 2)) / sqrt(20 + pow(avgL - 50, 2)); + var sc = 1 + 0.045 * avgCp; + var sh = 1 + 0.015 * avgCp * T; + var deltaTheta = 30 * exp(-pow((avgHp - 275) / 25, 2)); + var Rc = 2 * sqrt(pow(avgCp, 7) / (pow(avgCp, 7) + pow(25, 7))); + var Rt = -Rc * sin(2 * deg2rad(deltaTheta)); + var result = sqrt( + pow(deltaL / (Kl * sl), 2) + + pow(deltaCp / (Kc * sc), 2) + + pow(deltaHp / (Kh * sh), 2) + + Rt * (deltaCp / (Kc * sc)) * (deltaHp / (Kh * sh)) + ); + return max(0, min(100, result)); + } + + // simple Euclidean distance + function distance (a, b, mode) { + if ( mode === void 0 ) mode = 'lab'; + + // Delta E (CIE 1976) + // see http://www.brucelindbloom.com/index.html?Equations.html + a = new Color(a); + b = new Color(b); + var l1 = a.get(mode); + var l2 = b.get(mode); + var sum_sq = 0; + for (var i in l1) { + var d = (l1[i] || 0) - (l2[i] || 0); + sum_sq += d * d; + } + return Math.sqrt(sum_sq); + } + + function valid () { + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + try { + new (Function.prototype.bind.apply( Color, [ null ].concat( args) )); + return true; + // eslint-disable-next-line + } catch (e) { + return false; + } + } + + // some pre-defined color scales: + + var scales = { + cool: function cool() { + return scale([chroma.hsl(180, 1, 0.9), chroma.hsl(250, 0.7, 0.4)]); + }, + hot: function hot() { + return scale(['#000', '#f00', '#ff0', '#fff']).mode( + 'rgb' + ); + } + }; + + /** + ColorBrewer colors for chroma.js + + Copyright (c) 2002 Cynthia Brewer, Mark Harrower, and The + Pennsylvania State University. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed + under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. See the License for the + specific language governing permissions and limitations under the License. + */ + + var colorbrewer = { + // sequential + OrRd: ['#fff7ec', '#fee8c8', '#fdd49e', '#fdbb84', '#fc8d59', '#ef6548', '#d7301f', '#b30000', '#7f0000'], + PuBu: ['#fff7fb', '#ece7f2', '#d0d1e6', '#a6bddb', '#74a9cf', '#3690c0', '#0570b0', '#045a8d', '#023858'], + BuPu: ['#f7fcfd', '#e0ecf4', '#bfd3e6', '#9ebcda', '#8c96c6', '#8c6bb1', '#88419d', '#810f7c', '#4d004b'], + Oranges: ['#fff5eb', '#fee6ce', '#fdd0a2', '#fdae6b', '#fd8d3c', '#f16913', '#d94801', '#a63603', '#7f2704'], + BuGn: ['#f7fcfd', '#e5f5f9', '#ccece6', '#99d8c9', '#66c2a4', '#41ae76', '#238b45', '#006d2c', '#00441b'], + YlOrBr: ['#ffffe5', '#fff7bc', '#fee391', '#fec44f', '#fe9929', '#ec7014', '#cc4c02', '#993404', '#662506'], + YlGn: ['#ffffe5', '#f7fcb9', '#d9f0a3', '#addd8e', '#78c679', '#41ab5d', '#238443', '#006837', '#004529'], + Reds: ['#fff5f0', '#fee0d2', '#fcbba1', '#fc9272', '#fb6a4a', '#ef3b2c', '#cb181d', '#a50f15', '#67000d'], + RdPu: ['#fff7f3', '#fde0dd', '#fcc5c0', '#fa9fb5', '#f768a1', '#dd3497', '#ae017e', '#7a0177', '#49006a'], + Greens: ['#f7fcf5', '#e5f5e0', '#c7e9c0', '#a1d99b', '#74c476', '#41ab5d', '#238b45', '#006d2c', '#00441b'], + YlGnBu: ['#ffffd9', '#edf8b1', '#c7e9b4', '#7fcdbb', '#41b6c4', '#1d91c0', '#225ea8', '#253494', '#081d58'], + Purples: ['#fcfbfd', '#efedf5', '#dadaeb', '#bcbddc', '#9e9ac8', '#807dba', '#6a51a3', '#54278f', '#3f007d'], + GnBu: ['#f7fcf0', '#e0f3db', '#ccebc5', '#a8ddb5', '#7bccc4', '#4eb3d3', '#2b8cbe', '#0868ac', '#084081'], + Greys: ['#ffffff', '#f0f0f0', '#d9d9d9', '#bdbdbd', '#969696', '#737373', '#525252', '#252525', '#000000'], + YlOrRd: ['#ffffcc', '#ffeda0', '#fed976', '#feb24c', '#fd8d3c', '#fc4e2a', '#e31a1c', '#bd0026', '#800026'], + PuRd: ['#f7f4f9', '#e7e1ef', '#d4b9da', '#c994c7', '#df65b0', '#e7298a', '#ce1256', '#980043', '#67001f'], + Blues: ['#f7fbff', '#deebf7', '#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#08519c', '#08306b'], + PuBuGn: ['#fff7fb', '#ece2f0', '#d0d1e6', '#a6bddb', '#67a9cf', '#3690c0', '#02818a', '#016c59', '#014636'], + Viridis: ['#440154', '#482777', '#3f4a8a', '#31678e', '#26838f', '#1f9d8a', '#6cce5a', '#b6de2b', '#fee825'], + + // diverging + Spectral: ['#9e0142', '#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#e6f598', '#abdda4', '#66c2a5', '#3288bd', '#5e4fa2'], + RdYlGn: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850', '#006837'], + RdBu: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#f7f7f7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac', '#053061'], + PiYG: ['#8e0152', '#c51b7d', '#de77ae', '#f1b6da', '#fde0ef', '#f7f7f7', '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221', '#276419'], + PRGn: ['#40004b', '#762a83', '#9970ab', '#c2a5cf', '#e7d4e8', '#f7f7f7', '#d9f0d3', '#a6dba0', '#5aae61', '#1b7837', '#00441b'], + RdYlBu: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee090', '#ffffbf', '#e0f3f8', '#abd9e9', '#74add1', '#4575b4', '#313695'], + BrBG: ['#543005', '#8c510a', '#bf812d', '#dfc27d', '#f6e8c3', '#f5f5f5', '#c7eae5', '#80cdc1', '#35978f', '#01665e', '#003c30'], + RdGy: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#ffffff', '#e0e0e0', '#bababa', '#878787', '#4d4d4d', '#1a1a1a'], + PuOr: ['#7f3b08', '#b35806', '#e08214', '#fdb863', '#fee0b6', '#f7f7f7', '#d8daeb', '#b2abd2', '#8073ac', '#542788', '#2d004b'], + + // qualitative + Set2: ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f', '#e5c494', '#b3b3b3'], + Accent: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0', '#f0027f', '#bf5b17', '#666666'], + Set1: ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33', '#a65628', '#f781bf', '#999999'], + Set3: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd', '#ccebc5', '#ffed6f'], + Dark2: ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e', '#e6ab02', '#a6761d', '#666666'], + Paired: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a', '#ffff99', '#b15928'], + Pastel2: ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9', '#fff2ae', '#f1e2cc', '#cccccc'], + Pastel1: ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc', '#e5d8bd', '#fddaec', '#f2f2f2'] + }; + + var colorbrewerTypes = Object.keys(colorbrewer); + var typeMap = new Map(colorbrewerTypes.map(function (key) { return [key.toLowerCase(), key]; })); + + // use Proxy to allow case-insensitive access to palettes + var colorbrewerProxy = + typeof Proxy === 'function' + ? new Proxy(colorbrewer, { + get: function get(target, prop) { + var lower = prop.toLowerCase(); + if (typeMap.has(lower)) { + return target[typeMap.get(lower)]; + } + }, + getOwnPropertyNames: function getOwnPropertyNames() { + return Object.getOwnPropertyNames(colorbrewerTypes); + } + }) + : colorbrewer; + + // feel free to comment out anything to rollup + // a smaller chroma.js bundle + + Object.assign(chroma, { + analyze: analyze, + average: average, + bezier: bezier$1, + blend: blend, + brewer: colorbrewerProxy, + Color: Color, + colors: w3cx11, + contrast: contrast, + contrastAPCA: contrastAPCA, + cubehelix: cubehelix, + deltaE: deltaE, + distance: distance, + input: input, + interpolate: mix, + limits: limits, + mix: mix, + random: random$1, + scale: scale, + scales: scales, + valid: valid, + cmyk: cmyk, + css: css, + gl: gl, + hcg: hcg$1, + hex: hex, + hsi: hsi$1, + hsl: hsl$1, + hsv: hsv$1, + lab: lab$1, + lch: lch$1, + hcl: hcl, + num: num$1, + rgb: rgb$1, + temp: temp, + kelvin: temp, + temperature: temp, + oklab: oklab$1, + oklch: oklch$1, + getLabWhitePoint: getLabWhitePoint, + setLabWhitePoint: setLabWhitePoint + }); + + return chroma; + +})); diff --git a/base_geoengine/static/lib/geostats-2.1.0/geostats.css b/base_geoengine/static/lib/geostats-2.1.0/geostats.css new file mode 100644 index 000000000..a1bad4e69 --- /dev/null +++ b/base_geoengine/static/lib/geostats-2.1.0/geostats.css @@ -0,0 +1,24 @@ +.geostats-legend div { + margin:3px 10px 5px 10px; + clear:left; +} + +.geostats-legend-title { + font-weight: bold; + margin-bottom: 4px; +} + +.geostats-legend-block { + border: 1px solid #555555; + display: block; + float: left; + height: 12px; + margin: 0 5px 0 20px; + width: 20px; +} + +.geostats-legend-counter { + font-size: 0.8em; + color:#666; + font-style: italic; +} diff --git a/base_geoengine/static/lib/geostats-2.1.0/geostats.js b/base_geoengine/static/lib/geostats-2.1.0/geostats.js new file mode 100755 index 000000000..0da331884 --- /dev/null +++ b/base_geoengine/static/lib/geostats-2.1.0/geostats.js @@ -0,0 +1,1435 @@ +/** +* geostats() is a tiny and standalone javascript library for classification +* Project page - https://github.com/simogeo/geostats +* Copyright (c) 2011 Simon Georget, http://www.intermezzo-coop.eu +* Licensed under the MIT license +*/ + + +(function (definition) { + // This file will function properly as a