/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2024, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2024 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #include "StdAfx.h" #include "DbPolylineMultiModesGripPE.h" //---------------------------------------------------------------------------------------- #include "DbCommandContext.h" #include "DbPolyline.h" #include "DbLine.h" #include "Gs/Gs.h" #include #include //######################################################################################## //############### OdDbPolylineMultiModesGripPE ############## //######################################################################################## ODRX_NO_CONS_DEFINE_MEMBERS(OdGripPolylineMultiModeAppData, OdRxObject); bool OdDbPolylineMultiModesGripPE::getGripModes(const OdDbEntity* pEnt, OdDbGripData* pGripData, OdArray& modes, unsigned int& curMode) const { if (!pEnt || !pGripData) return false; OdGripPolylineMultiModeAppDataPtr appData = static_cast(pGripData->appData()); if (!appData) return false; appData->getGripModes(modes); curMode = appData->mode(); return true; } unsigned int OdDbPolylineMultiModesGripPE::mode(OdDbEntity*, OdDbGripData* pGripData) const { OdGripPolylineMultiModeAppDataPtr appData = static_cast(pGripData->appData()); return appData->mode(); } OdDbMultiModesGripPE::GripMode OdDbPolylineMultiModesGripPE::modeEx(OdDbEntity*, OdDbGripData* pGripData) const { OdGripPolylineMultiModeAppDataPtr appData = static_cast(pGripData->appData()); return appData->gripMode(); } namespace Trackers { inline double calcBulge(const OdGeCircArc2d& arc) { double ang = arc.endAng() - arc.startAng(); if (ang < 0.) ang += Oda2PI; return tan(ang * 0.25); } class PolyStretchTracker : public OdStaticRxObject { public: PolyStretchTracker() = delete; PolyStretchTracker(const OdDbPolylinePtr& org, const OdIntArray& indices, const OdGePoint3d& gripPnt) : m_pOrg(org), m_pPoly(org->clone()), m_indices(indices), m_gripPnt(gripPnt) { } virtual void setValue(const OdGePoint3d& value) { m_pPoly->copyFrom(m_pOrg); m_pPoly->moveGripPointsAt(m_indices, value - m_gripPnt); } virtual int addDrawables(OdGsView* pView) { pView->add(m_pPoly, 0); return 1; } virtual void removeDrawables(OdGsView* pView) { pView->erase(m_pPoly); } private: const OdDbPolylinePtr m_pOrg; OdDbPolylinePtr m_pPoly; const OdIntArray m_indices; const OdGePoint3d m_gripPnt; }; class PolyAddVertexTracker : public OdStaticRxObject { public: PolyAddVertexTracker() = delete; PolyAddVertexTracker(const OdDbPolylinePtr& org, const OdGePoint3d& pnt, unsigned index, double bulge, double endWidth) : m_pPoly(org->clone()), m_index(index + 1) { m_pPoly->addVertexAt(m_index, pnt.convert2d(), bulge, endWidth, endWidth); } virtual void setValue(const OdGePoint3d& value) { m_pPoly->setPointAt(m_index, value.convert2d()); } virtual int addDrawables(OdGsView* pView) { pView->add(m_pPoly, 0); return 1; } virtual void removeDrawables(OdGsView* pView) { pView->erase(m_pPoly); } private: OdDbPolylinePtr m_pPoly; const unsigned m_index; }; class PolyStretchArcTracker : public OdStaticRxObject { public: PolyStretchArcTracker() = delete; PolyStretchArcTracker(const OdDbPolylinePtr& org, unsigned index, const OdGeLineSeg2d& seg) : m_pPoly(org->clone()), m_index(index), m_seg(seg) { } virtual void setValue(const OdGePoint3d& value) { double bulge = 0.; if (!m_seg.isOn(value.convert2d())) { OdGeCircArc2d arc(m_seg.startPoint(), value.convert2d(), m_seg.endPoint()); bulge = calcBulge(arc); if (arc.isClockWise()) bulge = -bulge; } m_pPoly->setBulgeAt(m_index, bulge); m_bulge = bulge; } virtual int addDrawables(OdGsView* pView) { pView->add(m_pPoly, 0); return 1; } virtual void removeDrawables(OdGsView* pView) { pView->erase(m_pPoly); } double getBulge() const { return m_bulge; } private: OdDbPolylinePtr m_pPoly; const unsigned m_index; OdGeLineSeg2d m_seg; double m_bulge = 0.; }; class PolyExtendTracker : public OdStaticRxObject { public: PolyExtendTracker() = delete; PolyExtendTracker(const OdGePoint3d& pnt) : m_pLine(OdDbLine::createObject()) { m_pLine->setStartPoint(pnt); } virtual void setValue(const OdGePoint3d& value) { m_pLine->setEndPoint(value); } virtual int addDrawables(OdGsView* pView) { pView->add(m_pLine, 0); return 1; } virtual void removeDrawables(OdGsView* pView) { pView->erase(m_pLine); } private: OdDbLinePtr m_pLine; }; } bool OdDbPolylineMultiModesGripPE::setMode(OdDbEntity* pEnt, OdDbGripData* pGripData, unsigned int newMode) { OdDbPolylinePtr pPoly = pEnt; OdDbDatabase* pDb = pPoly->database(); OdDbCommandContextPtr pCmdCtx = OdDbCommandContext::registredCommandContext(pDb); OdDbUserIO* pIO = pCmdCtx->dbUserIO(); if (!pGripData) return false; OdGripPolylineMultiModeAppDataPtr appData = static_cast(pGripData->appData()); if (!appData) return false; appData->setMode(newMode); const OdDbMultiModesGripPE::GripMode curMode = appData->gripMode(); const unsigned index = appData->index(); try { switch (newMode) { case 101: { int nKeyword = 0; bool bKeyword = false; OdIntArray indices; if (!appData->getIndices(indices)) return false; try { Trackers::PolyStretchTracker tracker(pPoly, indices, pGripData->gripPoint()); OdGePoint3d pnt = pIO->getPoint(curMode.CLIPromptString, OdEd::kGptRubberBand, &pGripData->gripPoint(), curMode.CLIKeywordList, &tracker); pPoly->moveGripPointsAt(indices, pnt - pGripData->gripPoint()); } catch (const OdEdKeyword& kwd) { bKeyword = true; nKeyword = kwd.keywordIndex(); } catch (...) { throw; } if (bKeyword && nKeyword == 0) return false; break; } case 102: { const double bulge = pPoly->getBulgeAt(index); double swidth = 0., ewidth = 0.; pPoly->getWidthsAt(index, swidth, ewidth); Trackers::PolyAddVertexTracker tracker(pPoly, pGripData->gripPoint(), index, bulge, ewidth); OdGePoint3d pnt = pIO->getPoint(curMode.CLIPromptString, OdEd::kGptRubberBand, &pGripData->gripPoint(), curMode.CLIKeywordList, &tracker); pPoly->addVertexAt(index + 1, pnt.convert2d(), bulge, ewidth, ewidth); break; } case 103: { pIO->putString(curMode.CLIPromptString); pPoly->removeVertexAt(index); break; } case 104: { Trackers::PolyExtendTracker tracker(pGripData->gripPoint()); OdGePoint3d pnt = pIO->getPoint(curMode.CLIPromptString, OdEd::kGptRubberBand, &pGripData->gripPoint(), curMode.CLIKeywordList, &tracker); pPoly->addVertexAt(index == 0 ? index : index + 1, pnt.convert2d()); break; } case 105: { OdGeLineSeg2d seg; pPoly->getLineSegAt(index, seg); Trackers::PolyStretchArcTracker tracker(pPoly, appData->index(), seg); OdGePoint3d pnt = pIO->getPoint(curMode.CLIPromptString, OdEd::kGptRubberBand, &pGripData->gripPoint(), curMode.CLIKeywordList, &tracker); pPoly->setBulgeAt(index, tracker.getBulge()); break; } case 106: { pIO->putString(curMode.CLIPromptString); pPoly->setBulgeAt(index, 0.); break; } default: return false; } } catch (const OdEdCancel&) { return false; } return true; } OdDbMultiModesGripPE::GripType OdDbPolylineMultiModesGripPE::gripType(OdDbEntity*, OdDbGripData* pGripData) const { if (pGripData) { OdGripPolylineMultiModeAppDataPtr appData = static_cast(pGripData->appData()); if (appData) return appData->gripType(); } return OdDbMultiModesGripPE::kPrimary; } void OdDbPolylineMultiModesGripPE::reset(OdDbEntity*) { } void OdGripPolylineMultiModeAppData::initGripModes() { if (!m_modes.empty() || (m_polyGripType != DEFAULT_GRIP && m_polyGripType != BOUNDARY_GRIP && m_polyGripType != LINE_GRIP && m_polyGripType != ARC_GRIP)) return; { OdDbMultiModesGripPE::GripMode mode; mode.Mode = 101; if (m_polyGripType == DEFAULT_GRIP || m_polyGripType == BOUNDARY_GRIP) mode.DisplayString = "Stretch Vertex"; else mode.DisplayString = "Stretch"; mode.ActionType = OdDbMultiModesGripPE::GripActionType::kImmediate; mode.CLIDisplayString = "** STRETCH **"; mode.CLIPromptString = "Specify stretch point or [eXit]:"; mode.CLIKeywordList = "eXit"; m_modes[mode.Mode] = mode; } if (m_polyGripType == DEFAULT_GRIP || m_polyGripType == BOUNDARY_GRIP) { { OdDbMultiModesGripPE::GripMode mode; mode.Mode = 102; mode.DisplayString = "Add Vertex"; mode.ActionType = OdDbMultiModesGripPE::GripActionType::kImmediate; mode.CLIDisplayString = "** ADD VERTEX **"; mode.CLIPromptString = "Specify new vertex point:"; m_modes[mode.Mode] = mode; } { OdDbMultiModesGripPE::GripMode mode; mode.Mode = 103; mode.DisplayString = "Remove Vertex"; mode.ActionType = OdDbMultiModesGripPE::GripActionType::kImmediate; mode.CLIDisplayString = "** REMOVE VERTEX **"; mode.CLIPromptString = "Pick to remove vertex:"; m_modes[mode.Mode] = mode; } if (m_polyGripType == BOUNDARY_GRIP) { OdDbMultiModesGripPE::GripMode mode; mode.Mode = 104; mode.DisplayString = "Extend Vertex"; mode.ActionType = OdDbMultiModesGripPE::GripActionType::kImmediate; mode.CLIDisplayString = "** EXTEND VERTEX **"; mode.CLIPromptString = "Specify new vertex point:"; m_modes[mode.Mode] = mode; } } else if (m_polyGripType == LINE_GRIP || m_polyGripType == ARC_GRIP) { { OdDbMultiModesGripPE::GripMode mode; mode.Mode = 102; mode.DisplayString = "Add Vertex"; mode.ActionType = OdDbMultiModesGripPE::GripActionType::kImmediate; mode.CLIDisplayString = "** ADD VERTEX **"; mode.CLIPromptString = "Specify new vertex point:"; m_modes[mode.Mode] = mode; } { OdDbMultiModesGripPE::GripMode mode; if (m_polyGripType == LINE_GRIP) { mode.Mode = 105; mode.DisplayString = "Convert to Arc"; mode.ActionType = OdDbMultiModesGripPE::GripActionType::kImmediate; mode.CLIDisplayString = "** CONVERT TO ARC **"; mode.CLIPromptString = "Specify midpoint of arc segment:"; } else { mode.Mode = 106; mode.DisplayString = "Convert to Line"; mode.ActionType = OdDbMultiModesGripPE::GripActionType::kImmediate; mode.CLIDisplayString = "** CONVERT TO LINE **"; mode.CLIPromptString = "Pick to convert to line segment:"; } m_modes[mode.Mode] = mode; } } } void OdGripPolylineMultiModeAppData::getGripModes(OdArray& modes) { for (const auto& mode : m_modes) modes.append(mode.second); } bool OdGripPolylineMultiModeAppData::getIndices(OdIntArray& indices) const { if (m_polyGripType == OdGripPolylineMultiModeAppData::LINE_GRIP || m_polyGripType == OdGripPolylineMultiModeAppData::ARC_GRIP) indices.append(m_index * 2 + 1); else indices.append(m_index * 2); return true; }