Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions build/docma-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@
"web/client/plugins/BackgroundSelector.jsx",
"web/client/plugins/BurgerMenu.jsx",
"web/client/plugins/CRSSelector.jsx",
"web/client/plugins/CameraPosition.jsx",
"web/client/plugins/Context.jsx",
"web/client/plugins/ContextCreator.jsx",
"web/client/plugins/ContextExport.jsx",
Expand All @@ -259,8 +260,8 @@
"web/client/plugins/History.jsx",
"web/client/plugins/Home.jsx",
"web/client/plugins/Identify.jsx",
"web/client/plugins/Itinerary/Itinerary.jsx",
"web/client/plugins/Isochrone/Isochrone.jsx",
"web/client/plugins/Itinerary/Itinerary.jsx",
"web/client/plugins/Language.jsx",
"web/client/plugins/LayerDownload.jsx",
"web/client/plugins/LayerInfo.jsx",
Expand Down Expand Up @@ -346,4 +347,4 @@
]
}
]
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
"@mapbox/geojsonhint": "3.3.0",
"@mapbox/togeojson": "0.16.2",
"@mapstore/patcher": "https://github.com/geosolutions-it/Patcher/tarball/master",
"@math.gl/geoid": "^4.1.0",
"@turf/along": "6.5.0",
"@turf/area": "6.5.0",
"@turf/bbox": "4.1.0",
Expand Down
16 changes: 16 additions & 0 deletions web/client/actions/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export const ORIENTATION = 'MAP:ORIENTATION';
export const UPDATE_MAP_VIEW = 'MAP:UPDATE_MAP_VIEW';
export const UPDATE_MAP_OPTIONS = 'MAP:UPDATE_MAP_OPTIONS';
export const FORCE_RENDER = 'MAP:FORCE_RENDER';
export const CHANGE_CAMERA_POSITION_CRS = 'CHANGE_CAMERA_POSITION_CRS';
export const CHANGE_CAMERA_POSITION_HEIGHT_TYPE = 'CHANGE_CAMERA_POSITION_HEIGHT_TYPE';


/**
Expand Down Expand Up @@ -87,6 +89,20 @@ export function changeMapView(center, zoom, bbox, size, mapStateSource, projecti
};
}

export function changeCameraPositionCrs(crs) {
return {
type: CHANGE_CAMERA_POSITION_CRS,
crs
};
}

export function changeCameraPositionHeightType(heightType) {
return {
type: CHANGE_CAMERA_POSITION_HEIGHT_TYPE,
heightType
};
}

export const changeCRS = (crs) => ({
type: CHANGE_MAP_CRS,
crs: crs
Expand Down
5 changes: 4 additions & 1 deletion web/client/components/map/cesium/Map.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ class CesiumMap extends React.Component {
}
};


getDocument = () => {
return this.props.document || document;
};
Expand Down Expand Up @@ -645,7 +646,9 @@ class CesiumMap extends React.Component {
cameraPosition: {
longitude: Cesium.Math.toDegrees(cameraPosition.longitude),
latitude: Cesium.Math.toDegrees(cameraPosition.latitude),
height: cameraPosition.height
height: cameraPosition.height,
crs: this.props.viewerOptions?.cameraPosition?.crs || "EPSG:4326",
heightType: this.props.viewerOptions?.cameraPosition?.heightType || 'Ellipsoidal'
},
orientation: {
heading: this.map.camera.heading,
Expand Down
180 changes: 108 additions & 72 deletions web/client/components/mapcontrols/mouseposition/CRSSelector.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,88 +7,124 @@
*/

import PropTypes from 'prop-types';
import React from 'react';
import React, { useRef } from 'react';
import { ControlLabel, FormControl, FormGroup } from 'react-bootstrap';
import ReactDOM from 'react-dom';

import {filterCRSList, getAvailableCRS} from '../../../utils/CoordinatesUtils';
import { filterCRSList, getAvailableCRS } from '../../../utils/CoordinatesUtils';
import FlexBox from '../../layout/FlexBox';

class CRSSelector extends React.Component {
static propTypes = {
id: PropTypes.string,
label: PropTypes.oneOfType([PropTypes.func, PropTypes.string, PropTypes.object]),
availableCRS: PropTypes.object,
filterAllowedCRS: PropTypes.array,
projectionDefs: PropTypes.array,
additionalCRS: PropTypes.object,
crs: PropTypes.string,
enabled: PropTypes.bool,
onCRSChange: PropTypes.func,
useRawInput: PropTypes.bool
};
/**
* CRSSelector allows to select a crs from a combobox or using a raw input.
* @memberof components.mousePosition
* @class
* @prop {string} id the id of the component
* @prop {string|object|function} label the label shown next to the combobox (if editCRS is true)
* @prop {object} availableCRS list of available crs to be used in the combobox
* @prop {string[]} filterAllowedCRS list of allowed crs in the combobox list
* @prop {object[]} projectionDefs list of additional project definitions
* @prop {object} additionalCRS additional crs to be added to the list
* @prop {string} crs the current selected crs
* @prop {boolean} enabled if true shows the component
* @prop {function} onCRSChange callback when a new crs is selected
* @prop {boolean} useRawInput if true shows a raw input instead of a combobox
*/

static defaultProps = {
id: "mapstore-crsselector",
availableCRS: getAvailableCRS(),
crs: null,
onCRSChange: function() {},
enabled: false,
useRawInput: false
};
const CRSSelector = (props) => {
const {
id,
label,
availableCRS,
filterAllowedCRS,
projectionDefs,
additionalCRS,
crs,
enabled,
onCRSChange,
useRawInput
} = props;

render() {
var val;
var label;
var list = [];
let availableCRS = {};
if (Object.keys(this.props.availableCRS).length) {
availableCRS = filterCRSList(this.props.availableCRS, this.props.filterAllowedCRS, this.props.additionalCRS, this.props.projectionDefs );
}
for (let crs in availableCRS) {
if (availableCRS.hasOwnProperty(crs)) {
val = crs;
label = availableCRS[crs].label;
list.push(<option value={val} key={val}>{label}</option>);
}
}
const formRef = useRef(null);

if (this.props.enabled && this.props.useRawInput) {
return (
<select
id={this.props.id}
value={this.props.crs}
onChange={this.launchNewCRSAction}
bsSize="small"
>
{list}
</select>);
} else if (this.props.enabled && !this.props.useRawInput) {
return (
<FormGroup>
<ControlLabel>{this.props.label}</ControlLabel>
<FormControl
componentClass="select"
id={this.props.id}
value={this.props.crs}
onChange={this.launchNewCRSAction}
bsSize="small"
>
{list}
</FormControl>
</FormGroup>);
const launchNewCRSAction = (ev) => {
if (useRawInput) {
onCRSChange(ev.target.value);
} else {
const element = ReactDOM.findDOMNode(formRef.current);
const selectNode = element.getElementsByTagName('select').item(0);
onCRSChange(selectNode.value);
}
};

if (!enabled) {
return null;
}

launchNewCRSAction = (ev) => {
if (this.props.useRawInput) {
this.props.onCRSChange(ev.target.value);
} else {
let element = ReactDOM.findDOMNode(this);
let selectNode = element.getElementsByTagName('select').item(0);
this.props.onCRSChange(selectNode.value);
}
};
}
const filteredCRS = Object.keys(availableCRS).length
? filterCRSList(availableCRS, filterAllowedCRS, additionalCRS, projectionDefs)
: {};

const options = Object.entries(filteredCRS).map(([crsKey, crsValue]) => (
<option value={crsKey} key={crsKey}>{crsValue.label}</option>
));

if (useRawInput) {
return (
<select
id={id}
value={crs}
onChange={launchNewCRSAction}
bsSize="small"
>
{options}
</select>
);
}

return (
<FlexBox
ref={formRef}
component={FormGroup}
centerChildrenVertically
gap="sm"
>
<ControlLabel style={{ margin: 0, fontWeight: 'normal', minWidth: 'max-content' }}>
{label}
</ControlLabel>
<FormControl
componentClass="select"
id={id}
value={crs}
onChange={launchNewCRSAction}
bsSize="small"
style={{ borderRadius: 4 }}
>
{options}
</FormControl>
</FlexBox>
);
};

CRSSelector.propTypes = {
id: PropTypes.string,
label: PropTypes.oneOfType([PropTypes.func, PropTypes.string, PropTypes.object]),
availableCRS: PropTypes.object,
filterAllowedCRS: PropTypes.array,
projectionDefs: PropTypes.array,
additionalCRS: PropTypes.object,
crs: PropTypes.string,
enabled: PropTypes.bool,
onCRSChange: PropTypes.func,
useRawInput: PropTypes.bool
};

CRSSelector.defaultProps = {
id: "mapstore-crsselector",
availableCRS: getAvailableCRS(),
crs: null,
onCRSChange: function() {},
enabled: false,
useRawInput: false
};

export default CRSSelector;
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright 2025, GeoSolutions Sas.
* 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 PropTypes from "prop-types";
import React from "react";
import { ControlLabel, FormControl, FormGroup } from "react-bootstrap";
import FlexBox from "../../layout/FlexBox";

/**
* HeightTypeSelector allows to select a height type from a combobox.
* @memberof components.mousePosition
* @class
* @prop {string} id the id of the component
* @prop {string|object|function} label the label shown next to the combobox (if editHeight is true)
* @prop {string[]} filterAllowedHeight list of allowed height type in the combobox list. Accepted values are "Ellipsoidal" and "MSL"
* @prop {string} heightType the current selected height type
* @prop {boolean} enabled if true shows the component
* @prop {function} onHeightTypeChange callback when a new height type is selected
*/

const HeightTypeSelector = (props) => {
const {
id,
label,
filterAllowedHeight,
heightType,
enabled,
onHeightTypeChange
} = props;

if (!enabled) {
return null;
}
const availableHeightTypes = [
{ value: "Ellipsoidal", label: "Ellipsoidal" },
{ value: "MSL", label: "MSL" }
];

const filteredHeightTypes = filterAllowedHeight && filterAllowedHeight.length > 0
? availableHeightTypes.filter((height) => filterAllowedHeight.includes(height.value))
: availableHeightTypes;

const options = filteredHeightTypes.map(({ value, label: optionLabel }) => (
<option value={value} key={value}>{optionLabel}</option>
));

return (
<FlexBox component={FormGroup} centerChildrenVertically gap="sm">
<ControlLabel style={{ margin: 0, fontWeight: 'normal', minWidth: 'max-content' }}>
{label}
</ControlLabel>
<FormControl
componentClass="select"
id={id}
value={heightType}
onChange={(e) => onHeightTypeChange(e.target.value)}
bsSize="small"
style={{ borderRadius: 4 }}
>
{options}
</FormControl>
</FlexBox>
);
};

HeightTypeSelector.propTypes = {
id: PropTypes.string,
label: PropTypes.oneOfType([PropTypes.func, PropTypes.string, PropTypes.object]),
filterAllowedHeight: PropTypes.array,
heightType: PropTypes.string,
enabled: PropTypes.bool,
onHeightTypeChange: PropTypes.func
};

HeightTypeSelector.defaultProps = {
id: "mapstore-heightselector",
heightType: null,
onHeightTypeChange: function() {},
enabled: false
};

export default HeightTypeSelector;
Loading