Implementing the Object Snap Point Function

If you want your custom entity to support object snap modes, you need to override the subGetOsnapPoints() function. AutoCAD invokes getOsnapPoints() to acquire the relevant snap points for the current mode, which in turn invokes subGetOsnapPoints() to access a custom entity’s snap mode. If you do not want your entity to support snap points for a particular mode, you can filter out the snap modes you support and return eOk for the others; the user is prompted to select again. If multiple object snap modes are active, this function is called once for each object snap mode.

Note: The intersection object snap mode is processed differently from getOsnapPoints(). It uses AcDbEntity::intersectWith(), not getOsnapPoints().

The following shows how the AsdkPoly class implements the subGetOsnapPoints() function:

 Acad::ErrorStatus 
 AsdkPoly::subGetOsnapPoints( 
     AcDb::OsnapMode       osnapMode, 
     Adesk::GsMarker       gsSelectionMark, 
     const AcGePoint3d&    pickPoint, 
     const AcGePoint3d&    lastPoint, 
     const AcGeMatrix3d&   viewXform, 
     AcGePoint3dArray&     snapPoints, 
     AcDbIntArray&         /*geomIds*/) const 
 { 
  
     assertReadEnabled(); 
     Acad::ErrorStatus es = Acad::eOk; 
  
     if (gsSelectionMark == 0) 
         return Acad::eOk; 
  
     if (   osnapMode != AcDb::kOsModeEnd 
         && osnapMode != AcDb::kOsModeMid 
         && osnapMode != AcDb::kOsModeNear 
         && osnapMode != AcDb::kOsModePerp 
         && osnapMode != AcDb::kOsModeCen 
         && osnapMode != AcDb::kOsModeIns) 
     { 
         return Acad::eOk; 
     } 
  
     // First, check to see if the gsSelection marker is the 
     // text geometry. If so, handle center and insertion  
     // modes, then return. No need to go into perp, mid, etc. 
     // 
     AcGePoint3d center; 
     getCenter(center); 
     if (gsSelectionMark == (mNumSides + 1)) { 
         if (osnapMode == AcDb::kOsModeIns) 
             snapPoints.append(center); 
         else if (osnapMode == AcDb::kOsModeCen) 
             snapPoints.append(center); 
          
         return es; 
     } 
  
     int startIndex = (int)(gsSelectionMark - 1); 
  
     AcGePoint3dArray vertexArray; 
     if ((es = getVertices3d(vertexArray)) != Acad::eOk) { 
         return es; 
     } 
  
     AcGeLineSeg3d lnsg(vertexArray[startIndex], 
             vertexArray[startIndex + 1]); 
     AcGePoint3d pt; 
  
     AcGeLine3d line, perpLine; 
     AcGeVector3d vec; 
  
     AcGeVector3d viewDir(viewXform(Z, 0), viewXform(Z, 1), 
             viewXform(Z, 2)); 
  
     switch (osnapMode) { 
     case AcDb::kOsModeEnd: 
         snapPoints.append(vertexArray[startIndex]); 
         snapPoints.append(vertexArray[startIndex + 1]); 
         break; 
  
     case AcDb::kOsModeMid: 
         pt.set( 
             ((vertexArray[startIndex])[X] 
                 + (vertexArray[startIndex + 1])[X]) * 0.5, 
             ((vertexArray[startIndex])[Y] 
                 + (vertexArray[startIndex + 1])[Y]) * 0.5, 
             ((vertexArray[startIndex])[Z] 
                 + (vertexArray[startIndex + 1])[Z]) * 0.5); 
         snapPoints.append(pt); 
         break; 
  
     case AcDb::kOsModeNear: 
         pt = lnsg.projClosestPointTo(pickPoint, viewDir); 
         snapPoints.append(pt); 
         break; 
  
     case AcDb::kOsModePerp: 
  
         // Create a semi-infinite line and find a point on it. 
         // 
         vec = vertexArray[startIndex + 1] 
             - vertexArray[startIndex]; 
         vec.normalize(); 
         line.set(vertexArray[startIndex], vec); 
         pt = line.closestPointTo(lastPoint); 
         snapPoints.append(pt); 
         break; 
  
     case AcDb::kOsModeCen: 
         snapPoints.append(center); 
         break; 
  
     default: 
         return Acad::eOk; 
  
     } 
     return es; 
 }