-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a569902
commit 1960bfe
Showing
2 changed files
with
337 additions
and
197 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,319 @@ | ||
import type {CustomDataSource, Model} from '@cesium/engine'; | ||
import { | ||
ArcType, | ||
Axis, | ||
CallbackProperty, | ||
Cartesian2, | ||
Cartesian3, | ||
Color, | ||
Matrix3, | ||
Matrix4, | ||
Plane, | ||
Quaternion, | ||
TranslationRotationScale, | ||
} from '@cesium/engine'; | ||
import type {UploadedModel} from './ngv-plugin-cesium-upload.js'; | ||
|
||
export type PlaneColorOptions = { | ||
material?: Color; | ||
outline?: boolean; | ||
outlineColor?: Color; | ||
}; | ||
|
||
export type EdgeStyleOptions = { | ||
width?: number; | ||
material?: Color; | ||
}; | ||
|
||
export type CornerPointStyleOptions = { | ||
radii?: Cartesian3; | ||
material?: Color; | ||
}; | ||
|
||
const DefaultPlaneColorOptions = { | ||
material: Color.RED.withAlpha(0.1), | ||
outline: true, | ||
outlineColor: Color.WHITE, | ||
}; | ||
|
||
const DefaultEdgeStyles = { | ||
width: 10, | ||
material: Color.WHITE.withAlpha(0.3), | ||
}; | ||
|
||
const DefaultCornerPointStyles = { | ||
radii: new Cartesian3(10, 10, 10), | ||
material: Color.BROWN, | ||
}; | ||
|
||
const SIDE_PLANES: Plane[] = [ | ||
new Plane(new Cartesian3(0, 0, 1), 0.5), | ||
new Plane(new Cartesian3(0, 0, -1), 0.5), | ||
new Plane(new Cartesian3(0, 1, 0), 0.5), | ||
new Plane(new Cartesian3(0, -1, 0), 0.5), | ||
new Plane(new Cartesian3(1, 0, 0), 0.5), | ||
new Plane(new Cartesian3(-1, 0, 0), 0.5), | ||
]; | ||
|
||
const CORNER_POINT_VECTORS = [ | ||
new Cartesian3(0.5, 0.5, 0.5), | ||
new Cartesian3(0.5, -0.5, 0.5), | ||
new Cartesian3(-0.5, -0.5, 0.5), | ||
new Cartesian3(-0.5, 0.5, 0.5), | ||
]; | ||
|
||
const LOCAL_EDGES: [Cartesian3, Cartesian3][] = []; | ||
CORNER_POINT_VECTORS.forEach((vector, i) => { | ||
const upPoint = vector; | ||
const downPoint = Cartesian3.clone(upPoint, new Cartesian3()); | ||
downPoint.z *= -1; | ||
const nextUpPoint = CORNER_POINT_VECTORS[(i + 1) % 4]; | ||
const nextDownPoint = Cartesian3.clone(nextUpPoint, new Cartesian3()); | ||
nextDownPoint.z *= -1; | ||
const verticalEdge: [Cartesian3, Cartesian3] = [upPoint, downPoint]; | ||
// const topEdge: [Cartesian3, Cartesian3] = [nextUpPoint, upPoint]; | ||
// const bottomEdge: [Cartesian3, Cartesian3] = [nextDownPoint, downPoint]; | ||
LOCAL_EDGES.push(verticalEdge); | ||
}); | ||
|
||
const scaleScratch = new Cartesian3(); | ||
export function getScaleFromMatrix(matrix: Matrix4): Cartesian3 { | ||
return Matrix4.getScale(matrix, scaleScratch); | ||
} | ||
|
||
const dimensionsScratch = new Cartesian3(); | ||
function getScaledDimensions(model: UploadedModel): Cartesian3 { | ||
Cartesian3.clone(model.id.dimensions, dimensionsScratch); | ||
Cartesian3.multiplyComponents( | ||
getScaleFromMatrix(model.modelMatrix), | ||
dimensionsScratch, | ||
dimensionsScratch, | ||
); | ||
return dimensionsScratch; | ||
} | ||
|
||
const scratchRotationMatrix = new Matrix3(); | ||
const scratchRotationQuaternion = new Quaternion(); | ||
export function getRotationQuaternionFromMatrix(matrix: Matrix4): Quaternion { | ||
return Quaternion.fromRotationMatrix( | ||
Matrix4.getRotation(matrix, scratchRotationMatrix), | ||
scratchRotationQuaternion, | ||
); | ||
} | ||
|
||
const scratchTranslation = new Cartesian3(); | ||
export function getTranslationFromMatrix(matrix: Matrix4): Cartesian3 { | ||
return Matrix4.getTranslation(matrix, scratchTranslation); | ||
} | ||
|
||
const scratchTranslationRotationDimensionsMatrix = new Matrix4(); | ||
export function getTranslationRotationDimensionsMatrix( | ||
model: UploadedModel, | ||
result = scratchTranslationRotationDimensionsMatrix, | ||
): Matrix4 { | ||
return Matrix4.fromTranslationRotationScale( | ||
new TranslationRotationScale( | ||
getTranslationFromMatrix(model.modelMatrix), | ||
getRotationQuaternionFromMatrix(model.modelMatrix), | ||
getScaledDimensions(model), | ||
), | ||
result, | ||
); | ||
} | ||
|
||
const scratchTranslationRotationScaleMatrix = new Matrix4(); | ||
export function getTranslationRotationScaleMatrix( | ||
matrix: Matrix4, | ||
result = scratchTranslationRotationScaleMatrix, | ||
): Matrix4 { | ||
return Matrix4.fromTranslationRotationScale( | ||
new TranslationRotationScale( | ||
getTranslationFromMatrix(matrix), | ||
getRotationQuaternionFromMatrix(matrix), | ||
getScaleFromMatrix(matrix), | ||
), | ||
result, | ||
); | ||
} | ||
|
||
const centerDiffScratch = new Cartesian3(); | ||
export function getModelCenterDiff(model: Model): Cartesian3 { | ||
return Cartesian3.subtract( | ||
model.boundingSphere.center, | ||
getTranslationFromMatrix(model.modelMatrix), | ||
centerDiffScratch, | ||
); | ||
} | ||
|
||
const scaleMatrixScratch = new Matrix4(); | ||
const planeScaleScratch = new Cartesian3(); | ||
function getPlaneScale(model: UploadedModel, normalAxis: Axis) { | ||
const dimensions = getScaledDimensions(model); | ||
if (normalAxis === Axis.Y) { | ||
dimensions.clone(planeScaleScratch); | ||
} else { | ||
let scaleArray: number[] = []; | ||
if (normalAxis === Axis.X) { | ||
scaleArray = [dimensions.x, dimensions.y, dimensions.z]; | ||
} else if (normalAxis === Axis.Z) { | ||
scaleArray = [dimensions.y, dimensions.x, dimensions.z]; | ||
} | ||
Cartesian3.fromArray(scaleArray, 0, planeScaleScratch); | ||
} | ||
|
||
return Matrix4.fromScale(planeScaleScratch, scaleMatrixScratch); | ||
} | ||
|
||
const planeDimensionsScratch = new Cartesian2(); | ||
function getPlaneDimensions(model: UploadedModel, normalAxis: Axis) { | ||
const dimensions = getScaledDimensions(model); | ||
let dimensionsArray: number[] = []; | ||
|
||
if (normalAxis === Axis.X) { | ||
dimensionsArray = [dimensions.y, dimensions.z]; | ||
} else if (normalAxis === Axis.Y) { | ||
dimensionsArray = [dimensions.x, dimensions.z]; | ||
} else if (normalAxis === Axis.Z) { | ||
dimensionsArray = [dimensions.x, dimensions.y]; | ||
} | ||
|
||
return Cartesian2.fromArray(dimensionsArray, 0, planeDimensionsScratch); | ||
} | ||
|
||
export function createPlaneEntity( | ||
dataSource: CustomDataSource, | ||
plane: Plane, | ||
model: UploadedModel, | ||
colorOptions: PlaneColorOptions = DefaultPlaneColorOptions, | ||
): void { | ||
const normalAxis: Axis = plane.normal.x | ||
? Axis.X | ||
: plane.normal.y | ||
? Axis.Y | ||
: Axis.Z; | ||
|
||
dataSource.entities.add({ | ||
position: new CallbackProperty(() => model.boundingSphere.center, false), | ||
orientation: new CallbackProperty( | ||
() => getRotationQuaternionFromMatrix(model.modelMatrix), | ||
false, | ||
), | ||
plane: { | ||
plane: new CallbackProperty( | ||
() => Plane.transform(plane, getPlaneScale(model, normalAxis)), | ||
false, | ||
), | ||
dimensions: new CallbackProperty( | ||
() => getPlaneDimensions(model, normalAxis), | ||
false, | ||
), | ||
...colorOptions, | ||
}, | ||
}); | ||
} | ||
export function createEdge( | ||
dataSource: CustomDataSource, | ||
model: UploadedModel, | ||
edge: Cartesian3[], | ||
styles: EdgeStyleOptions = DefaultEdgeStyles, | ||
): void { | ||
const positions = [new Cartesian3(), new Cartesian3()]; | ||
dataSource.entities.add({ | ||
polyline: { | ||
show: true, | ||
positions: new CallbackProperty(() => { | ||
const matrix = getTranslationRotationDimensionsMatrix(model); | ||
Matrix4.multiplyByPoint(matrix, edge[0], positions[0]); | ||
Matrix4.multiplyByPoint(matrix, edge[1], positions[1]); | ||
const centerDiff = getModelCenterDiff(model); | ||
Cartesian3.add(positions[0], centerDiff, positions[0]); | ||
Cartesian3.add(positions[1], centerDiff, positions[1]); | ||
return positions; | ||
}, false), | ||
width: styles.width, | ||
material: styles.material, | ||
arcType: ArcType.NONE, | ||
}, | ||
}); | ||
} | ||
|
||
export function createCornerPoint( | ||
dataSource: CustomDataSource, | ||
model: UploadedModel, | ||
edges: Cartesian3[], | ||
styles: CornerPointStyleOptions = DefaultCornerPointStyles, | ||
): void { | ||
const position = new Cartesian3(); | ||
edges.forEach((localEdge) => { | ||
dataSource.entities.add({ | ||
position: new CallbackProperty(() => { | ||
const matrix = getTranslationRotationDimensionsMatrix(model); | ||
Matrix4.multiplyByPoint(matrix, localEdge, position); | ||
const centerDiff = getModelCenterDiff(model); | ||
Cartesian3.add(position, centerDiff, position); | ||
return position; | ||
}, false), | ||
ellipsoid: { | ||
show: true, | ||
radii: styles.radii, | ||
material: styles.material, | ||
}, | ||
}); | ||
}); | ||
} | ||
|
||
export function showModelBBox( | ||
dataSources: { | ||
topDownPlanesDataSource?: CustomDataSource; | ||
sidePlanesDataSource?: CustomDataSource; | ||
edgeLinesDataSource?: CustomDataSource; | ||
cornerPointsDataSource?: CustomDataSource; | ||
}, | ||
model: UploadedModel, | ||
styles: { | ||
planeColorOptions?: PlaneColorOptions; | ||
edgeStyleOptions?: EdgeStyleOptions; | ||
cornerPointStyleOptions: CornerPointStyleOptions; | ||
} = { | ||
planeColorOptions: DefaultPlaneColorOptions, | ||
edgeStyleOptions: DefaultEdgeStyles, | ||
cornerPointStyleOptions: DefaultCornerPointStyles, | ||
}, | ||
): void { | ||
const topDownPlanesDataSource = dataSources.topDownPlanesDataSource; | ||
const sidePlanesDataSource = dataSources.sidePlanesDataSource; | ||
if (topDownPlanesDataSource || sidePlanesDataSource) { | ||
SIDE_PLANES.forEach((plane) => { | ||
const normalAxis: Axis = plane.normal.x | ||
? Axis.X | ||
: plane.normal.y | ||
? Axis.Y | ||
: Axis.Z; | ||
|
||
const dataSource = | ||
normalAxis === Axis.Z ? topDownPlanesDataSource : sidePlanesDataSource; | ||
if (dataSource) | ||
createPlaneEntity(dataSource, plane, model, styles.planeColorOptions); | ||
}); | ||
} | ||
if (dataSources.edgeLinesDataSource) { | ||
LOCAL_EDGES.forEach((edge) => | ||
createEdge( | ||
dataSources.edgeLinesDataSource, | ||
model, | ||
edge, | ||
styles.edgeStyleOptions, | ||
), | ||
); | ||
} | ||
if (dataSources.cornerPointsDataSource) { | ||
LOCAL_EDGES.forEach((edge) => | ||
createCornerPoint( | ||
dataSources.cornerPointsDataSource, | ||
model, | ||
edge, | ||
styles.cornerPointStyleOptions, | ||
), | ||
); | ||
} | ||
} |
Oops, something went wrong.