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
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"liveServer.settings.port": 5502
}
Binary file added resources/.DS_Store
Binary file not shown.
1,501 changes: 873 additions & 628 deletions resources/openbim-components.js

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions src/civil/RoadElevationNavigator/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as FRAGS from "bim-fragment";
import { UI, UIElement } from "../../base-types";
import { Drawer } from "../../ui";
import { Components } from "../../core";
Expand Down Expand Up @@ -26,6 +27,15 @@ export class RoadElevationNavigator extends RoadNavigator implements UI {
return null as any;
}

showKPStations(mesh: FRAGS.CurveMesh) {
// TODO: Discuss and Implement the Logic for Vertical Views and KP Stations
console.log(mesh);
}

clearKPStations(): void {
// Clearing KP Stations
}

private setUI() {
const drawer = new Drawer(this.components);
this.components.ui.add(drawer);
Expand Down
25 changes: 7 additions & 18 deletions src/civil/RoadNavigator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { Alignment, FragmentsGroup } from "bim-fragment";
import { Component, Event } from "../../base-types";
import { Components, Simple2DMarker, Simple2DScene } from "../../core";
import { CurveHighlighter } from "./src/curve-highlighter";
import { MarkerManager } from "../../core/Simple2DMarker/src/marker-manager";

export type CivilMarkerType = "hover" | "select";

Expand All @@ -17,6 +16,9 @@ export abstract class RoadNavigator extends Component<any> {

abstract highlighter: CurveHighlighter;

abstract showKPStations(curveMesh: FRAGS.CurveMesh): void;
abstract clearKPStations(): void;

readonly onHighlight = new Event<{
point: THREE.Vector3;
mesh: FRAGS.CurveMesh;
Expand All @@ -31,8 +33,6 @@ export abstract class RoadNavigator extends Component<any> {

private _curveMeshes: FRAGS.CurveMesh[] = [];

markerManager: MarkerManager;

mouseMarkers: {
hover: Simple2DMarker;
select: Simple2DMarker;
Expand All @@ -41,7 +41,6 @@ export abstract class RoadNavigator extends Component<any> {
protected constructor(components: Components) {
super(components);
this.scene = new Simple2DScene(this.components, false);
this.markerManager = new MarkerManager(this.components, this.scene);

this.mouseMarkers = {
select: this.newMouseMarker(components, "#ffffff"),
Expand Down Expand Up @@ -75,19 +74,6 @@ export abstract class RoadNavigator extends Component<any> {
throw new Error("Alignment not found!");
}

// TODO: Generate All The KPs and Stations
this.markerManager.addCivilMarker(
`0+${alignment.initialKP.toFixed(2)}`,
alignment[this.view][0].mesh,
"InitialKP"
);

this.markerManager.addCivilMarker(
"end",
alignment[this.view][alignment[this.view].length - 1].mesh,
"FinalKP"
);

for (const curve of alignment[this.view]) {
scene.add(curve.mesh);
this._curveMeshes.push(curve.mesh);
Expand Down Expand Up @@ -159,10 +145,14 @@ export abstract class RoadNavigator extends Component<any> {
await this.updateMarker(result, "select");

await this.onHighlight.trigger({ mesh, point: result.point });

this.showKPStations(mesh);

return;
}

this.highlighter.unSelect();
this.clearKPStations();
});
}

Expand All @@ -172,7 +162,6 @@ export abstract class RoadNavigator extends Component<any> {
this.onHighlight.reset();
await this.scene.dispose();
this._curveMeshes = [];
this.markerManager.dispose();
}

clear() {
Expand Down
257 changes: 257 additions & 0 deletions src/civil/RoadNavigator/src/kp-station.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
import * as FRAGS from "bim-fragment";
import * as THREE from "three";
import CameraControls from "camera-controls";
import { MarkerManager } from "../../../core/Simple2DMarker/src/marker-manager";
import { Components, SimpleRenderer } from "../../../core";
import { PostproductionRenderer } from "../../../navigation";

type CivilHighlightType = "horizontal" | "absolute" | "vertical";

export class KPStation {
private type: CivilHighlightType;

// private scene: THREE.Group | THREE.Scene;

private markerManager: MarkerManager;

private divisionLength = 100;

constructor(
components: Components,
renderer: SimpleRenderer | PostproductionRenderer,
scene: THREE.Group | THREE.Scene,
controls: CameraControls,
type: CivilHighlightType
) {
// this.scene = scene;
this.type = type;

this.markerManager = new MarkerManager(
components,
renderer,
scene,
controls
);
}

showKPStations(mesh: FRAGS.CurveMesh) {
if (this.type === "horizontal") {
const endKPStations = this.generateStartAndEndKP(mesh);
for (const [, data] of endKPStations) {
this.markerManager.addKPStation(data.value, data.normal);
}

const constantKPStations = this.generateConstantKP(mesh);
for (const [, data] of constantKPStations) {
this.markerManager.addKPStation(data.value, data.normal);
}
}
}

private generateStartAndEndKP(mesh: FRAGS.CurveMesh) {
const { alignment } = mesh.curve;
const data = new Map<
number,
{
value: string;
distance: number;
point: THREE.Vector3;
normal: THREE.Line;
}
>();

for (const curve of alignment.horizontal) {
const length = curve.getLength();
if (data.size > 0) {
const last = curve.index - 1;
const previousData = data.get(last);
const updateDistance = previousData!.distance + length;

const curvePosition = curve.mesh.geometry.getAttribute("position");
const lastSegmentIndex = curvePosition.count - 1;

const lastSegment = new THREE.Vector3();
lastSegment.x = curvePosition.getX(lastSegmentIndex);
lastSegment.y = curvePosition.getY(lastSegmentIndex);
lastSegment.z = curvePosition.getZ(lastSegmentIndex);

const normalLine = this.createNormalLine(curve.mesh);

data.set(curve.index, {
value: this.getShortendKPValue(updateDistance),
distance: updateDistance,
point: lastSegment,
normal: normalLine,
});
} else {
const curvePosition = curve.mesh.geometry.getAttribute("position");
const lastSegmentIndex = curvePosition.count - 1;

const lastSegment = new THREE.Vector3();
lastSegment.x = curvePosition.getX(lastSegmentIndex);
lastSegment.y = curvePosition.getY(lastSegmentIndex);
lastSegment.z = curvePosition.getZ(lastSegmentIndex);

const normalLine = this.createNormalLine(curve.mesh);

data.set(curve.index, {
value: this.getShortendKPValue(length),
distance: length,
point: lastSegment,
normal: normalLine,
});
}
}

return data;
}

private createNormalLine(curveMesh: FRAGS.CurveMesh) {
const lastIndex = curveMesh.geometry.attributes.position.count - 1;
const secondLastIndex = lastIndex - 1;

const lastPoint = new THREE.Vector3();
lastPoint.x = curveMesh.geometry.attributes.position.getX(lastIndex);
lastPoint.y = curveMesh.geometry.attributes.position.getY(lastIndex);
lastPoint.z = curveMesh.geometry.attributes.position.getZ(lastIndex);

const secondLastPoint = new THREE.Vector3();
secondLastPoint.x =
curveMesh.geometry.attributes.position.getX(secondLastIndex);
secondLastPoint.y =
curveMesh.geometry.attributes.position.getY(secondLastIndex);
secondLastPoint.z =
curveMesh.geometry.attributes.position.getZ(secondLastIndex);

const direction = new THREE.Vector3().subVectors(
lastPoint,
secondLastPoint
);

const normal = direction
.clone()
.applyAxisAngle(new THREE.Vector3(0, 0, 1), Math.PI * 0.5)
.normalize();
const normalGeom = new THREE.BufferGeometry().setFromPoints([
normal.clone().setLength(10).add(lastPoint),
normal.clone().setLength(-10).add(lastPoint),
]);
const normalLine = new THREE.Line(normalGeom);
// this.scene.add(normalLine);

return normalLine;
}

private generateConstantKP(mesh: FRAGS.CurveMesh) {
const { alignment } = mesh.curve;
const data = new Map<
number,
{
value: string;
distance: number;
point: THREE.Vector3;
normal: THREE.Line;
}
>();

const alignmentLength = alignment.getLength("horizontal");
const divisions = Math.floor(alignmentLength / this.divisionLength);
for (let i = 0; i < divisions; i++) {
const percentage = i / divisions;
const kpPoint = alignment.getPointAt(percentage, "horizontal");
const length = alignmentLength * percentage;
// const curve = alignment.getCurveAt(percentage, "horizontal");
const normalLine = this.getNormal(alignment, kpPoint);
data.set(i, {
value: this.getShortendKPValue(length),
distance: length,
point: kpPoint,
normal: normalLine,
});
}

return data;
}

// TODO: Move Generation of Points to Previous Method Call
private getNormal(curve: FRAGS.Alignment, point: THREE.Vector3) {
const pointsInCurve = [];
const normalPoints = {
start: new THREE.Vector3(),
end: new THREE.Vector3(),
};

for (let i = 0; i < curve.horizontal.length; i++) {
const curveMesh = curve.horizontal[i].mesh;
const position = curveMesh.geometry.attributes.position;
const length = position.count;

for (let j = 0; j < length; j++) {
const x = position.getX(j);
const y = position.getY(j);
const z = position.getZ(j);
pointsInCurve.push(new THREE.Vector3(x, y, z));
}
}

for (let i = 0; i < pointsInCurve.length - 1; i++) {
const p1 = pointsInCurve[i];
const p2 = pointsInCurve[i + 1];

const distanceP1 = p1.distanceTo(point);
const distanceP2 = p2.distanceTo(point);
const distanceP1P2 = p1.distanceTo(p2);

const epsilion = 0.00001;
const isOnLine = Math.abs(distanceP1 + distanceP2 - distanceP1P2);

if (isOnLine < epsilion) {
normalPoints.start = p1;
normalPoints.end = p2;
}
}

const direction = new THREE.Vector3().subVectors(
normalPoints.end,
normalPoints.start
);
const normal = direction
.clone()
.applyAxisAngle(new THREE.Vector3(0, 0, 1), Math.PI * 0.5)
.normalize();
const normalGeom = new THREE.BufferGeometry().setFromPoints([
normal.clone().setLength(10).add(point),
normal.clone().setLength(-10).add(point),
]);
const normalLine = new THREE.Line(
normalGeom,
new THREE.LineBasicMaterial({ color: 0xff0000 })
);
return normalLine;
}

private getShortendKPValue(value: number) {
const formattedValue = value.toFixed(2);
const [integerPart, fractionalPart] = formattedValue.toString().split(".");
const formattedFractionalPart = fractionalPart || "00";

if (parseInt(integerPart, 10) > 1000 && parseInt(integerPart, 10) < 10000) {
const [first, ...rest] = integerPart;
return `${first}+${rest.join("")}.${formattedFractionalPart}`;
}
if (parseInt(integerPart, 10) > 10000) {
const [first, second, ...rest] = integerPart;
return `${first}${second}+${rest.join("")}.${formattedFractionalPart}`;
}

return `0+${integerPart.padStart(3, "0")}.${formattedFractionalPart}`;
}

clearKPStations() {
this.markerManager.clearMarkers();
}

dispose() {
this.markerManager.dispose();
}
}
Loading