샘플 코드
// 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; }
댓글
댓글 쓰기