Hi,
I want to remove all holes on these smart solids automatically in the attached DGN file. How can I do that?
sink.dgn
Hi Ahmet,
If your slab is primarily created, all its faceId.nodeId should be 1. Based on this, I wrote the following code to retain the faces which nodeId = 1 and remove all other faces. This seems meet your requirement.
MSElementDescrP edP = NULL; KIBODY *pBody = NULL; KIENTITY_LIST* pFaceList = NULL; KIENTITY_LIST* pRemovedFaceList = NULL; Transform trans; int cnt; mdlAssoc_getElementDescr(&edP, NULL, 875L, ACTIVEMODEL, FALSE); mdlKISolid_elementToBody2(&pBody, &trans, edP, ACTIVEMODEL, 1L, FALSE); mdlElmdscr_freeAll(&edP); mdlKISolid_listCreate(&pRemovedFaceList); mdlKISolid_listCreate(&pFaceList); mdlKISolid_getFaceList(pFaceList, pBody); mdlKISolid_listCount(&cnt, pFaceList); for (int i = 0; i < cnt; i++) { KIFACE *pFace; FaceId faceId; mdlKISolid_listNthEl(&pFace, pFaceList, i); mdlKISolid_idFromFace(&faceId, pFace, TRUE); if (1 != faceId.nodeId) { mdlKISolid_listAdd(pRemovedFaceList, pFace); } } mdlKISolid_listDelete(&pFaceList); //Here can't free body because it will be used later KIENTITY_LIST* pBodyList = NULL; mdlKISolid_listCreate(&pBodyList); if (SUCCESS == mdlKISolid_removeFaces2(pBodyList, pRemovedFaceList, HEAL_Parent, TRUE)) { mdlKISolid_listCount(&cnt, pBodyList); for (int i = 0; i < cnt; i++) { KIBODY *pCreatedBody = NULL; mdlKISolid_listNthEl(&pCreatedBody, pBodyList, i); mdlKISolid_bodyToElement(&edP, pCreatedBody, TRUE, -1, NULL, ACTIVEMODEL); mdlKISolid_beginCurrTrans(ACTIVEMODEL); mdlElmdscr_transform(edP, &trans); mdlKISolid_endCurrTrans(); mdlElmdscr_add(edP); mdlElmdscr_freeAll(&edP); } } mdlKISolid_listDelete(&pRemovedFaceList); mdlKISolid_listDelete(&pBodyList); mdlKISolid_freeBody(pBody);
HTH, YongAn
Hi Yongan, Thank you so much for the code. I tried it but all faceId.nodeId values return 1. How can I distinguish holes?
Kind regards,
Sedat AlisAEC Technology Inc.
Unknown said: Do you mind to upload your DGN file and let us analyze it ?
Do you mind to upload your DGN file and let us analyze it ?
Hi Yongan,
Thank you so much. :)
DGN file is attached.010614S01116@001.dgn
I realized that your creation solid method is different than me. I firstly create a base slab and then use "Cut Solids by Curves" tool to create holes on base slab. So my code is just appropriate for this case. I inferred that your creation method is firstly creating a 2D group hole profile element and then extruding this profile to solid.
Please see my attached DGN file. Two solids are same from its appearance but with different creation method. The red one is mine and my code is suitable for it.
010614S01116-test.dgn
I will investigate your situation and try to write a more common code to suit two cases.
Regards, YongAn
Unknown said: I realized that your creation solid method is different than me. I firstly create a base slab and then use "Cut Solids by Curves" tool to create holes on base slab. So my code is just appropriate for this case. I inferred that your creation method is firstly creating a 2D group hole profile element and then extruding this profile to solid.
You are right.
Unknown said: I will investigate your situation and try to write a more common code to suit two cases.
Unknown said: Hi Ahmet, I have some ideas to do this but haven't implemented by coding. 1. Collect and record all edge ids in internal loops (using mdlKISolid_loopExternal to determine which loop is external or internal); 2. Iterate every face and remove internal loops for every face (using an undocumented function mdlKISolid_deleteLoopsFromSheetBody); 3. Iterate every face and remove all faces which has internal loop's edge (using the result of 1). 4. Sew all faces into final solid (using mdlKISolid_sewBodies).
Hi Ahmet, I have some ideas to do this but haven't implemented by coding. 1. Collect and record all edge ids in internal loops (using mdlKISolid_loopExternal to determine which loop is external or internal); 2. Iterate every face and remove internal loops for every face (using an undocumented function mdlKISolid_deleteLoopsFromSheetBody); 3. Iterate every face and remove all faces which has internal loop's edge (using the result of 1). 4. Sew all faces into final solid (using mdlKISolid_sewBodies).
I wish to know all undocumented functions and conclude the job. :)
I wrote following long code snippet to process your case and it works. But for more complex cases, it doesn't work. FYI.
class edgeId_finder { public: edgeId_finder(const EdgeId edgeId) :m_edgeId(edgeId){} bool operator ()(const vector<EdgeId>::value_type &value) { return (value.faces[0].entityId == m_edgeId.faces[0].entityId && value.faces[0].nodeId == m_edgeId.faces[0].nodeId && value.faces[1].entityId == m_edgeId.faces[1].entityId && value.faces[1].nodeId == m_edgeId.faces[1].nodeId); } private: EdgeId m_edgeId; }; void getInternalEdgeArray(vector<EdgeId>& internalEdgeArray, KIBODY* pBody) { KIENTITY_LIST* pLoopList = NULL; int cnt; mdlKISolid_listCreate(&pLoopList); mdlKISolid_getLoopList(pLoopList, pBody); mdlKISolid_listCount(&cnt, pLoopList); for (int i = 0; i < cnt; i++) { KILOOP* pLoop; mdlKISolid_listNthEl(&pLoop, pLoopList, i); //mdlKISolid_loopExternal can't function for unclear loop case KIFACE* pFace; KIENTITY_LIST* pFaceList = NULL; mdlKISolid_faceFromLoop(&pFace, pLoop); mdlKISolid_listCreate(&pFaceList); mdlKISolid_getEdgeListFromFace(pFaceList, pFace); int cntFace; mdlKISolid_listCount(&cntFace, pFaceList); mdlKISolid_listDelete(&pFaceList); if (cntFace < 6) continue; int isExternal; mdlKISolid_loopExternal(&isExternal, pLoop); if (!isExternal) { KICOEDGE* pCoEdge; int status = mdlKISolid_loopData(NULL, &pCoEdge, NULL, pLoop); BoolInt reversed = FALSE; while (SUCCESS == status) { KIEDGE* pEdge; EdgeId edgeId; status = mdlKISolid_coedgeData(&pEdge, NULL, NULL, &pCoEdge, NULL, NULL, NULL, &reversed, pCoEdge); mdlKISolid_idFromEdge(&edgeId, pEdge, TRUE); if (find_if (internalEdgeArray.begin(), internalEdgeArray.end(), edgeId_finder(edgeId)) != internalEdgeArray.end()) break; internalEdgeArray.push_back(edgeId); } } } mdlKISolid_listDelete(&pLoopList); } extern "C" StatusInt mdlKISolid_deleteLoopsFromSheetBody(KIENTITY_LIST *pLoopList); bool removeInternalLoops(KIENTITY_LIST* pFaceList, KIFACE* pFace) { KIBODY* pSheetBody = NULL; KIENTITY_LIST* pLoopList = NULL; KIENTITY_LIST* pRemovedLoopList = NULL; int cnt; mdlKISolid_sheetFromFace(&pSheetBody, pFace); mdlKISolid_listCreate(&pRemovedLoopList); mdlKISolid_listCreate(&pLoopList); mdlKISolid_getLoopList(pLoopList, pSheetBody); mdlKISolid_listCount(&cnt, pLoopList); bool bNeedRemove = false; for (int i = 0; i < cnt; i++) { KILOOP* pLoop; mdlKISolid_listNthEl(&pLoop, pLoopList, i); int isExternal; mdlKISolid_loopExternal(&isExternal, pLoop); if (!isExternal) { mdlKISolid_listAdd(pRemovedLoopList, pLoop); bNeedRemove = true; } } if (bNeedRemove) { KIENTITY_LIST* pSheetFaceList = NULL; KIFACE* pNewFace; mdlKISolid_deleteLoopsFromSheetBody(pRemovedLoopList); mdlKISolid_listCreate(&pSheetFaceList); mdlKISolid_getFaceList(pSheetFaceList, pSheetBody); mdlKISolid_listNthEl(&pNewFace, pSheetFaceList, 0); mdlKISolid_listRemove(pFaceList, pFace); mdlKISolid_listAdd(pFaceList, pNewFace); mdlKISolid_listDelete(&pSheetFaceList); } mdlKISolid_listDelete(&pLoopList); mdlKISolid_listDelete(&pRemovedLoopList); //Here can't free sheet body return bNeedRemove; } bool includeInternalEdge(KIFACE* pFace, vector<EdgeId>& internalEdgeArray) { KIENTITY_LIST* pEdgeList = NULL; int cnt; bool bFound = false; mdlKISolid_listCreate(&pEdgeList); mdlKISolid_getEdgeListFromFace(pEdgeList, pFace); mdlKISolid_listCount(&cnt, pEdgeList); for (int i = 0; i < cnt; i++) { KIEDGE *pEdge; EdgeId edgeId; mdlKISolid_listNthEl(&pEdge, pEdgeList, i); mdlKISolid_idFromEdge(&edgeId, pEdge, TRUE); if (find_if(internalEdgeArray.begin(), internalEdgeArray.end(), edgeId_finder(edgeId)) != internalEdgeArray.end()) { bFound = true; break; } } mdlKISolid_listDelete(&pEdgeList); return bFound; } void removeAllHolesFromSmartSolid2(ElementId elId) { MSElementDescrP edP = NULL; KIBODY *pBody = NULL; Transform trans; mdlAssoc_getElementDescr(&edP, NULL, elId, ACTIVEMODEL, FALSE); mdlKISolid_elementToBody2(&pBody, &trans, edP, ACTIVEMODEL, 1L, FALSE); mdlElmdscr_freeAll(&edP); // 1 -- Get internalEdgeList vector<EdgeId> internalEdgeArray; getInternalEdgeArray(internalEdgeArray, pBody); //printf("internalEdge Cnt = %d", internalEdgeArray.size()); // 2 -- Remove internal loops for every face KIENTITY_LIST* pFaceList = NULL; int cnt; mdlKISolid_listCreate(&pFaceList); mdlKISolid_getFaceList(pFaceList, pBody); mdlKISolid_listCount(&cnt, pFaceList); for (int i = 0; i < cnt; i++) { KIFACE *pFace; mdlKISolid_listNthEl(&pFace, pFaceList, i); if (removeInternalLoops(pFaceList, pFace)) i--; } // 3 -- Remove all faces with internal edges for (int i = 0; i < cnt; i++) { KIFACE *pFace; mdlKISolid_listNthEl(&pFace, pFaceList, i); if (includeInternalEdge(pFace, internalEdgeArray)) { mdlKISolid_listRemove(pFaceList, pFace); i--; } } // 4 -- sew all faces into body KIENTITY_LIST* pSheetBodyList = NULL; KIENTITY_LIST* pSewBodyList = NULL; KIENTITY_LIST* pUnsewBodyList = NULL; mdlKISolid_listCreate(&pSheetBodyList); mdlKISolid_listCreate(&pSewBodyList); mdlKISolid_listCreate(&pUnsewBodyList); mdlKISolid_listCount(&cnt, pFaceList); for (int i = 0; i < cnt; i++) { KIFACE* pFace; KIBODY* pSheetBody; mdlKISolid_listNthEl(&pFace, pFaceList, i); mdlKISolid_sheetFromFace(&pSheetBody, pFace); mdlKISolid_listAdd(pSheetBodyList, pSheetBody); } mdlKISolid_freeBody(pBody); if (SUCCESS == mdlKISolid_sewBodies(pSewBodyList, pUnsewBodyList, pSheetBodyList, 1e-06)) { mdlKISolid_listNthEl(&pBody, pSheetBodyList, 0); MSElementDescrP edP = NULL; mdlKISolid_bodyToElement(&edP, pBody, FALSE, -1, NULL, ACTIVEMODEL); mdlElmdscr_add(edP); mdlElmdscr_freeAll(&edP); } mdlKISolid_listDelete(&pFaceList); mdlKISolid_listDelete(&pUnsewBodyList); mdlKISolid_listDelete(&pSewBodyList); mdlKISolid_listDelete(&pSheetBodyList); }
Unknown said:if (find_if (internalEdgeArray.begin(), internalEdgeArray.end(), edgeId_finder(edgeId)) != internalEdgeArray.end())
Good example of the C++ Standard Library!
Regards, Jon Summers LA Solutions