Skip to content

Commit

Permalink
feat(pointcloud): Highlighing pointCLoud by the attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
Kerwin-L committed Feb 15, 2023
1 parent 6be1167 commit 1f7ac06
Show file tree
Hide file tree
Showing 12 changed files with 233 additions and 249 deletions.
122 changes: 96 additions & 26 deletions packages/lb-annotation/src/core/pointCloud/highlightWorker.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,48 @@
class PointCloudUtils {
static genColorByCoord(x, y, z) {
if (z <= 0) {
return [128, 128, 128];
// COLOR_MAP_JET
function createColorMapJet() {
let s;
const p = new Array(256).fill('').map(() => new Array(3).fill(''));
for (let i = 0; i < 20; i++) {
for (s = 0; s < 32; s++) {
p[s][0] = 128 + 4 * s;
p[s][1] = 0;
p[s][2] = 0;
}

if (z < 5) {
return [255, 0, 0];
p[32][0] = 255;
p[32][1] = 0;
p[32][2] = 0;
for (s = 0; s < 63; s++) {
p[33 + s][0] = 255;
p[33 + s][1] = 4 + 4 * s;
p[33 + s][2] = 0;
}

if (z < 10) {
return [0, 255, 0];
p[96][0] = 254;
p[96][1] = 255;
p[96][2] = 2;
for (s = 0; s < 62; s++) {
p[97 + s][0] = 250 - 4 * s;
p[97 + s][1] = 255;
p[97 + s][2] = 6 + 4 * s;
}
p[159][0] = 1;
p[159][1] = 255;
p[159][2] = 254;
for (s = 0; s < 64; s++) {
p[160 + s][0] = 0;
p[160 + s][1] = 252 - s * 4;
p[160 + s][2] = 255;
}
for (s = 0; s < 32; s++) {
p[224 + s][0] = 0;
p[224 + s][1] = 0;
p[224 + s][2] = 252 - 4 * s;
}

return [0, 0, 255];
}

static getStandardColorByCoord(x, y, z) {
const pdColor = this.genColorByCoord(x, y, z);
return pdColor.map((hex) => hex / 255);
}
return p;
}

const COLOR_MAP_JET = createColorMapJet();

export function isInPolygon(checkPoint, polygonPoints, lineType = 0) {
let counter = 0;
let i;
Expand Down Expand Up @@ -63,29 +85,77 @@ export function isInPolygon(checkPoint, polygonPoints, lineType = 0) {
return true;
}

function getNewColorByBox({ zMin, zMax, polygonPointList, attribute, x, y, z, colorList }) {
const inPolygon = isInPolygon({ x, y }, polygonPointList);
if (inPolygon && z >= zMin && z <= zMax) {
if (colorList[attribute]) {
return colorList[attribute].rgba.slice(0, 3).map((v) => v / 255);
}

return [1, 0, 0];
}
}

onmessage = function onmessage(e) {
const { zMin, zMax, polygonPointList, position: points, color } = e.data;
const { position: points, color, cuboidList, colorList } = e.data;
let num = 0;

let maxZ = -Number.MAX_SAFE_INTEGER;
let minZ = Number.MAX_SAFE_INTEGER;
for (let i = 0; i < points.length; i += 3) {
const z = points[i + 2];
if (z) {
if (z < minZ) {
minZ = z;
}
if (z > maxZ) {
maxZ = z;
}
}
}

// Loop to determine if it is in range
for (let i = 0; i < points.length; i += 3) {
const x = points[i];
const y = points[i + 1];
const z = points[i + 2];

const inPolygon = isInPolygon({ x, y }, polygonPointList);
const newColorInfo = cuboidList
.map((v) => {
return getNewColorByBox({
polygonPointList: v.polygonPointList,
zMin: v.zMin,
zMax: v.zMax,
x,
y,
z,
attribute: v.attribute,
colorList,
});
})
.filter((v) => v)
.pop();

if (inPolygon && z >= zMin && z <= zMax) {
// Notice. Scope: [0, 1];
if (newColorInfo) {
num++;
color[i] = 0;
color[i + 1] = 1;
color[i + 2] = 1;
} else {
// DEFAULT COLOR RENDERc
const [r, g, b] = PointCloudUtils.getStandardColorByCoord(x, y, z);
const [r, g, b] = newColorInfo;
color[i] = r;
color[i + 1] = g;
color[i + 2] = b;
} else {
// // DEFAULT COLOR RENDERc
// Recover the originPoint

// const [r, g, b] = PointCloudUtils.genColorByZ({ z, minZ, maxZ });
const L = maxZ - minZ;

const index = Math.floor(((z - minZ) / L) * 255);
const newColor = COLOR_MAP_JET[index];
const [r, g, b] = newColor;
color[i] = r / 255;
color[i + 1] = g / 255;
color[i + 2] = b / 255;
}
}

Expand Down
82 changes: 52 additions & 30 deletions packages/lb-annotation/src/core/pointCloud/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
IPointCloudConfig,
toolStyleConverter,
} from '@labelbee/lb-utils';
import { PointsMaterial, Shader } from 'three';
import { BufferAttribute, PointsMaterial, Shader } from 'three';
import HighlightWorker from 'web-worker:./highlightWorker.js';
import FilterBoxWorker from 'web-worker:./filterBoxWorker.js';
import { isInPolygon } from '@/utils/tool/polygonTool';
Expand Down Expand Up @@ -47,7 +47,7 @@ interface IProps {
}

const DEFAULT_DISTANCE = 30;
const highlightWorker = new HighlightWorker();
const highlightWorker = new HighlightWorker({ type: 'module' });

export class PointCloud {
public renderer: THREE.WebGLRenderer;
Expand Down Expand Up @@ -272,6 +272,17 @@ export class PointCloud {
this.render();
}

public getAllAttributeColor(boxes: IPointCloudBox[]) {
return boxes.reduce((acc: { [k: string]: any }, box) => {
acc[box.attribute] = toolStyleConverter.getColorFromConfig(
{ attribute: box.attribute },
{ ...this.config, attributeConfigurable: true },
{},
);
return acc;
}, {});
}

/*
* Remove exist box and add new one to scene
* @param boxParams
Expand Down Expand Up @@ -598,40 +609,51 @@ export class PointCloud {
};

/**
* It needs to be updated after load PointCLoud's data.
* It needs to be updated after load PointCloud's data.
* @param boxParams
* @returns
*/
public highlightOriginPointCloud(boxParams: IPointCloudBox) {
if (boxParams && highlightWorker) {
// Temporarily turn off highlighting
public highlightOriginPointCloud(pointCloudBoxList?: IPointCloudBox[]) {
const oldPointCloud = this.scene.getObjectByName(this.pointCloudObjectName) as THREE.Points;
if (!oldPointCloud) {
return;
}

// const oldPointCloud: any = this.scene.getObjectByName(this.pointCloudObjectName);
// if (!oldPointCloud) {
// return;
// }
return new Promise<BufferAttribute[] | undefined>((resolve) => {
if (window.Worker) {
const newPointCloudBoxList = pointCloudBoxList ? [...pointCloudBoxList] : [];

const cuboidList = newPointCloudBoxList.map((v) => getCuboidFromPointCloudBox(v));
const colorList = this.getAllAttributeColor(cuboidList);
const params = {
cuboidList,
position: oldPointCloud.geometry.attributes.position.array,
color: oldPointCloud.geometry.attributes.color.array,
colorList,
};

// if (window.Worker) {
// const { zMin, zMax, polygonPointList } = getCuboidFromPointCloudBox(boxParams);

// const params = {
// boxParams,
// zMin,
// zMax,
// polygonPointList,
// position: oldPointCloud.geometry.attributes.position.array,
// color: oldPointCloud.geometry.attributes.color.array,
// };

// highlightWorker.postMessage(params);
// highlightWorker.onmessage = (e: any) => {
// const { color } = e.data;
// oldPointCloud.geometry.attributes.color.array = color;
// oldPointCloud.geometry.attributes.color.needsUpdate = true;
// this.render();
// };
// }
highlightWorker.postMessage(params);
highlightWorker.onmessage = (e: any) => {
const { color } = e.data;
const colorAttribute = new THREE.BufferAttribute(color, 3);
colorAttribute.needsUpdate = true;
oldPointCloud.geometry.setAttribute('color', colorAttribute);
resolve(color);
this.render();
};
}
});
}

public updateColor(color: any[]) {
const oldPointCloud = this.scene.getObjectByName(this.pointCloudObjectName) as THREE.Points;
if (oldPointCloud) {
const colorAttribute = new THREE.BufferAttribute(color, 3);
colorAttribute.needsUpdate = true;
oldPointCloud.geometry.setAttribute('color', colorAttribute);

this.render();
}
}

/**
Expand Down
1 change: 1 addition & 0 deletions packages/lb-annotation/src/core/pointCloud/matrix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export function getCuboidFromPointCloudBox(boxParams: IPointCloudBox) {
const zMin = center.z - depth / 2;

return {
...boxParams,
polygonPointList,
zMax,
zMin,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ const PointCloudSideView = ({ currentData, config, checkMode }: IA2MapStateProps

synchronizeTopView(newBoxParams, newPolygon, ptCtx.topViewInstance, ptCtx.mainViewInstance);
synchronizeSideView(newBoxParams, newPolygon, ptCtx.sideViewInstance, currentData.url);
ptCtx.mainViewInstance.highlightOriginPointCloud(newBoxParams);
updateSelectedBox(newBoxParams);
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface IPointCloudContext extends IPointCloudContextInstances {
addSelectedID: (selectedID: string) => void;
selectedAllBoxes: () => void;
selectedID: string;
addPointCloudBox: (boxParams: IPointCloudBox) => void;
addPointCloudBox: (boxParams: IPointCloudBox) => IPointCloudBox[];

polygonList: IPolygonData[];
setPolygonList: (polygonList: IPolygonData[]) => void;
Expand All @@ -33,6 +33,8 @@ export interface IPointCloudContext extends IPointCloudContextInstances {
setZoom: (zoom: number) => void;

history: ActionsHistory; // Operation History

syncAllViewPointCloudColor: (newPointCloudList?: IPointCloudBox[]) => void;
}

export const PointCloudContext = React.createContext<IPointCloudContext>({
Expand All @@ -41,21 +43,22 @@ export const PointCloudContext = React.createContext<IPointCloudContext>({
selectedID: '',
selectedIDs: [],
valid: true,
setSelectedIDs: () => {},
setPointCloudResult: () => {},
setPointCloudValid: () => {},
setTopViewInstance: () => {},
setSideViewInstance: () => {},
setBackViewInstance: () => {},
setMainViewInstance: () => {},
addSelectedID: () => {},
selectedAllBoxes: () => {},
addPointCloudBox: () => {},
setPolygonList: () => {},
setSelectedIDs: () => { },
setPointCloudResult: () => { },
setPointCloudValid: () => { },
setTopViewInstance: () => { },
setSideViewInstance: () => { },
setBackViewInstance: () => { },
setMainViewInstance: () => { },
addSelectedID: () => { },
selectedAllBoxes: () => { },
addPointCloudBox: () => { return [] },
setPolygonList: () => { },

zoom: 1,
setZoom: () => {},
setZoom: () => { },
history: new ActionsHistory(),
syncAllViewPointCloudColor: () => { },
});

export const PointCloudProvider: React.FC<{}> = ({ children }) => {
Expand All @@ -78,7 +81,9 @@ export const PointCloudProvider: React.FC<{}> = ({ children }) => {
const selectedPointCloudBox = pointCloudBoxList.find((v) => v.id === selectedID);

const addPointCloudBox = (box: IPointCloudBox) => {
setPointCloudResult(pointCloudBoxList.concat(box));
const newPointCloudList = pointCloudBoxList.concat(box)
setPointCloudResult(newPointCloudList);
return newPointCloudList;
};

const setPointCloudValid = (valid?: boolean) => {
Expand Down Expand Up @@ -116,6 +121,21 @@ export const PointCloudProvider: React.FC<{}> = ({ children }) => {
setSelectedIDs(pointCloudBoxList.map((i) => i.id));
};

/**
* Synchronize the highlighted pointCloud for all views.
* @param pointCloudList
*/
const syncAllViewPointCloudColor = (pointCloudList?: IPointCloudBox[]) => {
const colorPromise = mainViewInstance?.highlightOriginPointCloud(pointCloudList);
colorPromise?.then((color) => {
[topViewInstance, sideViewInstance, backViewInstance].forEach(instance => {
if (color) {
instance?.pointCloudInstance?.updateColor(color);
}
})
})
}

return {
selectedID,
pointCloudBoxList,
Expand All @@ -141,6 +161,7 @@ export const PointCloudProvider: React.FC<{}> = ({ children }) => {
zoom,
setZoom,
history,
syncAllViewPointCloudColor,
};
}, [
valid,
Expand Down
Loading

0 comments on commit 1f7ac06

Please sign in to comment.