So the point is to add a sprite for several elements in the middle of bounding box using data visualisation api or anything else.
I didn't find any option for this using standard methods from Autodesk.
Does anybody know how to handle this task?
Step-by-step flow:
Currently my function for adding sprites looks like this:
const findViewables = async (model, dbIDs) => {
const DataVizCore = Autodesk.DataVisualization.Core;
const viewableType = DataVizCore.ViewableType.SPRITE;
const spriteColor = new THREE.Color(0xffffff);
const style_default = new DataVizCore.ViewableStyle(viewableType, spriteColor, spriteNfDefault);
const style_success = new DataVizCore.ViewableStyle(viewableType, spriteColor, spriteNfSuccess);
const style_warning = new DataVizCore.ViewableStyle(viewableType, spriteColor, spriteNfWarning);
const style_informative = new DataVizCore.ViewableStyle(viewableType, spriteColor, spriteNfInformative);
const style_danger = new DataVizCore.ViewableStyle(viewableType, spriteColor, spriteNfDanger);
const viewableData = new DataVizCore.ViewableData();
viewableData.spriteSize = 40;
dbIDs
.filter((value, index, self) => {
return self.findIndex(v => v.nfNumber === value.nfNumber) === index;
})
.forEach(el => {
el.model.getData()?.instanceTree.enumNodeFragments(el.dbId, async fragId => {
const frags = el.model.getFragmentList();
let bbox = new THREE.Box3();
const { role } = el.model.getDocumentNode().data;
if (role === '2d') {
let boundsCallback = new Autodesk.Viewing.Private.BoundsCallback(bbox);
const mesh = frags.getVizmesh(fragId);
const vbr = new Autodesk.Viewing.Private.VertexBufferReader(mesh.geometry, window.NOP_VIEWER.impl.use2dInstancing);
vbr.enumGeomsForObject(el.dbId, boundsCallback);
}
if (role === '3d') {
frags.getWorldBounds(fragId, bbox);
}
const center = bbox.getCenter();
const viewable_default = new DataVizCore.SpriteViewable(center, style_default, el.dbId);
const viewable_success = new DataVizCore.SpriteViewable(center, style_success, el.dbId);
const viewable_warning = new DataVizCore.SpriteViewable(center, style_warning, el.dbId);
const viewable_informative = new DataVizCore.SpriteViewable(center, style_informative, el.dbId);
const viewable_danger = new DataVizCore.SpriteViewable(center, style_danger, el.dbId);
if (el.value === 'accepted') {
viewableData.addViewable(viewable_success);
} else if (el.value === 'declined') {
viewableData.addViewable(viewable_danger);
} else if (el.value === 'sent') {
viewableData.addViewable(viewable_informative);
} else if (el.value === 'submitted' || el.value === 'provided') {
viewableData.addViewable(viewable_warning);
} else {
viewableData.addViewable(viewable_default);
}
});
});
await viewableData.finish();
return viewableData;
};
With dfIds it works good, but when i try to add getExternalIdMapping it starts lagging and loop never ends because we have a lot of items and each item could have a lot of guids which should be replaced by dbIds.
Can you advise any efficient way to replace guids to dbIds or use guids as dbids?
I resolve this issue using getBulkProperties2
method.
On GEOMETRY_LOADED_EVENT i call a callback and inside it i use code below
event.target.model.getBulkProperties2(
dbids,
{ propFilter: '', categoryFilter: 'Identity Data', ignoreHidden: false, needsExternalId: true },
arg => {
const dict = new Object();
arg.forEach(el => {
dict[el.externalId] = el.dbId;
});
//seting state in react component and use it in useEffect
setMapExtIdData(dict);
},
err => {
console.log('bulk error', err);
},
);
after that i call function in useEffect see useEffect code
useEffect(() => {
if (view_role !== '2d') return;
if (!window?.NOP_VIEWER) return;
if (!needList) return;
if (!mapExtIdData.keys?.length && !needList?.length) return;
const prep = needList
.map(item => {
const geom_guids = item.geometries
?.map(geom => geom.data)
.map(elem => elem.markups)
.flat()
.map(elem => elem.geometry_objects)
.flat();
const dbIds = geom_guids.reduce((acc, value) => {
const dbidObj = mapExtIdData[value];
if (dbidObj !== undefined) {
acc.push(dbidObj);
}
return acc;
}, []);
return { nf: item.nf, value: item.status, dbIds };
})
.filter(el => el.dbIds.length);
const prep2 = prep.reduce((acc, value) => {
value.dbIds.forEach(el => {
acc.push({ nf: value.nf, value: value.value, dbId: el, model: window?.NOP_VIEWER.model });
});
return acc;
}, []);
addSprites(window?.NOP_VIEWER, window?.NOP_VIEWER.model, prep2, view_role);
}, [addSprites, mapExtIdData, needList, needList?.length, view_role]);
i know it is not perfect, but i still in process of development This code works well and add sprites to guids in few sec, faster than getExternalIdMapping. Please tell me if you need additional parts of code to understand the logic.