This site was built to allow users to learn about ObjectARX® and AutoCAD® programming.
ObjectARX® and AutoCAD® are trademarks of Autodesk Inc.

Friday, January 12, 2007

Exercise2 - Step3

Creating a Custom Entity – Exercise 2 – Step 3Now you will learn how to add GRIP points to your entity. In fact, as the default implementation of AuPolyline forward the call to its base class you may already noted that its GRIP points are visible and working. The GRIP point behavior is handled by two methods. The first method, called getGripPoints() is responsible for acquiring all GRIP points from your entity. The second, called moveGripPointsAt(), is responsible for the action fired by each grip.Each default polyline GRIP action is to move the related vertex. In this example we want to add one extra grip positioned at our polygon’s center. To do that we first need to create a helper method to calculate this point. We will walk through all polygon points and will sum the coordinates dividing the result by numVerts(). This method will not change our entity data so it is recommended to be CONST and will require only the assertReadEnabled() call:AcGePoint3d AuPolyline::GetPolylineCenter() const{assertReadEnabled();AcGePoint3d ptC,pti;double cx = 0.0, cy = 0.0, cz = 0.0;for (int i=0; i<numVerts(); i++){this->getPointAt(i,pti);cx += pti[X];cy += pti[Y];cz += pti[Z];}cx = cx / numVerts();cy = cy / numVerts();cz = cz / numVerts();ptC.set(cx, cy, cz);return ptC;}Lines 04-15 apply the center formula and at line 16 we build the point using cx, cy and cz as the point’s X, Y and Z coordinates respectively.Next we need to change the default implementation of the both GRIP point methods. First we will redefine the getGripPoints() method. This method has 2 signatures and we will use the new AcDbGripData method instead of the “old style” method.This method receives an array of AcDbGripData pointers. These objects represent the GRIP point information. We need to inform at least the point and an arbitrary data (void*). This arbitrary data can be used later to get back information from each GRIP point allowing the moveGripPointsAt() method to perform the custom actions:Acad::ErrorStatus AuPolyline::getGripPoints (AcDbGripDataPtrArray &grips,const double curViewUnitSize,const int gripSize,const AcGeVector3d &curViewDir,const int bitflags) const{assertReadEnabled () ;AcDbGripData* gpd = new AcDbGripData();gpd->setAppData((void*)9999); // Center Grip codegpd->setGripPoint(GetPolylineCenter());grips.append(gpd);AcDbPolyline::getGripPoints (grips, curViewUnitSize, gripSize, curViewDir, bitflags);return (Acad::eOk);}This method will not change our entity’s data so it is also a CONST method and calls assertReadEnabled() method. On lines 09-12 we instantiate an AcDbGripData pointer and set its application data (9999 in this case) and the grip point which is calculated by the GetPolylineCenter() method. Next, on line 13 we forward the call to AcDbPolyline’s grip point method so it is able to add its own GRIP points at last. These GRIP points are those vertexes points we have mentioned before. The next step is to change the moveGripPointsAt() method so when the user clicks on this center GRIP it will reflect a custom action. In this example, our custom action will move the entire polyline. The following code shows how to do that:Acad::ErrorStatus AuPolyline::moveGripPointsAt (const AcDbVoidPtrArray &gripAppData,const AcGeVector3d &offset,const int bitflags){assertWriteEnabled () ;for (int g=0; g<gripAppData.length(); g++){// Get grip data back and see if it is our 0 Gripint i = (int)gripAppData.at(g);// If it is our grip, move the entire entity. If not, forward the callif (i == 9999)this->transformBy(offset);elseAcDbCurve::moveGripPointsAt (gripAppData, offset, bitflags);}return (Acad::eOk);}This time, our method cannot be CONST once we will change our entity’s data. Due that, we need to call assertWriteEnabled() at it’s beginning. On line 07 we start to inspect the AcDbVoidPtrArray (an array of void*) looking for our application data (9999). This method also receives a 3D vector which represents the transformation being applied to the GRIP. If the GRIP being modified is our 9999 we will apply this vector transformation to the entire polyline. This can be done through the transformBy() method passing the same vector (Figure 16).Figure 16 – Center GRIP in action.If the fired GRIP is not our 9999 code we will forward the call to AcDbCurve class (AcDbPolylin’s base class) which will handle it for us. The resulting behavior is when you select a GRIP over the polyline boundary the entity stretches and when you select the center GRIP the entity moves.

4 comments
:

Anonymous
said...

Hi Fernando,

I know my question is not completely related but i know that it deals with grips in some way. I am using Land Desktop 2007, (which im fairly new at) and had a question about labeling. When you create a contour line you can have that label basically be a part of the line. It will move with it, etc. So i want to know how to add this type of label to other lines. Is this possible? Thanks

I want to say that its not just specific to Land but can not guarantee that. Do know what I would be looking for if I looked at the ObjectARX API and also where exactly could I find it. Thank you for you help.