Типовой Код
Этот пример создает класс, который дает возможность пользователю создать эллипс, выбирая его среднюю точку и затем перемещая, чтобы выбрать желательную главную ось и незначительные{*младшие*} длины оси. В течение перетащенных операций, пользователь будет способен видеть то, что эллипс напоминает в любое время.
ОБРАТИТЕ ВНИМАНИЕ, пробует ли пользователь делать незначительную{*младшую*} ось дольше чем главная ось, эллипс закончится как круг, потому что отношение{*коэффициент*} радиуса не может быть большее чем 1.0.
class AsdkEllipseJig : public AcEdJig
// This class allows the user to create an ellipse by
// picking its center point and then dragging to select the
// desired major axis and minor axis lengths. During the
// drag operations, the user will be able to visually see
// what the ellipse looks like at any time.
//
{
public:
AsdkEllipseJig(const AcGePoint3d&, const AcGeVector3d&);
void doIt();
virtual DragStatus sampler();
virtual Adesk::Boolean update();
virtual AcDbEntity* entity() const;
private:
AcDbEllipse *mpEllipse;
AcGePoint3d mCenterPt, mAxisPt;
AcGeVector3d mMajorAxis, mNormal;
double mRadiusRatio;
int mPromptCounter;
};
// The following defines the constructor that accepts a point to be
// used as the centerpoint of the ellipse and the current UCS normal
// vector to be used as the normal for the ellipse. It also
// initializes the radius ratio to a small value so that during
// selection of the major axis, the ellipse will appear as a line.
// The prompt counter is also initialized to 0.
//
AsdkEllipseJig::AsdkEllipseJig(
const AcGePoint3d& pt,
const AcGeVector3d& normal)
: mCenterPt(pt),
mNormal(normal),
mRadiusRatio(0.00001),
mPromptCounter(0)
{ }
// This function creates an AcDbEllipse object and gets the
// jig started acquiring the necessary info to properly fill
// it in.
//
void
AsdkEllipseJig::doIt()
{
mpEllipse = new AcDbEllipse;
// Get the major axis vector from the user.
// At this time, mPromptCounter == 0.
//
setDispPrompt("\nEllipse major axis: ");
AcEdJig::DragStatus stat = drag();
// Get the ellipse’s radius ratio.
//
mPromptCounter++; // now == 1
setDispPrompt("\nEllipse minor axis: ");
stat = drag();
// Now add the ellipse to the database’s current space.
//
append();
}
// This function is called by the drag function to
// acquire a sample input.
//
AcEdJig::DragStatus
AsdkEllipseJig::sampler()
{
DragStatus stat;
setUserInputControls((UserInputControls)
(AcEdJig::kAccept3dCoordinates
| AcEdJig::kNoNegativeResponseAccepted
| AcEdJig::kNoZeroResponseAccepted));
if (mPromptCounter == 0) {
// Aquire the major axis endpoint.
//
// If the newly acquired point is the same as it was
// in the last sample, then we return kNoChange so the
// AsdkEllipseJig::update() function will not be called
// and the last update call will be able to finish, thus
// allowing the ellipse to fully elaborate.
//
static AcGePoint3d axisPointTemp;
stat = acquirePoint(mAxisPt, mCenterPt);
if (axisPointTemp != mAxisPt)
axisPointTemp = mAxisPt;
else if (stat == AcEdJig::kNormal)
return AcEdJig::kNoChange;
}
else if (mPromptCounter == 1) {
// Aquire the distance from ellipse center to minor
// axis endpoint. This will be used to calculate the
// radius ratio.
//
// If the newly acquired distance is the same as it was
// in the last sample, then we return kNoChange so the
// AsdkEllipseJig::update() function will not be called
// and the last update call will be able to finish, thus
// allowing the ellipse to fully elaborate.
//
static double radiusRatioTemp = -1;
stat = acquireDist(mRadiusRatio, mCenterPt);
if (radiusRatioTemp != mRadiusRatio)
radiusRatioTemp = mRadiusRatio;
else if (stat == AcEdJig::kNormal)
return AcEdJig::kNoChange;
}
return stat;
}
// This function is called to update the entity based on the
// input values.
//
Adesk::Boolean
AsdkEllipseJig::update()
{
switch (mPromptCounter) {
case 0:
// At this time, mAxis contains the value of one
// endpoint of the desired major axis. The
// AcDbEllipse class stores the major axis as the
// vector from the center point to where the axis
// intersects the ellipse path (such as half of the true
// major axis), so we already have what we need.
//
mMajorAxis = mAxisPt - mCenterPt;
break;
case 1:
// Calculate the radius ratio. mRadiusRatio
// currently contains the distance from the ellipse
// center to the current pointer position. This is
// half of the actual minor axis length. Since
// AcDbEllipse stores the major axis vector as the
// vector from the center point to the ellipse curve
// (half the major axis), to get the radius ratio we
// simply divide the value currently in mRadiusRatio
// by the length of the stored major axis vector.
//
mRadiusRatio = mRadiusRatio / mMajorAxis.length();
break;
}
// Now update the ellipse with the latest setting.
//
mpEllipse->set(mCenterPt, mNormal, mMajorAxis,
mRadiusRatio);
return Adesk::kTrue;
}
// This function must be implemented to return a pointer to
// the entity being manipulated by the jig.
//
AcDbEntity*
AsdkEllipseJig::entity() const
{
return mpEllipse;
}
// This function uses the AcEdJig mechanism to create and
// drag an ellipse entity. The creation criteria are
// slightly different from the AutoCAD command. In this
// case, the user selects an ellipse center point and
// drags to visually select the major and minor axes
// lengths. This sample is somewhat limited; if the
// minor axis ends up longer than the major axis, then the
// ellipse will just be round because the radius ratio
// cannot be greater than 1.0.
//
void
createEllipse()
{
// First, have the user select the ellipse center point.
// We don’t use the jig for this because there is
// nothing to see yet.
//
AcGePoint3d tempPt;
struct resbuf rbFrom, rbTo;
acedGetPoint(NULL, "\nEllipse center point: ",
asDblArray(tempPt));
// The point we just got is in UCS coordinates, but
// AcDbEllipse works in WCS, so convert the point.
//
rbFrom.restype = RTSHORT;
rbFrom.resval.rint = 1; // from UCS
rbTo.restype = RTSHORT;
rbTo.resval.rint = 0; // to WCS
acedTrans(asDblArray(tempPt), &rbFrom, &rbTo,
Adesk::kFalse, asDblArray(tempPt));
// Now you need to get the current UCS z-Axis to be used
// as the normal vector for the ellipse.
//
AcGeVector3d x =
acdbHostApplicationServices()->workingDatabase()->ucsxdir();
AcGeVector3d y =
acdbHostApplicationServices()->workingDatabase()->ucsydir();
AcGeVector3d normalVec = x.crossProduct(y);
normalVec.normalize();
// Create an AsdkEllipseJig object passing in the
// center point just selected by the user and the normal
// vector just calculated.
//
AsdkEllipseJig *pJig
= new AsdkEllipseJig(tempPt, normalVec);
// Now start up the jig to interactively get the major
// and minor axes lengths.
//
pJig->doIt();
// Now delete the jig object, since it is no longer needed.
//
delete pJig;
}
void
initApp()
{
acedRegCmds->addCommand("ASDK_VISUAL_ELLIPSE",
"ASDK_VELLIPSE", "VELLIPSE", ACRX_CMD_MODAL,
createEllipse);
}
void
unloadApp()
{
acedRegCmds->removeGroup("ASDK_VISUAL_ELLIPSE");
}
extern "C" AcRx::AppRetCode
acrxEntryPoint(AcRx::AppMsgCode msg, void* appId)
{
switch (msg) {
case AcRx::kInitAppMsg:
acrxDynamicLinker->unlockApplication(appId);
acrxDynamicLinker->registerAppMDIAware(appId);
initApp();
break;
case AcRx::kUnloadAppMsg:
unloadApp();
}
return AcRx::kRetOK;
}