Creating a solid from a set of SubDMesh

<?xml encoding=”UTF-8″>By Balaji Ramamoorthy

If you have a collection of subDMesh and wish to create a Solid from it, first convert each of those mesh to a surface. If the sufaces all put together form a closed volume, then a sculpted solid can be created from these surfaces. Here is a sample code snippet :

 <span>// For SubDMesh </span><span> </span>
 <span>#include</span><span>  <span>"dbSubD.h"</span><span> </span></span>
 
 <span>static</span><span>  <span>void</span><span>  AdskMeshToSolid()</span></span>
 <span>{</span>
 	Acad::ErrorStatus es;
 	<span>int</span><span>  ret;</span>
 
 	<span>// Select the meshes to create the solid from</span><span> </span>
 	AcArray<AcDbObjectId> meshIdArray;
 	<span>do</span><span> </span>
 	<span>{</span>
 		ads_name entName;
 		ads_point pt;
 		ret = acedEntSel(L<span>"Select a mesh : "</span><span> , </span>
 						entName, pt);
 
 		<span>if</span><span> (RTNORM != ret) </span>
 			<span>break</span><span> ;</span>
 
 		AcDbObjectId objId = AcDbObjectId::kNull;
 		<span>if</span><span> ( Acad::eOk != acdbGetObjectId(objId, entName)) </span>
 			<span>break</span><span> ;</span>
 
 		<span>if</span><span> (objId.objectClass() == AcDbSubDMesh::desc())</span>
 		<span>{</span>
 			meshIdArray.append(objId);
 		<span>}</span>
 	<span>}</span><span>while</span><span> (ret == RTNORM);</span>
 
 	<span>// Convert the meshes to surfaces</span><span> </span>
 	AcArray<AcDbEntity*> surfacesArray;
 	AcGeIntArray limits;
 	AcDbSurface *pSurface = NULL;
 
 	<span>for</span><span> (<span>int</span><span>  mesh = 0; mesh < meshIdArray.length(); mesh++)</span></span>
 	<span>{</span>
 		AcDbEntity *pEntity = NULL; 
 		<span>if</span><span> (acdbOpenAcDbEntity(pEntity, meshIdArray[mesh], </span>
 							AcDb::kForRead) != Acad::eOk) 
 		<span>{</span>
 			<span>return</span><span> ; </span>
 		<span>}</span>
 			
 		AcDbSubDMesh *pMesh = AcDbSubDMesh::cast(pEntity); 
 		<span>if</span><span> (pMesh)</span>
 		<span>{</span>
 			es = pMesh->convertToSurface(
 							<span>false</span><span> , </span>
 							<span>false</span><span> , </span>
 							pSurface);
 
 			<span>if</span><span> (es != Acad::eOk)</span>
 				<span>return</span><span> ;</span>
 
 			<span>if</span><span>  ( es == Acad::eOk && </span>
 				pSurface->isKindOf(AcDbSurface::desc()))
 			<span>{</span>
 				surfacesArray.append(pSurface);
 			<span>}</span>
 		<span>}</span>
 
 		pEntity->close();
 	<span>}</span>
 
 	<span>// Create a sculpted solid from surfaces</span><span> </span>
 	AcDb3dSolid *pSolid = <span>new</span><span>  AcDb3dSolid();</span>
 	pSolid->setDatabaseDefaults();
 		 
 	es = pSolid->createSculptedSolid(
 					surfacesArray, 
 					limits);
 
 	<span>if</span><span> (es == Acad::eOk)</span>
 	<span>{</span>
 		<span>// Add sculpted solid to the database </span><span> </span>
 		AcDbObjectId solidOid = AcDbObjectId::kNull;
 		postToDb(pSolid, &solidOid);
  
 		<span>// To show the newly created solid away</span><span> </span>
 		<span>// from the surfaces, we transform it..</span><span> </span>
 		AcDbEntity *pSolidEnt;
 		es = acdbOpenAcDbEntity(
 				pSolidEnt, solidOid, AcDb::kForWrite);
 		<span>if</span><span>   (es == Acad::eOk &&</span>
 				pSolidEnt->isKindOf(AcDb3dSolid::desc()))
 		<span>{</span>
 			AcGeVector3d vec(15.0, 15.0, 0.0);
 			AcGeMatrix3d transform 
 						= transform.setToTranslation(vec);
 			es = pSolidEnt->transformBy(transform);
 			pSolidEnt->close();
 			acutPrintf(
 				ACRX_T(<span>"Solid3d created from mesh !"</span><span> ));</span>
 		<span>}</span>
 		<span>else</span><span> </span>
 		<span>{</span>
 			acutPrintf(
 				ACRX_T(<span>"Solid3d creation failed !"</span><span> ));</span>
 		<span>}</span>
 	<span>}</span>
 	<span>else</span><span> </span>
 	<span>{</span>
 		acutPrintf(ACRX_T(<span>"Solid3d creation failed !"</span><span> ));</span>
 		<span>delete</span><span>  pSolid;</span>
 	<span>}</span>
  
 	<span>// Cleanup</span><span> </span>
 	<span>// We do not need the surfaces anymore</span><span> </span>
 	<span>int</span><span>  surfCnt = 0;</span>
 	<span>for</span><span> (;surfCnt < surfacesArray.length(); surfCnt++)</span>
 	<span>{</span>
 		AcDbEntity *pEnt = surfacesArray[surfCnt];
 		<span>delete</span><span>  pEnt;</span>
 	<span>}</span>
 <span>}</span>
 
 <span>static</span><span>  <span>void</span><span>  postToDb( AcDbEntity* pEnt, AcDbObjectId *pOid) </span></span>
 <span>{</span>
 	AcDbBlockTable* pBlockTable;
 	AcDbDatabase *pDb = 
 		acdbHostApplicationServices()->workingDatabase();
 	pDb->getBlockTable(pBlockTable, AcDb::kForRead);
 	
 	AcDbBlockTableRecord* pModelSpaceBTR =  NULL; 
 	pBlockTable->getAt(
 		ACDB_MODEL_SPACE, 
 		pModelSpaceBTR, 
 		AcDb::kForWrite);
 	
 	AcDbObjectId oid = AcDbObjectId::kNull;
 	<span>if</span><span> (pOid != NULL)</span>
 	<span>{</span>
 		pModelSpaceBTR->appendAcDbEntity(*pOid, pEnt);
 	<span>}</span>
 	<span>else</span><span> </span>
 	<span>{</span>
 		pModelSpaceBTR->appendAcDbEntity(oid, pEnt);
 	<span>}</span>
 	pEnt->close(); 
 	
 	pModelSpaceBTR->close();
 	pBlockTable->close();
 <span>}</span>
 

Here is a screenshot of the output

MeshToSolid


Comments

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading