Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,25 @@ export const rectangle2bbox = (bbox: Rectangle): BBox => [
CesiumMath.toDegrees(bbox.north),
];

export const rectangle2Feature = (rect: Rectangle): Feature<Polygon> => {
return {
type: 'Feature',
properties: {},
geometry: {
type: 'Polygon',
coordinates: [
[
[CesiumMath.toDegrees(rect.west), CesiumMath.toDegrees(rect.north)],
[CesiumMath.toDegrees(rect.east), CesiumMath.toDegrees(rect.north)],
[CesiumMath.toDegrees(rect.east), CesiumMath.toDegrees(rect.south)],
[CesiumMath.toDegrees(rect.west), CesiumMath.toDegrees(rect.south)],
[CesiumMath.toDegrees(rect.west), CesiumMath.toDegrees(rect.north)], // close the ring
],
],
},
};
};

export const customComputeViewRectangle = (mapViewer: CesiumViewer) => {
const scene = mapViewer.scene;
const camera = mapViewer.camera;
Expand Down Expand Up @@ -330,7 +349,7 @@ export const computeLimitedViewRectangle = (mapViewer: CesiumViewer, maxDistance
export const createRectangleAround = (
centerCartographic: { longitude: number; latitude: number },
widthMeters: number,
heightMeters: number,
heightMeters: number
): Polygon => {
const ellipsoid = Ellipsoid.WGS84;
const lat = centerCartographic.latitude;
Expand Down Expand Up @@ -361,7 +380,14 @@ export const createRectangleAround = (
};
};

export const defaultVisualizationHandler = (viewer: CesiumViewer, dataSource: GeoJsonDataSource, processEntityIds: string[], color: string, extent?: BBox, labeling?: ICesiumWFSLayerLabelingOptions): void => {
export const defaultVisualizationHandler = (
viewer: CesiumViewer,
dataSource: GeoJsonDataSource,
processEntityIds: string[],
color: string,
extent?: BBox,
labeling?: ICesiumWFSLayerLabelingOptions
): void => {
const is2D = viewer.scene.mode === SceneMode.SCENE2D;

const getGeoJsonFromEntity = (entity: Entity): Polygon | undefined => {
Expand Down Expand Up @@ -413,11 +439,7 @@ export const defaultVisualizationHandler = (viewer: CesiumViewer, dataSource: Ge
return { widthMeters, heightMeters };
};

const createRectangleAround = (
centerCartographic: { longitude: number; latitude: number },
widthMeters: number,
heightMeters: number
): Polygon => {
const createRectangleAround = (centerCartographic: { longitude: number; latitude: number }, widthMeters: number, heightMeters: number): Polygon => {
const ellipsoid = Ellipsoid.WGS84;
const lat = centerCartographic.latitude;
const lon = centerCartographic.longitude;
Expand Down Expand Up @@ -557,21 +579,21 @@ export const defaultVisualizationHandler = (viewer: CesiumViewer, dataSource: Ge
.then((dataSource) => {
dataSource?.entities.values.forEach((entity: Entity) => {
entity.billboard = new BillboardGraphics({
image: entity.properties?.label.getValue(JulianDate.now()).dataURL,
heightReference: HeightReference.NONE, // Ensures it's not clamped and floats above
scale: 1.0,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
image: entity.properties?.label.getValue(JulianDate.now()).dataURL,
heightReference: HeightReference.NONE, // Ensures it's not clamped and floats above
scale: 1.0,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
});
});
});
});
}
};

const DEFAULT_RECTANGLE_FACTOR = 0.2;

export const applyFactor = (rect: CesiumRectangle, factor = DEFAULT_RECTANGLE_FACTOR): CesiumRectangle => {
if (rect.width === 0) {
rect.east = rect.east + 0.0001 * factor;
rect.east = rect.east + 0.0001 * factor;
rect.west = rect.west - 0.0001 * factor;
rect.south = rect.south - 0.0001 * factor;
rect.north = rect.north + 0.0001 * factor;
Expand All @@ -584,4 +606,4 @@ export const applyFactor = (rect: CesiumRectangle, factor = DEFAULT_RECTANGLE_FA
rect.north = rect.north + rect.height * factor;

return rect;
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { get } from 'lodash';
import pMap from 'p-map';
import { v4 as uuidv4 } from 'uuid';
import booleanValid from '@turf/boolean-valid';
import { distance, center, rectangle2bbox, computeLimitedViewRectangle, defaultVisualizationHandler } from '../helpers/utils';
import { distance, center, rectangle2bbox, computeLimitedViewRectangle, defaultVisualizationHandler, rectangle2Feature } from '../helpers/utils';
import { CesiumViewer, useCesiumMap, useCesiumMapViewstate } from '../map';

export interface ICesiumWFSLayerLabelTextField {
Expand All @@ -27,6 +27,7 @@ export interface ICesiumWFSLayerLabelTextField {
format?: string;
predicate?: (value: any) => any;
}

export interface ICesiumWFSLayerLabelingOptions {
dataSourcePrefix: string;
text: {
Expand All @@ -41,9 +42,38 @@ export interface ICesiumWFSLayerLabelingOptions {
lineWidth: number;
}

export interface IGqlServiceConfig {
query: string;
variablesDescriptor: {
featureProp: string;
startIndexProp: string;
countProp: string;
typeNameProp: string;
};
variables: {
data: Record<string, unknown>;
};
}

export interface IApiServiceConfig {
method?: 'GET' | 'POST';
headers?: Record<string, string>;
}

export type AlternativePayload =
| {
type: 'gql';
gql: IGqlServiceConfig;
}
| {
type: 'api';
api: IApiServiceConfig;
};

export interface ICesiumWFSLayerOptions {
url: string;
featureType: string;
alternativePayload?: AlternativePayload;
style: {
color: string;
hover: string;
Expand Down Expand Up @@ -72,7 +102,7 @@ interface IFetchMetadata {

export const CesiumWFSLayer: React.FC<ICesiumWFSLayer> = (props) => {
const { options, meta, visualizationHandler, withGeometryValidation = false } = props;
const { url, featureType, style, pageSize, zoomLevel, maxCacheSize, keyField, labeling } = options;
const { url, featureType, alternativePayload, style, pageSize, zoomLevel, maxCacheSize, keyField, labeling } = options;
const { color, hover } = style;
const mapViewer = useCesiumMap();
const mapViewState = useCesiumMapViewstate();
Expand Down Expand Up @@ -269,11 +299,7 @@ export const CesiumWFSLayer: React.FC<ICesiumWFSLayer> = (props) => {
updateMetadata(0, 0);
};

const fetchWfsData = async (wfsDataUrl: string, method: string = 'GET', body?: string): Promise<any> => {
const options: RequestInit = { method };
if (body !== undefined) {
options.body = body;
}
const fetchWfsData = async (wfsDataUrl: string, options: RequestInit = { method: 'GET' }): Promise<any> => {
const response = await fetch(wfsDataUrl, options);
if (response.status === 200) {
return await response.json();
Expand Down Expand Up @@ -534,15 +560,38 @@ export const CesiumWFSLayer: React.FC<ICesiumWFSLayer> = (props) => {
const position: Feature<Point> = center(bbox);

try {
const urlSeparator = url.includes('?') ? '&' : '?';
let wfsDataUrl = `${url}${urlSeparator}service=WFS&version=2.0.0&request=GetFeature&typeNames=${featureType}&outputFormat=application/json&bbox=${extent.join(
','
)},EPSG:4326&startIndex=${offset}&count=${pageSize}`;
if (keyField) {
wfsDataUrl += `&sortBy=${keyField}%20ASC`;
let wfsResponse = null;
if (alternativePayload) {
if (alternativePayload.type === 'gql') {
const { variablesDescriptor, ...payload } = alternativePayload.gql;
payload.variables.data[variablesDescriptor.featureProp] = rectangle2Feature(bbox);
payload.variables.data[variablesDescriptor.startIndexProp] = offset;
payload.variables.data[variablesDescriptor.typeNameProp] = featureType;
payload.variables.data[variablesDescriptor.countProp] = pageSize;

wfsResponse = await fetchWfsData(url, {
method: 'POST',
body: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json',
},
});
const queryName = payload.query.split('(')[0].replace('query ', ''); //strip queryName
await handleWfsResponse((wfsResponse as any)?.data[queryName], extent, offset, position);
} else {
throw 'API as alternative service still not supported';
}
} else {
const urlSeparator = url.includes('?') ? '&' : '?';
let wfsDataUrl = `${url}${urlSeparator}service=WFS&version=2.0.0&request=GetFeature&typeNames=${featureType}&outputFormat=application/json&bbox=${extent.join(
','
)},EPSG:4326&startIndex=${offset}&count=${pageSize}`;
if (keyField) {
wfsDataUrl += `&sortBy=${keyField}%20ASC`;
}
wfsResponse = await fetchWfsData(wfsDataUrl);
await handleWfsResponse(wfsResponse, extent, offset, position);
}
const wfsResponse = await fetchWfsData(wfsDataUrl);
await handleWfsResponse(wfsResponse, extent, offset, position);
} catch (error) {
console.error('Error fetching WFS data:', error);
updateMetadata(-1, -1);
Expand Down