天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 56|回复: 0

Creating a Point Cloud Spatial Filter/Clipping box using ObjectARX

[复制链接]

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
发表于 2024-6-22 09:46:18 | 显示全部楼层 |阅读模式


[code]acrxEntryPoint.cpp

//-----------------------------------------------------------------------------

//----- acrxEntryPoint.cpp

//-----------------------------------------------------------------------------

#include "StdAfx.h"

#include "resource.h"

#include "myFilter.h"

#include "MyBoxReactor.h"



#pragma comment(lib,"AcDbPointCloudObj.lib")

#include "AcPointCloud.h"



//-----------------------------------------------------------------------------

#define szRDS _RXST("asdk")



//-----------------------------------------------------------------------------

//----- ObjectARX EntryPoint

class CAcPointCloudTestApp : public AcRxArxApp

{

public:

CAcPointCloudTestApp () : AcRxArxApp () {}



virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {

  // TODO: Load dependencies here



  // You *must* call On_kInitAppMsg here

  AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;



  // TODO: Add your initialization code here



  return (retCode) ;

}



virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {

  // TODO: Add your code here



  // You *must* call On_kUnloadAppMsg here

  AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;



  // TODO: Unload dependencies here



  return (retCode) ;

}



virtual void RegisterServerComponents () {

}





  ///////////////////////////////////////////////////////////////

// by Fenton Webb, DevTech, 19/03/2013

static void asdkAcPointCloudTestaddFilter(void)

{

  // pick a point cloud

  ads_name ename;

  ads_point pnt;

  int res = acedEntSel(_T("\nSelect a Point Cloud : "), ename, pnt);

    // if ok

    if (res == RTNORM)

    {

      // then convert the ename to an object id

   AcDbObjectId id;

   acdbGetObjectId(id,ename);



    // open the selected point cloud entity

    AcDbEntityPointer ent(id, AcDb::kForWrite);

      // if ok

      if (ent.openStatus() == Acad::eOk)

    {

      // reset the point cloud view

        Acad::ErrorStatus es = acdbResetPointCloudDataView(ent);

        // if not ok, possibly not a point cloud

        if (es != Acad::eOk)

        {

          acutPrintf(_T("\nNot a point cloud..."));

          return;

        }



        AcGePoint3d minPnt;

        acedInitGet(RSG_GETZ, NULL);

      // select the first bounding point

      res = acedGetPoint(NULL, _T("\nSelect Bottom Left Corner : "), asDblArray(minPnt));

        // if ok

        if (res == RTNORM)

        {

          AcGePoint3d maxPnt;

          acedInitGet(RSG_GETZ, NULL);

          // select the second bounding point

        res = acedGetPoint(NULL, _T("\nSelect Top Right Corner : "), asDblArray(maxPnt));

          // if ok

          if (res == RTNORM)

          {

            // convert any UCS to world

            AcGeMatrix3d matUcs2Wcs;

            acedGetCurrentUCS(matUcs2Wcs);

            matUcs2Wcs.invert();

            minPnt.transformBy(matUcs2Wcs);

            maxPnt.transformBy(matUcs2Wcs);



            // set up and nice extents box

            AcGeBoundBlock3d filterExtents;

            filterExtents.set(minPnt, maxPnt);

            // draw controller box

            DrawSlicerBox(filterExtents);



            // create a new filter object, my one I mean - document specific

            DocVars.docData().mPCFilter = new MyFilter(filterExtents, id);

          // and apply the filter to the point cloud

          res = acdbModifyPointCloudDataView(ent.object(), DocVars.docData().mPCFilter);

          }

        }

      }

    }

}



  static bool DrawSlicerBox(AcGeBoundBlock3d extents)

  {

    // extract the points

    AcGePoint3d minPnt, maxPnt;

    extents.getMinMaxPoints(minPnt, maxPnt);



    // draw a box

    {

      AcDbObjectPointer<AcDb3dSolid> box;

      box.create();

      box->setRecordHistory(true);

      double xDist = fabs(maxPnt.x - minPnt.x) + 0.001;

      double yDist = fabs(maxPnt.y - minPnt.y) + 0.001;

      double zDist = fabs(maxPnt.z - minPnt.z) + 0.001;

      box->createBox(xDist, yDist, zDist);

      box->transformBy(AcGeMatrix3d().setTranslation(AcGeVector3d(minPnt.x + xDist/2, minPnt.y + yDist/2, minPnt.z + zDist/2)));

      AcDbBlockTableRecordPointer curSpace(curDoc()->database()->currentSpaceId(), AcDb::kForWrite);

      // if ok

      if (curSpace.openStatus() == Acad::eOk)

      {

        curSpace->appendAcDbEntity(box.object());

        // add a reactor to it

        box->addReactor(new MyBoxReactor());

        return true;

      }

    }



    return false;

  }



// - asdkAcPointCloudTest.removeFilter command (do not rename)

static void asdkAcPointCloudTestremoveFilter(void)

{

    // pick a point cloud

    ads_name ename;

    ads_point pnt;

    int res = acedEntSel(_T("\nSelect a Point Cloud : "), ename, pnt);

    // if ok

    if (res == RTNORM)

    {

      // then convert the ename to an object id

      AcDbObjectId id;

      acdbGetObjectId(id,ename);

    // just reset the point cloud view

    AcDbEntityPointer ent(id, AcDb::kForWrite);

      // if ok

      if (ent.openStatus() == Acad::eOk)

      {

        // reset the point cloud view

        Acad::ErrorStatus es = acdbResetPointCloudDataView(ent);

        // if not ok, possibly not a point cloud

        if (es != Acad::eOk)

        {

          acutPrintf(_T("\nNot a point cloud..."));

          return;

        }

      }

    }

}



  static void asdkAcPointCloudTesttest(void)

  {

    AcGePoint3d minPnt;

    acedInitGet(RSG_GETZ, NULL);

    // select the first bounding point

    int res = acedGetPoint(NULL, _T("\nSelect Bottom Left Corner : "), asDblArray(minPnt));

    // if ok

    if (res == RTNORM)

    {

      AcGePoint3d maxPnt;

      acedInitGet(RSG_GETZ, NULL);

      // select the second bounding point

      res = acedGetPoint(NULL, _T("\nSelect Top Right Corner : "), asDblArray(maxPnt));

      // if ok

      if (res == RTNORM)

      {

        // set up and nice extents box

        AcGeBoundBlock3d filterExtents;

        filterExtents.set(minPnt, maxPnt);

        DrawSlicerBox(filterExtents);      



        while(res == RTNORM)

        {

          AcGePoint3d inside;

          // select the second bounding point

          res = acedGetPoint(NULL, _T("\nPick a point : "), asDblArray(inside));



          if (filterExtents.contains(inside))

            acutPrintf(_T("\nInside"));

        }

      }

    }

  }

} ;



//-----------------------------------------------------------------------------

IMPLEMENT_ARX_ENTRYPOINT(CAcPointCloudTestApp)



ACED_ARXCOMMAND_ENTRY_AUTO(CAcPointCloudTestApp, asdkAcPointCloudTest, addFilter, addFilter, ACRX_CMD_TRANSPARENT, NULL)

ACED_ARXCOMMAND_ENTRY_AUTO(CAcPointCloudTestApp, asdkAcPointCloudTest, removeFilter, removeFilter, ACRX_CMD_TRANSPARENT, NULL)

ACED_ARXCOMMAND_ENTRY_AUTO(CAcPointCloudTestApp, asdkAcPointCloudTest, test, test, ACRX_CMD_TRANSPARENT, NULL)



MyBoxReactor.cpp


#include "StdAfx.h"

#include "resource.h"

#include "MyBoxReactor.h"

#include "acadi.h"

#include "dynprops.h"

#include "axboiler.h"

#include "axpnt3d.h"

#include "dbobjptr2.h"



//////////////////////////////////////////////////////////////////////////

void MyBoxReactor::modified(const AcDbObject* obj)

{

  // if we have a n assigned point cloud filter

  if (DocVars.docData().mPCFilter)

  {

    // make sure we have a 3d solid

    AcDb3dSolid *solid = AcDb3dSolid::cast(obj);

    if (solid)

    {

      if (!solid->isErased())

      {

        // extract the minPoint from the existing PCFilter

        AcGePoint3d minPnt, maxPnt;

        DocVars.docData().mPCFilter->mFilterExtents.getMinMaxPoints(minPnt, maxPnt);



        // get the IUknown of the entity, we’ll need it to get the properties for the instance and also so we can set them

        CComPtr<IUnknown> entIUnknown = NULL;

        HRESULT hr = AcAxGetIUnknownOfObject(&entIUnknown, obj->objectId(), acedGetAcadWinApp()->GetIDispatch(TRUE));

        double length=0.001, height=0.001, width=0.001;



        // get the box info

        AcRxClass* pAcrxClass = AcDb3dSolid::desc();

        // Per-instance dynamic property managers

        OPMPerInstancePropertyExtension* pPerInstanceExtension = GET_OPM_PERINSTANCE_EXTENSION_PROTOCOL(pAcrxClass);

        if (NULL != pPerInstanceExtension)

        {

          COleSafeArray sourceNames;

          CComBSTR sourceName;

          // get the property source names stored on the extension object

          pPerInstanceExtension->GetObjectPropertySourceNames((LPVARIANT)sourceNames);

          // find out how many we have

          long start = 0;

          long end = 0;

          sourceNames.GetLBound(1, &start);

          sourceNames.GetUBound(1, &end);

          // loop the property sources

          for (long i=start; i<=end; ++i)

          {

            // extract each one of the property sources out

            CComPtr<IPropertySource> propertySource;

            sourceNames.GetElement(&i, (void*)&sourceName);

            // GetPropertySourceAt does AddRef, so we directly assign pointer here.

            propertySource.p = GET_OPM_PERINSTANCE_PROPERTY_SOURCES()->GetPropertySourceAt(&sourceName);

            // if we have one

            if (propertySource.p)

            {

              // if ok

              if (SUCCEEDED(hr))

              {

                // extract the Dynamic properties from it

                COleSafeArray props;

                hr = propertySource->GetProperties(entIUnknown, props);

                // if ok

                if (SUCCEEDED(hr))

                {

                  // loop all the dynamic properties that we have

                  long start = 0;

                  long end = 0;

                  props.GetLBound(1, &start);

                  props.GetUBound(1, &end);

                  for (long i=start; i<=end; ++i)

                  {

                    // first get the iUknown to make sure we have something

                    CComPtr<IUnknown> unknown = NULL;

                    props.GetElement(&i, (void*)&unknown);

                    // if we have

                    if (unknown.p)

                    {

                      // try and cast it to an updated IDynamicProperty2

                      CComQIPtr<IDynamicProperty2> dynProp = unknown;

                      // if ok

                      if (dynProp.p)

                      {

                        CComBSTR propName;

                        // extract out the property name

                        dynProp->GetDisplayName(&(propName.m_str));

                        // get the value

                        COleVariant getter;

                        dynProp->GetCurrentValueData(entIUnknown, getter);

                        // find out which property we are looking at

                        if (CString(propName) == _T("Length"))

                          length = ((*(tagVARIANT*)(&getter))).dblVal;

                        if (CString(propName) == _T("Width"))

                          width = ((*(tagVARIANT*)(&getter))).dblVal;

                        if (CString(propName) == _T("Height"))

                          height = ((*(tagVARIANT*)(&getter))).dblVal;;

                      }

                    }

                  }

                }

              }

            }

          }



          // now get the position from the solid

          CComQIPtr<IAcad3DSolid> solidCom(entIUnknown);

          if(solidCom != NULL)

          {

            COleVariant olePosition;

            hr = solidCom->get_Position(&olePosition);

            AcAxPoint3d position = olePosition;



            minPnt.x = position.x - length/2.0;

            minPnt.y = position.y - width/2.0;

            minPnt.z = position.z - height/2.0;

          }



          // finally, update the point cloud

          DocVars.docData().mPCFilter->mFilterExtents.set(minPnt, AcGePoint3d(minPnt.x+length, minPnt.y+width, minPnt.z+height));



          // and touch the point cloud for update

          AcDbBlockTableRecordPointer curSpace(curDoc()->database()->currentSpaceId(), AcDb::kForRead);

          // if ok

          if (curSpace.openStatus() == Acad::eOk)

          {

            AcDbObjectPointer<AcDbEntity> pointCloud( DocVars.docData().mPCFilter->mPointcloudId, AcDb::kForRead);

            // if ok

            if (pointCloud.openStatus() == Acad::eOk)

            {

              AcGsModel *gsModel = curDoc()->database()->gsModel();

              gsModel->onModified(AcGiDrawable::cast(pointCloud.object()), curSpace.object());

            }

          }

        }

      }

    }

  }

}


MyFilter.cpp


#include "StdAfx.h"

#include "resource.h"

#include "MyFilter.h"



//////////////////////////////////////////////////////////////////////////

// this is my point cloud filter implementation, by Fenton Webb, DevTech, Autodesk 27/05/2010

void MyFilter::doFilter(const IAcPcDataBuffer& inBuffer, IAcPcDataBuffer&outBuffer)

{

  AcGePoint3d minPnt, maxPnt;

  mFilterExtents.getMinMaxPoints(minPnt, maxPnt);



  // this is just to show how often the filter function is being called

  acutPrintf(_T("\nfilter is called - min(%.2f,%.2f,%.2f) max(%.2f,%.2f,%.2f)"), minPnt.x, minPnt.y, minPnt.z, maxPnt.x, maxPnt.y, maxPnt.z);



  // ignoring native double buffers for brevity

  if(const_cast<IAcPcDataBuffer&>(inBuffer).nativeDbl())

    return;



  DWORD noOfOutPoints(0);



  AcPcPointFloat *pInPoints = const_cast<IAcPcDataBuffer&>(inBuffer).floatPoints();   

  AcPcPointFloat *pOutPoints = outBuffer.floatPoints();   



  // the points from the point cloud are raw points, we need to convert them into WCS

  // first let's work out the transform matrix

  double x, y, z;   

  inBuffer.offset(x, y, z);

  AcGeMatrix3d mx;

  inBuffer.entityTransform(mx);



  // now lets loop the points

  int length = inBuffer.size();

  int incrementFactor = 1;

  for (int i=0; i<length; i+=incrementFactor, pInPoints+=incrementFactor)

  {

    // now convert the raw point cloud points into WCS

    AcGePoint3d pt(pInPoints->m_x + x, pInPoints->m_y + y, pInPoints->m_z + z);

    pt = mx*pt;



    // finally check to see if the point lays inside of our box

    if (mFilterExtents.contains(pt))

    {

      // if so, add it to the out array list

      *(pOutPoints+noOfOutPoints) = *pInPoints;

      ++noOfOutPoints;

    }

  }



  // finally, we have less points to show obviously so adjust to suit

  outBuffer.shrink(noOfOutPoints);

}



[/code]

 

 

 

 

Creating a Point Cloud Spatial Filter/Clipping box using ObjectARX
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|中国膜结构网_中国空间膜结构协会

GMT+8, 2024-11-1 13:33 , Processed in 0.125867 second(s), 23 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表