UNPKG

qwc2

Version:
24 lines 19.9 kB
function _typeof(o){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},_typeof(o)}function _toConsumableArray(r){return _arrayWithoutHoles(r)||_iterableToArray(r)||_unsupportedIterableToArray(r)||_nonIterableSpread()}function _nonIterableSpread(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _unsupportedIterableToArray(r,a){if(r){if("string"==typeof r)return _arrayLikeToArray(r,a);var t={}.toString.call(r).slice(8,-1);return"Object"===t&&r.constructor&&(t=r.constructor.name),"Map"===t||"Set"===t?Array.from(r):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?_arrayLikeToArray(r,a):void 0}}function _iterableToArray(r){if("undefined"!=typeof Symbol&&null!=r[Symbol.iterator]||null!=r["@@iterator"])return Array.from(r)}function _arrayWithoutHoles(r){if(Array.isArray(r))return _arrayLikeToArray(r)}function _arrayLikeToArray(r,a){(null==a||a>r.length)&&(a=r.length);for(var e=0,n=Array(a);e<a;e++)n[e]=r[e];return n}function _classCallCheck(a,n){if(!(a instanceof n))throw new TypeError("Cannot call a class as a function")}function _defineProperties(e,r){for(var t=0;t<r.length;t++){var o=r[t];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,_toPropertyKey(o.key),o)}}function _createClass(e,r,t){return r&&_defineProperties(e.prototype,r),t&&_defineProperties(e,t),Object.defineProperty(e,"prototype",{writable:!1}),e}function _callSuper(t,o,e){return o=_getPrototypeOf(o),_possibleConstructorReturn(t,_isNativeReflectConstruct()?Reflect.construct(o,e||[],_getPrototypeOf(t).constructor):o.apply(t,e))}function _possibleConstructorReturn(t,e){if(e&&("object"==_typeof(e)||"function"==typeof e))return e;if(void 0!==e)throw new TypeError("Derived constructors may only return object or undefined");return _assertThisInitialized(t)}function _assertThisInitialized(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function _isNativeReflectConstruct(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(_isNativeReflectConstruct=function _isNativeReflectConstruct(){return!!t})()}function _getPrototypeOf(t){return _getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)},_getPrototypeOf(t)}function _inherits(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Object.defineProperty(t,"prototype",{writable:!1}),e&&_setPrototypeOf(t,e)}function _setPrototypeOf(t,e){return _setPrototypeOf=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t},_setPrototypeOf(t,e)}function _defineProperty(e,r,t){return(r=_toPropertyKey(r))in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function _toPropertyKey(t){var i=_toPrimitive(t,"string");return"symbol"==_typeof(i)?i:i+""}function _toPrimitive(t,r){if("object"!=_typeof(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var i=e.call(t,r||"default");if("object"!=_typeof(i))return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===r?String:Number)(t)}/** * Copyright 2024 Sourcepole AG * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */import React from"react";import ColorLayer from"@giro3d/giro3d/core/layer/ColorLayer";import Shape from"@giro3d/giro3d/entities/Shape";import DrawTool,{conditions}from"@giro3d/giro3d/interactions/DrawTool.js";import VectorSource from"@giro3d/giro3d/sources/VectorSource";import ol from"openlayers";import pointInPolygon from"point-in-polygon";import PropTypes from"prop-types";import{CurvePath,LineCurve,Vector2,Vector3}from"three";import ConfigUtils from"../../utils/ConfigUtils";import CoordinatesUtils from"../../utils/CoordinatesUtils";import LocaleUtils from"../../utils/LocaleUtils";import MeasureUtils from"../../utils/MeasureUtils";import TaskBar from"../TaskBar";import ButtonBar from"../widgets/ButtonBar";import CopyButton from"../widgets/CopyButton";import HeightProfile3D from"./HeightProfile3D";import"../../plugins/style/Measure.css";var Measure3D=/*#__PURE__*/function(_React$Component){function Measure3D(props){var _this;_classCallCheck(this,Measure3D);_this=_callSuper(this,Measure3D,[props]);_defineProperty(_this,"state",{mode:null,result:null,lenUnit:"metric",areaUnit:"metric",elevUnit:"absolute"});_defineProperty(_this,"onShow",function(mode){_this.setState({mode:mode!==null&&mode!==void 0?mode:"Point"});_this.abortController=new AbortController;_this.measureTool=new DrawTool({instance:_this.props.sceneContext.scene});_this.drawLayer=new ColorLayer({source:new VectorSource({data:[],format:new ol.format.GeoJSON,style:_this.featureStyleFunction})});_this.props.sceneContext.map.addLayer(_this.drawLayer)});_defineProperty(_this,"onHide",function(){_this.clearResult();_this.setState({mode:null});_this.abortController.abort();_this.abortController=null;_this.measureTool.dispose();_this.measureTool=null;_this.props.sceneContext.map.removeLayer(_this.drawLayer,{dispose:true});_this.drawLayer=null});_defineProperty(_this,"renderModeSwitcher",function(){var buttons=[{key:"Point",label:LocaleUtils.tr("measureComponent.pointLabel")},{key:"HeightDiff",label:LocaleUtils.tr("measureComponent.heightDiffLabel")},{key:"LineString",label:LocaleUtils.tr("measureComponent.lengthLabel")},{key:"Polygon",label:LocaleUtils.tr("measureComponent.areaLabel")}];return/*#__PURE__*/React.createElement(ButtonBar,{active:_this.state.mode,buttons:buttons,onClick:function onClick(mode){return _this.setState({mode:mode,result:null})}})});_defineProperty(_this,"renderResult",function(){if(!_this.state.result){return null}var text="";var unitSelector=null;if(_this.state.mode==="Point"){text=CoordinatesUtils.getFormattedCoordinate(_this.state.result.pos.slice(0,2),_this.props.sceneContext.mapCrs);var prec=ConfigUtils.getConfigProp("measurementPrecision");text+=", "+(_this.state.result.ground>0&&_this.state.elevUnit==="ground"?_this.state.result.ground:_this.state.result.pos[2]).toFixed(prec);if(_this.state.result.ground>0){unitSelector=/*#__PURE__*/React.createElement("select",{onChange:function onChange(ev){return _this.setState({elevUnit:ev.target.value})},value:_this.state.elevUnit},/*#__PURE__*/React.createElement("option",{value:"ground"},LocaleUtils.tr("measureComponent.ground")),/*#__PURE__*/React.createElement("option",{value:"absolute"},LocaleUtils.tr("measureComponent.absolute")))}else{unitSelector=/*#__PURE__*/React.createElement("span",{className:"measure-unit-label"},LocaleUtils.tr("measureComponent.absolute"))}}else if(_this.state.mode==="HeightDiff"){text=(_this.state.result||[]).length===2?MeasureUtils.formatMeasurement(Math.abs(_this.state.result[1].z-_this.state.result[0].z),false,_this.state.lenUnit):"";unitSelector=/*#__PURE__*/React.createElement("select",{onChange:function onChange(ev){return _this.setState({lenUnit:ev.target.value})},value:_this.state.lenUnit},/*#__PURE__*/React.createElement("option",{value:"metric"},LocaleUtils.tr("measureComponent.metric")),/*#__PURE__*/React.createElement("option",{value:"imperial"},LocaleUtils.tr("measureComponent.imperial")),/*#__PURE__*/React.createElement("option",{value:"m"},"m"),/*#__PURE__*/React.createElement("option",{value:"km"},"km"),/*#__PURE__*/React.createElement("option",{value:"ft"},"ft"),/*#__PURE__*/React.createElement("option",{value:"mi"},"mi"))}else if(_this.state.mode==="LineString"){text=MeasureUtils.formatMeasurement(_this.state.result.length,false,_this.state.lenUnit);unitSelector=/*#__PURE__*/React.createElement("select",{onChange:function onChange(ev){return _this.setState({lenUnit:ev.target.value})},value:_this.state.lenUnit},/*#__PURE__*/React.createElement("option",{value:"metric"},LocaleUtils.tr("measureComponent.metric")),/*#__PURE__*/React.createElement("option",{value:"imperial"},LocaleUtils.tr("measureComponent.imperial")),/*#__PURE__*/React.createElement("option",{value:"m"},"m"),/*#__PURE__*/React.createElement("option",{value:"km"},"km"),/*#__PURE__*/React.createElement("option",{value:"ft"},"ft"),/*#__PURE__*/React.createElement("option",{value:"mi"},"mi"))}else if(_this.state.mode==="Polygon"){text=MeasureUtils.formatMeasurement(_this.state.result,true,_this.state.areaUnit);unitSelector=/*#__PURE__*/React.createElement("select",{onChange:function onChange(ev){return _this.setState({areaUnit:ev.target.value})},value:_this.state.areaUnit},/*#__PURE__*/React.createElement("option",{value:"metric"},LocaleUtils.tr("measureComponent.metric")),/*#__PURE__*/React.createElement("option",{value:"imperial"},LocaleUtils.tr("measureComponent.imperial")),/*#__PURE__*/React.createElement("option",{value:"sqm"},"m\xB2"),/*#__PURE__*/React.createElement("option",{value:"ha"},"ha"),/*#__PURE__*/React.createElement("option",{value:"sqkm"},"km\xB2"),/*#__PURE__*/React.createElement("option",{value:"sqft"},"ft\xB2"),/*#__PURE__*/React.createElement("option",{value:"acre"},"acre"),/*#__PURE__*/React.createElement("option",{value:"sqmi"},"mi\xB2"))}return/*#__PURE__*/React.createElement("div",{className:"measure-result controlgroup"},/*#__PURE__*/React.createElement("input",{className:"measure-result-field",readOnly:true,type:"text",value:text}),unitSelector,/*#__PURE__*/React.createElement(CopyButton,{text:text}))});_defineProperty(_this,"featureStyleFunction",function(){return[new ol.style.Style({fill:new ol.style.Fill({color:[41,120,180,0.5]})}),new ol.style.Style({stroke:new ol.style.Stroke({color:[255,255,255],width:4})}),new ol.style.Style({stroke:new ol.style.Stroke({color:[41,120,180],width:1.5})})]});_defineProperty(_this,"clearResult",function(){_this.drawLayer.source.clear();_this.measurementObjects.forEach(function(object){_this.props.sceneContext.scene.remove(object)});_this.measurementObjects=[];_this.setState({result:null})});_defineProperty(_this,"restart",function(){if(_this.abortController){_this.abortController.abort()}_this.abortController=new AbortController;var terrainPick=function terrainPick(e){return _this.props.sceneContext.scene.pickObjectsAt(e,{sortByDistance:true,where:[_this.props.sceneContext.getMap()]})};var options={signal:_this.abortController.signal,endCondition:conditions.doubleClick,pick:null// default pick };if(_this.state.mode==="Point"){_this.measureTool.createPoint(options).then(_this.measurePoint)["catch"](function(){})}else if(_this.state.mode==="LineString"){options.pick=terrainPick;_this.measureTool.createLineString(options).then(_this.measureLine)["catch"](function(){})}else if(_this.state.mode==="Polygon"){options.pick=terrainPick;_this.measureTool.createPolygon(options).then(_this.measureArea)["catch"](function(){})}else if(_this.state.mode==="HeightDiff"){_this.measureTool.createPoint(options).then(_this.measureHeightDiff)["catch"](function(){})}});_defineProperty(_this,"measurePoint",function(point){if(point===null){_this.restart();return}_this.clearResult();var pos=point.points[0];// Measure point above terrain _this.props.sceneContext.getTerrainHeightFromDTM([pos.x,pos.y]).then(function(elevation){var ground=pos.z-elevation>0.3?pos.z-elevation:0;var elevationLabelFormatter=function elevationLabelFormatter(options){if(options.index===0){return MeasureUtils.formatMeasurement(elevation,false,"m")+" "+LocaleUtils.tr("measureComponent.absolute")}else if(ground>0&&_this.state.elevUnit==="ground"){return MeasureUtils.formatMeasurement(pos.z-elevation,false,"m")+" "+LocaleUtils.tr("measureComponent.ground")}else{return MeasureUtils.formatMeasurement(pos.z,false,LocaleUtils.tr("measureComponent.absolute"))}};var shape=null;if(ground>0){// Add line shape=new Shape({showVertexLabels:true,showLine:true,showVertices:true,vertexLabelFormatter:elevationLabelFormatter});shape.setPoints([new Vector3(pos.x,pos.y,elevation),pos])}else{// Add point shape=new Shape({showVertexLabels:true,showLine:false,showVertices:true,vertexLabelFormatter:elevationLabelFormatter});shape.setPoints([new Vector3(pos.x,pos.y,pos.z)])}_this.props.sceneContext.scene.add(shape);_this.measurementObjects.push(shape);_this.props.sceneContext.scene.remove(point);_this.setState({result:{pos:[pos.x,pos.y,pos.z],ground:ground}});// Setup for next measurement _this.restart()})});_defineProperty(_this,"measureHeightDiff",function(point){if(point===null){_this.restart();return}if((_this.state.result||[]).length>=2){_this.clearResult()}var pos=point.points[0];if((_this.state.result||[]).length===1){// Add line if two points drawn var points=[_this.state.result[0],pos];if(points[0].z>points[1].z){points.reverse()}var line=new Shape({showVertexLabels:true,vertexLabelFormatter:function vertexLabelFormatter(options){return options.index===2?MeasureUtils.formatMeasurement(points[1].z-points[0].z,false,_this.state.lenUnit):null},showLine:true});line.setPoints([new Vector3(points[0].x,points[0].y,points[0].z),new Vector3(points[1].x,points[1].y,points[0].z),new Vector3(points[1].x,points[1].y,points[1].z)]);_this.props.sceneContext.scene.add(line);_this.measurementObjects.push(line)}else{// Add first drawn point var shape=new Shape({showVertices:true});shape.setPoints([new Vector3(pos.x,pos.y,pos.z)]);_this.props.sceneContext.scene.add(shape);_this.measurementObjects.push(shape)}_this.props.sceneContext.scene.remove(point);_this.setState(function(state){return{result:[].concat(_toConsumableArray(state.result||[]),[{x:pos.x,y:pos.y,z:pos.z}])}});_this.restart()});_defineProperty(_this,"measureLine",function(lineString){if(lineString===null){_this.restart();return}_this.clearResult();var features=new ol.format.GeoJSON().readFeatures(lineString.toGeoJSON(),{dataProjection:"EPSG:4326",featureProjection:_this.props.sceneContext.mapCrs});_this.drawLayer.source.addFeatures(features);_this.props.sceneContext.scene.remove(lineString);// Compute 2d length and nSamples spaced points var path=new CurvePath;var len2d=0;for(var i=0;i<lineString.points.length-1;i++){var v0=lineString.points[i];var v1=lineString.points[i+1];var line=new LineCurve(new Vector2(v0.x,v0.y),new Vector2(v1.x,v1.y));path.add(line);len2d+=Math.sqrt((v1.x-v0.x)*(v1.x-v0.x)+(v1.y-v0.y)*(v1.y-v0.y))}var nSamples=Math.min(_this.props.maxSampleCount,Math.round(len2d/_this.props.minMeasureLength));var points=path.getSpacedPoints(nSamples-1);var line3d=new Array(nSamples);line3d[0]=[points[0].x,points[0].y,_this.getElevation([points[0].x,points[0].y]),0];var len3d=0;for(var _i=1;_i<nSamples;++_i){line3d[_i]=[points[_i].x,points[_i].y,_this.getElevation([points[_i].x,points[_i].y]),0];var dx=line3d[_i][0]-line3d[_i-1][0];var dy=line3d[_i][1]-line3d[_i-1][1];var dz=line3d[_i][2]-line3d[_i-1][2];len3d+=Math.sqrt(dx*dx+dy*dy+dz*dz);line3d[_i][3]=len3d;// Also store incremental length for height profie }_this.setState({result:{length:len3d,profile:line3d}});_this.restart()});_defineProperty(_this,"measureArea",function(polygon){if(polygon===null){_this.restart();return}_this.clearResult();var features=new ol.format.GeoJSON().readFeatures(polygon.toGeoJSON(),{dataProjection:"EPSG:4326",featureProjection:_this.props.sceneContext.mapCrs});_this.drawLayer.source.addFeatures(features);_this.props.sceneContext.scene.remove(polygon);// Compute boundingbox of polygon, divide boundingbox into quads, // compute quad area on terrain for each quad in polygon var bbox=[polygon.points[0].x,polygon.points[0].y,polygon.points[0].x,polygon.points[0].y];var coordinates=polygon.points.map(function(v){bbox[0]=Math.min(bbox[0],v.x);bbox[1]=Math.min(bbox[1],v.y);bbox[2]=Math.max(bbox[2],v.x);bbox[3]=Math.max(bbox[3],v.y);return[v.x,v.y]});var quadSize=_this.props.minMeasureLength;var numX=Math.min(_this.props.maxSampleCount,Math.round((bbox[2]-bbox[0])/quadSize));var numY=Math.min(_this.props.maxSampleCount,Math.round((bbox[3]-bbox[1])/quadSize));var deltaX=(bbox[2]-bbox[0])/numX;var deltaY=(bbox[3]-bbox[1])/numY;var area=0;var elevationCache=new Array(numX*numY);for(var iX=0;iX<numX;++iX){for(var iY=0;iY<numY;++iY){var _elevationCache,_elevationCache2,_elevationCache3,_elevationCache4;// If quad center lies in polygon, consider it var p=[bbox[0]+iX*deltaX,bbox[1]+iY*deltaY];var c=[p[0]+0.5*deltaX,p[1]+0.5*deltaY];if(!pointInPolygon(c,coordinates)){continue}// Get elevations var z1=(_elevationCache=elevationCache[iY*numX+iX])!==null&&_elevationCache!==void 0?_elevationCache:elevationCache[iY*numX+iX]=_this.getElevation(p);var z2=(_elevationCache2=elevationCache[iY*numX+iX+1])!==null&&_elevationCache2!==void 0?_elevationCache2:elevationCache[iY*numX+iX+1]=_this.getElevation([p[0]+deltaX,p[1]]);var z3=(_elevationCache3=elevationCache[(iY+1)*numX+iX+1])!==null&&_elevationCache3!==void 0?_elevationCache3:elevationCache[(iY+1)*numX+iX+1]=_this.getElevation([p[0]+deltaX,p[1]+deltaY]);var z4=(_elevationCache4=elevationCache[(iY+1)*numX+iX])!==null&&_elevationCache4!==void 0?_elevationCache4:elevationCache[(iY+1)*numX+iX]=_this.getElevation([p[0],p[1]+deltaY]);// Divide quad along diagonal with smaller elevation difference var dz1=Math.abs(z3-z1);var dz2=Math.abs(z4-z2);if(dz1<dz2){var area1=_this.triangleArea([-deltaX,0,z1-z2],[0,deltaY,z3-z2]);var area2=_this.triangleArea([0,-deltaY,z1-z4],[deltaX,0,z3-z4]);area+=area1+area2}else{var _area=_this.triangleArea([deltaX,0,z2-z1],[0,deltaY,z4-z1]);var _area2=_this.triangleArea([-deltaX,0,z4-z3],[0,-deltaY,z1-z3]);area+=_area+_area2}}}_this.setState({result:area});// Setup for next measurement _this.restart()});_defineProperty(_this,"measureHeight",function(lineString){if(lineString===null){_this.restart();return}_this.clearResult();_this.measurementObjects.push(lineString);// Setup for next measurement _this.restart()});_defineProperty(_this,"getElevation",function(point){return _this.props.sceneContext.getTerrainHeightFromMap(point)});_defineProperty(_this,"triangleArea",function(u,v){var cross=[u[1]*v[2]-u[2]*v[1],u[0]*v[2]-u[2]*v[0],u[0]*v[1]-u[1]*v[0]];return 0.5*Math.sqrt(cross[0]*cross[0]+cross[1]*cross[1]+cross[2]*cross[2])});_this.measureTool=null;_this.drawLayer=null;_this.measurementObjects=[];return _this}_inherits(Measure3D,_React$Component);return _createClass(Measure3D,[{key:"componentDidUpdate",value:function componentDidUpdate(prevProps,prevState){if(this.state.mode&&this.state.mode!==prevState.mode){this.clearResult();this.restart()}if(this.state.elevUnit!==prevState.elevUnit){// Re-render height label this.measurementObjects[0].rebuildLabels();this.props.sceneContext.scene.notifyChange()}}},{key:"render",value:function render(){var _this2=this,_this$state$result;return[/*#__PURE__*/React.createElement(TaskBar,{key:"TaskBar",onHide:this.onHide,onShow:this.onShow,task:"Measure3D"},function(){return{body:/*#__PURE__*/React.createElement("div",{className:"measure-body"},_this2.renderModeSwitcher(),_this2.renderResult())}}),(_this$state$result=this.state.result)!==null&&_this$state$result!==void 0&&_this$state$result.profile?/*#__PURE__*/React.createElement(HeightProfile3D,{data:this.state.result.profile,key:"HeightProfile",sceneContext:this.props.sceneContext}):null]}}])}(React.Component);_defineProperty(Measure3D,"propTypes",{maxSampleCount:PropTypes.number,minMeasureLength:PropTypes.number,sceneContext:PropTypes.object});_defineProperty(Measure3D,"defaultProps",{maxSampleCount:500,minMeasureLength:1});export{Measure3D as default};