샘플 코드
// AsdkRectangleJig.h: interface for the AsdkRectangleJig class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_ASDKRECTANGLEJIG_H__B797B881_525A_491D_B14C_F2B9ACA711A8__INCLUDED_)
#define AFX_ASDKRECTANGLEJIG_H__B797B881_525A_491D_B14C_F2B9ACA711A8__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include
#include
#include // asDblArray()
#include // acdbWcs2Ecs() & acdbUcs2Ecs()
#include // lwpoly stuff.
#include "DataMgr.h"
#include "ViewCreator.h"
//-----------------------------------------------------------------------------
//
class CRectInfo {
public:
CRectInfo();
AcGePoint3d m_topLeftCorner; // First point selection.
double m_first; // First Chamfer distance.
double m_second; // Second Chamfer distance.
double m_bulge; // Bulge value.
double m_elev; // Elevation.
double m_thick; // Thickness.
double m_width; // Width.
double m_radius; // Fillet radius.
bool m_cornerTreatment; // Filleting or chamfering.
bool m_elevHandSet;
// m_chamfDirUnitVec is the vector direction of the chamfer of the
// top left corner of the rectangle. The chamfer opposite the top left
// corner will have the same vector direction and the ones on the
// alternate corners will be perpendicular to this one.
//
AcGeVector3d m_chamfDirUnitVec;
};
class AsdkRectangleJig : public AcEdJig
{
public:
AsdkRectangleJig(CViewCreatorDlg* pParent);
virtual ~AsdkRectangleJig();
public:
virtual DragStatus sampler();
virtual Adesk::Boolean update();
virtual AcDbEntity* entity() const;
void doRectangle();
AcGePoint3d BottomLeftCorner();
AcGePoint3d TopRightCorner();
AcGePoint3d samplerCorner;
static AcDbObjectId m_nObjectId;
private:
CViewCreatorDlg* m_pParent;
AcDbPolyline* m_pLWPoly;
AcGePoint3d m_TopLeftCorner;
AcGePoint3d m_TopRightCorner;
AcGePoint3d m_BottomLeftCorner;
AcGePoint3d m_BottomRightCorner;
AcGeVector3d m_vecUnitZ; // Unit vectors in the UCS plane
AcGeVector3d m_vecUnitX;
AcGeVector3d m_vecUnitY;
};
extern AsdkDataManager rectDataMgr; // MDI Safe
#define plineInfo rectDataMgr.docData()
#endif // !defined(AFX_ASDKRECTANGLEJIG_H__B797B881_525A_491D_B14C_F2B9ACA711A8__INCLUDED_)
2. AsdkRectangleJig.cpp
// AsdkRectangleJig.cpp: implementation of the AsdkRectangleJig class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include
#include "resource.h"
#include "ECRS.h"
#include "AsdkRectangleJig.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define MAKEUCSCOORD(x, y) tmpPoint = (y); \
acdbWcs2Ecs(asDblArray(tmpPoint), asDblArray(tmpPoint), asDblArray(m_vecUnitZ),\
Adesk::kFalse); x[X] = tmpPoint[X]; x[Y] = tmpPoint[Y];
AsdkDataManager rectDataMgr; // MDI Safe
// ----------------------------------------------------------------------------
// Constructor.
//
CRectInfo::CRectInfo()
{
m_topLeftCorner = AcGePoint3d();
m_first = m_second = m_bulge = m_elev = m_thick = m_width = m_radius = 0.0;
m_cornerTreatment = FALSE;
m_elevHandSet = FALSE;
}
AcDbObjectId AsdkRectangleJig::m_nObjectId;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
// parameter :
// description :
// remarks :
// returns :
AsdkRectangleJig::AsdkRectangleJig(CViewCreatorDlg* pParent)
{
m_pParent = pParent;
m_pLWPoly = new AcDbPolyline();
samplerCorner = AcGePoint3d();
plineInfo.m_cornerTreatment = plineInfo.m_first != 0.0
|| plineInfo.m_second != 0.0
|| plineInfo.m_radius != 0.0;
// Now need to get the current UCS Z-Axis to be used as the normal vector
// for the rectangle. At the same time, we get the x and y unit direction
// vectors used later.
//
if(CECRS::inPaperSpace()) {
m_vecUnitX = acdbHostApplicationServices()->workingDatabase()->pucsxdir();
m_vecUnitY = acdbHostApplicationServices()->workingDatabase()->pucsydir();
} else {
m_vecUnitX = acdbHostApplicationServices()->workingDatabase()->ucsxdir();
m_vecUnitY = acdbHostApplicationServices()->workingDatabase()->ucsydir();
}
m_vecUnitZ = m_vecUnitX.crossProduct(m_vecUnitY);
// Convert the incomming UCS point to ECS coordinate system
//
acdbUcs2Ecs(asDblArray(plineInfo.m_topLeftCorner),
asDblArray(m_TopLeftCorner), asDblArray(m_vecUnitZ), Adesk::kFalse);
acdbUcs2Ecs(asDblArray(plineInfo.m_topLeftCorner),
asDblArray(plineInfo.m_topLeftCorner), asDblArray(m_vecUnitZ),
Adesk::kFalse);
AcGePoint2d initPoint;
initPoint = AcGePoint2d(m_TopLeftCorner[X], m_TopLeftCorner[Y]);
// If the user has set the elev option from the main command prompt,
// then this will be the default until the user again sets it to 0.0.
// If however the user simply picks a point with or without an object
// snap, then use the Z value of the first point picked.
//
if (plineInfo.m_elevHandSet == TRUE)
m_pLWPoly->setElevation(plineInfo.m_elev);
else m_pLWPoly->setElevation(m_TopLeftCorner[Z]);
// If we are indeed filleting or chamfering the corners, then
// we'll add the extra verticies here to have their bulges and
// distances from the real corner changed on the fly.
//
if (plineInfo.m_cornerTreatment == TRUE) {
for (int i = 0 ; i < 8; i++)
m_pLWPoly->addVertexAt(i, initPoint);
} else {
for (int i = 0 ; i < 4; i++)
m_pLWPoly->addVertexAt(i, initPoint);
}
m_pLWPoly->setLineWeight(AcDb::kLnWt030);
m_pLWPoly->setNormal(m_vecUnitZ);
m_pLWPoly->setClosed(Adesk::kTrue);
m_pLWPoly->setThickness(plineInfo.m_thick);
m_pLWPoly->setConstantWidth(plineInfo.m_width);
// Get the current default linetype scale
m_pLWPoly->setLinetypeScale(acdbHostApplicationServices()
->workingDatabase()->celtscale());
// Now for jig dragger purposes, convert the point back to world
// coordinates.
//
acdbEcs2Wcs(asDblArray(m_TopLeftCorner),
asDblArray(m_TopLeftCorner), asDblArray(m_vecUnitZ), Adesk::kFalse);
acdbEcs2Wcs(asDblArray(plineInfo.m_topLeftCorner),
asDblArray(plineInfo.m_topLeftCorner), asDblArray(m_vecUnitZ),
Adesk::kFalse);
}
AsdkRectangleJig::~AsdkRectangleJig()
{
}
//-----------------------------------------------------------------------------
// This function creates an AcDbPolyline object after the
// jig startes and aquires the necessary vertex for the opposite
// corner from the drag samples.
//
void AsdkRectangleJig::doRectangle()
{
AcEdJig::DragStatus stat;
setDispPrompt("\nOther corner: ");
// Get the other corner now.
//
stat = drag();
// Now add the polyline rectangle to the database's current space
// if we return a kNormal stat from drag(). If we don't then delete
// the polyline.
//
AsdkRectangleJig::m_nObjectId = AcDbObjectId::kNull;
if (stat == kNormal){
AsdkRectangleJig::m_nObjectId = append();
m_pLWPoly->close();
}else delete m_pLWPoly;
setDispPrompt("\n");
}
//-----------------------------------------------------------------------------
// This function is called by the drag function in order to
// aquire a sample input
//
AcEdJig::DragStatus AsdkRectangleJig::sampler()
{
DragStatus stat = kNormal;
setUserInputControls((UserInputControls)
( AcEdJig::kNoNegativeResponseAccepted
| AcEdJig::kNoZeroResponseAccepted)
);
setSpecialCursorType(kCrosshair);
stat = acquirePoint(m_BottomRightCorner, plineInfo.m_topLeftCorner);
// Now project the point at the crosshairs to the ECS of the
// polyline being drawn.
//
AcGePlane planeParallelToUCS(m_TopLeftCorner, m_vecUnitZ);
m_BottomRightCorner = m_BottomRightCorner.project(planeParallelToUCS, m_vecUnitZ);
// If the newly acquired point is the same as it was
// in the last sample, then we return kNoChange so that
// AsdkRectangleJig::update() will not be called and the
// last update call will be able to finish thus allowing
// the polyline to fully elaborate.
//
if (samplerCorner != m_BottomRightCorner) {
// m_BottomRightCorner will be used to update the remaining corners
// in AsdkRectangleJig::update() below.
//
samplerCorner = m_BottomRightCorner;
} 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 AsdkRectangleJig::update()
{
AcGePoint2d adjustedPoint;
AcGePoint3d tmpPoint; // Used by MAKEUCSCOORD macro.
// We'll use the AcGeLine::intersectWith() function to infer the
// remaining points.
//
AcGeLine3d lineX, lineY;
lineX.set(m_TopLeftCorner, m_vecUnitX);
lineY.set(m_BottomRightCorner, m_vecUnitY);
// Top right corner is intersection of lineX and lineY.
//
lineX.intersectWith(lineY, m_TopRightCorner);
lineX.set(m_BottomRightCorner, m_vecUnitX);
lineY.set(m_TopLeftCorner, m_vecUnitY);
// Bottom left corner is intersection of lineX and lineY.
//
lineX.intersectWith(lineY, m_BottomLeftCorner);
AcGeVector3d tmpXVec, tmpYVec;
// Check to see if we have flipped around the X or Y axis.
//
bool bXFlip = m_vecUnitX.dotProduct(m_TopLeftCorner - m_TopRightCorner) >0;
bool bYFlip = m_vecUnitY.dotProduct(m_TopLeftCorner - m_BottomLeftCorner)<0;
// If the rectangle is dragged into the first or third quadrant,
// we need to reverse the sign of the bulge as well as reverse
// the x and y direction vectors.
//
tmpXVec = bXFlip ? -1 * m_vecUnitX : m_vecUnitX;
tmpYVec = bYFlip ? -1 * m_vecUnitY : m_vecUnitY;
// Now update the polyline with the latest setting
//
if (plineInfo.m_cornerTreatment) {
// We are going to fillet of chamfer this polyline rectangle. As such,
// the constructor has added the extra points at the corners to allow
// for there placement and bulge values to be updated on the fly.
// If, during the dragging, the rectangle is still too small to show the
// given radius or chamfer edges, the we will put the extra points in the
// corners and set the bulges to 0.0, so the rectangle retains its
// square corners until the user stretches the rectangle to a size large
// enough to have the corner treatment displayed.
//
// Use temporaries to see if we're too small to show fillet/chamfer, so
// we don't need to convert back to world.
//
AcGePoint2d point_TL, point_TR, point_BL;
MAKEUCSCOORD(point_TL, m_TopLeftCorner);
MAKEUCSCOORD(point_TR, m_TopRightCorner);
MAKEUCSCOORD(point_BL, m_BottomLeftCorner);
bool tooSmall = (point_TL.distanceTo(point_TR)
< plineInfo.m_first + plineInfo.m_second)
|| (point_TL.distanceTo(point_BL)
< plineInfo.m_first + plineInfo.m_second);
if (tooSmall) {
// Still to small to show the corner treatment.
//
m_pLWPoly->setBulgeAt(0, 0.0);
MAKEUCSCOORD(adjustedPoint, m_TopLeftCorner);
m_pLWPoly->setPointAt(0, adjustedPoint);
m_pLWPoly->setPointAt(1, adjustedPoint);
m_pLWPoly->setBulgeAt(2, 0.0);
MAKEUCSCOORD(adjustedPoint, m_TopRightCorner);
m_pLWPoly->setPointAt(2, adjustedPoint);
m_pLWPoly->setPointAt(3, adjustedPoint);
m_pLWPoly->setBulgeAt(4, 0.0);
MAKEUCSCOORD(adjustedPoint, m_BottomRightCorner);
m_pLWPoly->setPointAt(4, adjustedPoint);
m_pLWPoly->setPointAt(5, adjustedPoint);
m_pLWPoly->setBulgeAt(6, 0.0);
MAKEUCSCOORD(adjustedPoint, m_BottomLeftCorner);
m_pLWPoly->setPointAt(6, adjustedPoint);
m_pLWPoly->setPointAt(7, adjustedPoint);
} else {
double tmpBulge;
tmpBulge = ((!bXFlip && !bYFlip) || (bXFlip && bYFlip))
? plineInfo.m_bulge : -plineInfo.m_bulge;
// Now we will set adjustedPoint to the intersection of the rectangle
// sides with the place where the new end points will be.
//
m_pLWPoly->setBulgeAt(0, tmpBulge);
MAKEUCSCOORD(adjustedPoint,
m_TopLeftCorner + (-plineInfo.m_first * tmpYVec));
m_pLWPoly->setPointAt(0, adjustedPoint);
MAKEUCSCOORD(adjustedPoint,
m_TopLeftCorner + plineInfo.m_second * tmpXVec);
m_pLWPoly->setPointAt(1, adjustedPoint);
m_pLWPoly->setBulgeAt(2, tmpBulge);
MAKEUCSCOORD(adjustedPoint,
m_TopRightCorner + (-plineInfo.m_first * tmpXVec));
m_pLWPoly->setPointAt(2, adjustedPoint);
MAKEUCSCOORD(adjustedPoint,
m_TopRightCorner + (-plineInfo.m_second * tmpYVec));
m_pLWPoly->setPointAt(3, adjustedPoint);
m_pLWPoly->setBulgeAt(4, tmpBulge);
MAKEUCSCOORD(adjustedPoint,
m_BottomRightCorner + plineInfo.m_first * tmpYVec);
m_pLWPoly->setPointAt(4, adjustedPoint);
MAKEUCSCOORD(adjustedPoint,
m_BottomRightCorner + (-plineInfo.m_second * tmpXVec));
m_pLWPoly->setPointAt(5, adjustedPoint);
m_pLWPoly->setBulgeAt(6, tmpBulge);
MAKEUCSCOORD(adjustedPoint,
m_BottomLeftCorner + plineInfo.m_first * tmpXVec);
m_pLWPoly->setPointAt(6, adjustedPoint);
MAKEUCSCOORD(adjustedPoint,
m_BottomLeftCorner + plineInfo.m_second * tmpYVec);
m_pLWPoly->setPointAt(7, AcGePoint2d(adjustedPoint[X],
adjustedPoint[Y]));
}
} else {
// If this polyline is not having its corners treated, ie chamfered, or
// filleted then simply update the corners. Since we knew this ahead of
// time, the constructor did not add any extra verticies at the corners.
//
MAKEUCSCOORD(adjustedPoint, m_TopLeftCorner);
m_pLWPoly->setPointAt(0, adjustedPoint);
MAKEUCSCOORD(adjustedPoint, m_TopRightCorner);
m_pLWPoly->setPointAt(1, adjustedPoint);
MAKEUCSCOORD(adjustedPoint, m_BottomRightCorner);
m_pLWPoly->setPointAt(2, adjustedPoint);
MAKEUCSCOORD(adjustedPoint, m_BottomLeftCorner);
m_pLWPoly->setPointAt(3, adjustedPoint);
}
return Adesk::kTrue;
}
//-----------------------------------------------------------------------------
// This function must be implemented to return a pointer to
// the entity being manipulated by the jig.
//
AcDbEntity* AsdkRectangleJig::entity() const
{
return m_pLWPoly;
}
// parameter :
// description :
// remarks :
// returns :
AcGePoint3d AsdkRectangleJig::BottomLeftCorner(){
AcGePoint3d ptBottomLeft=m_BottomLeftCorner;
ptBottomLeft.x = (m_BottomRightCorner.x < ptBottomLeft.x) ? m_BottomRightCorner.x : tBottomLeft.x;
ptBottomLeft.y = (m_TopLeftCorner.y < ptBottomLeft.y) ? m_TopLeftCorner.y : tBottomLeft.y;
return ptBottomLeft;
}
// parameter :
// description :
// remarks :
// returns :
AcGePoint3d AsdkRectangleJig::TopRightCorner(){
AcGePoint3d ptTopRight=m_TopRightCorner;
ptTopRight.x = (m_TopLeftCorner.x > ptTopRight.x) ? m_TopLeftCorner.x : ptTopRight.x;
ptTopRight.y = (m_BottomRightCorner.y > ptTopRight.y) ? m_BottomRightCorner.y : tTopRight.y;
return ptTopRight;
}
댓글
댓글 쓰기