diff --git a/web/client/api/Model.js b/web/client/api/Model.js index 1d805a9347..269725804e 100644 --- a/web/client/api/Model.js +++ b/web/client/api/Model.js @@ -7,6 +7,7 @@ */ import axios from 'axios'; import proj4 from 'proj4'; +import { METERS_PER_UNIT } from '../utils/MapUtils'; /** * get ifc model main info such as: longitude, latitude, height and scale @@ -192,6 +193,30 @@ export const getIFCModel = (url) => { }); }); }; + +const getSize = ({ modelID, ifcModule, data }) => { + const { ifcApi, WebIFC } = ifcModule; + const boundingBoxSize = ifcApi.GetLineIDsWithType(modelID, WebIFC.IFCBOUNDINGBOX).size(); // eslint-disable-line + if (boundingBoxSize) { + const sizes = [...Array(boundingBoxSize).keys()].map((index) => { + const ifcBBoxLineID = ifcApi.GetLineIDsWithType(modelID, WebIFC.IFCBOUNDINGBOX).get(index); // eslint-disable-line + const ifcBBoxEntity = ifcApi.GetLine(modelID, ifcBBoxLineID); // eslint-disable-line + const corner = ifcApi.GetLine(modelID, ifcBBoxEntity.Corner.value); // eslint-disable-line + const coordinates = (corner?.Coordinates || []).map((coord) => coord?.value || 0); + // adding the corner because it could not be 0,0,0 + return [ + ifcBBoxEntity.XDim.value + Math.abs(coordinates[0]), + ifcBBoxEntity.YDim.value + Math.abs(coordinates[1]), + ifcBBoxEntity.ZDim.value + Math.abs(coordinates[2]) + ]; + }); + return sizes[0]; + } + // if there is not bounding box we could compute the size from the data itself + const { size } = ifcDataToJSON({ data, ifcModule }); + return size; +}; + /** * Common requests to IFC * @module api.IFC @@ -215,19 +240,21 @@ export const getCapabilities = (url) => { let capabilities = extractCapabilities(ifcModule, modelID, url); // extract model origin info by reading IFCProjectedCRS, IFCMapCONVERSION in case of IFC4 const modelOriginProperties = getModelOriginCoords(ifcModule, capabilities.version, modelID); + const size = getSize({ modelID, ifcModule, data }); capabilities.properties = { ...capabilities.properties, - ...modelOriginProperties + ...modelOriginProperties, + size }; ifcApi.CloseModel(modelID); // eslint-disable-line let properties = capabilities.properties; // todo: getting bbox needs to enhance to get the accurate bbox of the ifc model let bbox = { bounds: { - minx: properties.longitude || 0 - 0.001, - miny: properties.latitude || 0 - 0.001, - maxx: properties.longitude || 0 + 0.001, - maxy: properties.latitude || 0 + 0.001 + minx: (properties.longitude || 0) - ((size[0] / 2) / METERS_PER_UNIT.degrees), + miny: (properties.latitude || 0) - ((size[1] / 2) / METERS_PER_UNIT.degrees), + maxx: (properties.longitude || 0) + ((size[0] / 2) / METERS_PER_UNIT.degrees), + maxy: (properties.latitude || 0) + ((size[1] / 2) / METERS_PER_UNIT.degrees) }, crs: 'EPSG:4326' }; diff --git a/web/client/api/__tests__/Model-test.jsx b/web/client/api/__tests__/Model-test.jsx index 27f0a7ebb2..0aba12e80d 100644 --- a/web/client/api/__tests__/Model-test.jsx +++ b/web/client/api/__tests__/Model-test.jsx @@ -20,7 +20,8 @@ describe('Test Model API for ifc models', () => { expect(properties).toEqual({ projectedCrs: 'EPSG:5834', projectedCrsNotSupported: true, - mapConversion: { northings: 5334600, eastings: 4468005, orthogonalHeight: 515, xAxisOrdinate: 0, xAxisAbscissa: 1, rotation: 0, scale: 1 } + mapConversion: { northings: 5334600, eastings: 4468005, orthogonalHeight: 515, xAxisOrdinate: 0, xAxisAbscissa: 1, rotation: 0, scale: 1 }, + size: [ 1000, 1000, 0 ] }); expect(bbox).toBeTruthy(); expect(bbox.crs).toBe('EPSG:4326'); diff --git a/web/client/components/TOC/fragments/settings/ModelTransformation.jsx b/web/client/components/TOC/fragments/settings/ModelTransformation.jsx index 6f2914841d..8ddd1665b2 100644 --- a/web/client/components/TOC/fragments/settings/ModelTransformation.jsx +++ b/web/client/components/TOC/fragments/settings/ModelTransformation.jsx @@ -13,7 +13,7 @@ import PropTypes from 'prop-types'; import { FormGroup, ControlLabel, InputGroup } from 'react-bootstrap'; import DebouncedFormControl from '../../../misc/DebouncedFormControl'; import Message from '../../../I18N/Message'; - +import { METERS_PER_UNIT } from "../../../../utils/MapUtils"; /** * ModelTransformation. This component shows the model transformation options available * @prop {object} layer the layer options @@ -32,13 +32,14 @@ function ModelTransformation({ height, ...value }; + const size = feature?.properties?.size || [2, 2]; const newBbox = { ...layer?.bbox, bounds: { - minx: updatedCenter.longitude - 0.001, - miny: updatedCenter.latitude - 0.001, - maxx: updatedCenter.longitude + 0.001, - maxy: updatedCenter.latitude + 0.001 + minx: updatedCenter.longitude - ((size[0] / 2) / METERS_PER_UNIT.degrees), + miny: updatedCenter.latitude - ((size[1] / 2) / METERS_PER_UNIT.degrees), + maxx: updatedCenter.longitude + ((size[0] / 2) / METERS_PER_UNIT.degrees), + maxy: updatedCenter.latitude + ((size[1] / 2) / METERS_PER_UNIT.degrees) } }; onChange('features', [ diff --git a/web/client/epics/catalog.js b/web/client/epics/catalog.js index 90b2cfa219..8b8389f033 100644 --- a/web/client/epics/catalog.js +++ b/web/client/epics/catalog.js @@ -69,11 +69,10 @@ import {getCapabilitiesUrl, getLayerId, getLayerUrl, removeWorkspace} from '../u import {zoomToExtent} from "../actions/map"; import CSW from '../api/CSW'; import { projectionSelector, mapSelector } from '../selectors/map'; -import { getResolutions } from "../utils/MapUtils"; +import { getResolutions, METERS_PER_UNIT } from "../utils/MapUtils"; import { describeFeatureType } from '../api/WFS'; import { extractGeometryType } from '../utils/WFSLayerUtils'; import { createDefaultStyle } from '../utils/StyleUtils'; - const onErrorRecordSearch = (isNewService, errObj) => { if (isNewService) { return Rx.Observable.of( @@ -297,14 +296,15 @@ export default (API) => ({ const center = CoordinatesUtils.reproject(mapCenter, mapCenter.crs, 'EPSG:4326'); const longitude = center.x; const latitude = center.y; + const size = properties.size || [2, 2]; const newLayer = { ...layer, bbox: { bounds: { - minx: longitude || 0 - 0.001, - miny: latitude || 0 - 0.001, - maxx: longitude || 0 + 0.001, - maxy: latitude || 0 + 0.001 + minx: (longitude || 0) - ((size[0] / 2) / METERS_PER_UNIT.degrees), + miny: (latitude || 0) - ((size[1] / 2) / METERS_PER_UNIT.degrees), + maxx: (longitude || 0) + ((size[0] / 2) / METERS_PER_UNIT.degrees), + maxy: (latitude || 0) + ((size[1] / 2) / METERS_PER_UNIT.degrees) }, crs: 'EPSG:4326' }, @@ -324,6 +324,9 @@ export default (API) => ({ title: "notification.warning", message: properties?.projectedCrsNotSupported ? "layerProperties.modelLayer.warnings.projectedCrsNotSupported" : "layerProperties.modelLayer.warnings.projectedCrsNotProvided", autoDismiss: 15, + values: { + modelProjection: properties?.projectedCrsNotSupported ? `(${properties?.projectedCrs})` : "" + }, position: "tc" })] ); diff --git a/web/client/translations/data.de-DE.json b/web/client/translations/data.de-DE.json index 4f450dbfb7..e53147be6a 100644 --- a/web/client/translations/data.de-DE.json +++ b/web/client/translations/data.de-DE.json @@ -179,7 +179,7 @@ "height": "Höhe (m)", "heading": "Kurswinkel (DD)", "warnings": { - "projectedCrsNotSupported": "Das Modell wird aus folgenden Gründen in der Mitte der aktuellen Ansicht platziert: Das Modell verfügt über eine CRS-Projektion, diese wird jedoch nicht unterstützt.", + "projectedCrsNotSupported": "Das Modell wird aus folgenden Gründen in der Mitte der aktuellen Ansicht platziert: Das Modell verfügt über eine CRS-Projektion {modelProjection}, diese wird jedoch nicht unterstützt.", "projectedCrsNotProvided": "Das Modell wird aus folgenden Gründen in der Mitte der aktuellen Ansicht platziert: Das Modell verfügt über keine definierte CRS-Projektion." } }, diff --git a/web/client/translations/data.en-US.json b/web/client/translations/data.en-US.json index f0ac0953e1..ee84f928c5 100644 --- a/web/client/translations/data.en-US.json +++ b/web/client/translations/data.en-US.json @@ -179,7 +179,7 @@ "height": "Height (m)", "heading": "Heading (DD)", "warnings": { - "projectedCrsNotSupported": "The model is placed on the center of the current view because: the model has a CRS projection but it is not supported.", + "projectedCrsNotSupported": "The model is placed on the center of the current view because: the model has a CRS projection {modelProjection} but it is not supported.", "projectedCrsNotProvided": "The model is placed on the center of the current view because: the model has no defined CRS projection." } }, diff --git a/web/client/translations/data.es-ES.json b/web/client/translations/data.es-ES.json index dfb69b4ec1..cb98f46462 100644 --- a/web/client/translations/data.es-ES.json +++ b/web/client/translations/data.es-ES.json @@ -176,7 +176,7 @@ "height": "Altura (m)", "heading": "Ángulo de rumbo (DD)", "warnings": { - "projectedCrsNotSupported": "El modelo se coloca en el centro de la vista actual porque: el modelo tiene una proyección CRS pero no es soportado", + "projectedCrsNotSupported": "El modelo se coloca en el centro de la vista actual porque: el modelo tiene una proyección CRS {modelProjection} pero no es soportado", "projectedCrsNotProvided": "El modelo se coloca en el centro de la vista actual porque: el modelo no tiene una proyección CRS definida." } }, diff --git a/web/client/translations/data.fr-FR.json b/web/client/translations/data.fr-FR.json index 4838621068..d35786ee0c 100644 --- a/web/client/translations/data.fr-FR.json +++ b/web/client/translations/data.fr-FR.json @@ -179,7 +179,7 @@ "height": "Hauteur (m)", "heading": "Angle de cap (DD)", "warnings": { - "projectedCrsNotSupported": "Le modèle est placé au centre de la vue actuelle car: le modèle a une projection CRS, mais elle n'est pas prise en charge.", + "projectedCrsNotSupported": "Le modèle est placé au centre de la vue actuelle car: le modèle a une projection CRS {modelProjection}, mais elle n'est pas prise en charge.", "projectedCrsNotProvided": "Le modèle est placé au centre de la vue actuelle car: le modèle n'a pas de projection CRS définie." } }, diff --git a/web/client/translations/data.it-IT.json b/web/client/translations/data.it-IT.json index 8307162564..2749d74e99 100644 --- a/web/client/translations/data.it-IT.json +++ b/web/client/translations/data.it-IT.json @@ -179,7 +179,7 @@ "height": "Altezza (m)", "heading": "Angolo di rotta (DD)", "warnings": { - "projectedCrsNotSupported": "Il modello è posizionato al centro della vista corrente perché: il modello ha una proiezione CRS, ma non è supportata.", + "projectedCrsNotSupported": "Il modello è posizionato al centro della vista corrente perché: il modello ha una proiezione CRS {modelProjection}, ma non è supportata.", "projectedCrsNotProvided": "Il modello è posizionato al centro della vista corrente perché: il modello non ha una proiezione CRS definita." } },