//######################################################################################## #include "StdAfx.h" #include "DbMTextGripPoints.h" //---------------------------------------------------------------------------------------- #include #include #include #include //######################################################################################## //############### DbMTextGripPointsPE ############## //######################################################################################## OdResult OdDbMTextGripPointsPE::getGripPoints( const OdDbEntity* pEnt, OdGePoint3dArray& gripPoints )const { /* * ACAD has 3 different grip modes depending on column type (getColumnType()): * Here , only kNoColumns (default) mode is implemented: 4 points at extension corners + one at reference point, * kStaticColumns and kDynamicColumns mode not implemented. */ OdDbMTextPtr MText = pEnt; if (MText->width() < MText->textHeight()/10.0 ) { gripPoints.append(MText->location()); return eOk; } // define reference point Vs. text attachment OdGePoint3dArray boundingPoints; MText->getBoundingPoints(boundingPoints); // boundingPoints[0] Top left // boundingPoints[1] Top right // boundingPoints[2] Bottom left // boundingPoints[3] Bottom right OdGePoint3d ptRef; switch (MText->attachment()) { case OdDbMText::kTopLeft: ptRef = boundingPoints[0]; break; case OdDbMText::kTopCenter: ptRef = (boundingPoints[0] + boundingPoints[1].asVector()) / 2.; break; case OdDbMText::kTopRight: ptRef = boundingPoints[1]; break; case OdDbMText::kMiddleLeft: ptRef = (boundingPoints[0] + boundingPoints[2].asVector()) / 2.; break; case OdDbMText::kMiddleCenter: ptRef = (boundingPoints[3] + boundingPoints[0].asVector()) * 0.5; break; case OdDbMText::kMiddleRight: ptRef = (boundingPoints[1] + boundingPoints[3].asVector()) / 2.; break; case OdDbMText::kBottomLeft: ptRef = boundingPoints[2]; break; case OdDbMText::kBottomCenter: ptRef = (boundingPoints[2] + boundingPoints[3].asVector()) / 2.; break; case OdDbMText::kBottomRight: ptRef = boundingPoints[3]; break; default: break; } gripPoints.append(ptRef); gripPoints.append(boundingPoints); return eOk; } OdResult OdDbMTextGripPointsPE::moveGripPointsAt( OdDbEntity* pEnt, const OdIntArray& indices, const OdGeVector3d& offset ) { if ( indices.empty() ) return eOk; OdDbMTextPtr MText = pEnt; OdResult res = eOk; // check selected points int iBits = 0; for (int i : indices) { iBits |= (1 << i); } // move all the text if base point or 2 opposite corners selected if ((iBits & 1) // base point || ((iBits & 0x12) == 0x12) || ((iBits & 0x0c) == 0x0c) // 2 opposite corners selected ) res = pEnt->transformBy(OdGeMatrix3d::translation(offset)); else { // resize bounding rectangle; take into account that the text (and the rectangle) can be rotated. // here we can have 1 or 2 corner points selected // text may be rotated so calculate local CS OdGePoint3dArray boundingPoints; MText->getBoundingPoints(boundingPoints); OdGeVector3d vW = boundingPoints[1] - boundingPoints[0]; vW.normalize(); OdGeVector3d vH = boundingPoints[3] - boundingPoints[1]; vH.normalize(); int idxFix = -1; // bounding point index of the corner no to move; when we change width / height, all corners may move. if (indices.size() == 1) { // move one corner - resize bounding box double dW = vW.dotProduct(offset); double dH = vH.dotProduct(offset); switch (indices[0]) { case 1: dW = -dW; dH = -dH; idxFix = 3; // opposite corner break; case 2: dH = -dH; idxFix = 2; break; case 3: dW = -dW; idxFix = 1; break; case 4: idxFix = 0; break; } MText->setWidth(MText->width() + dW); MText->setHeight(MText->height() + dH); } else if (indices.size() == 2) { // move the edge; opposite corners case should be treated above switch (iBits & 0x1e) { case 0x6://0b00110: // grips 12 (top edge) MText->setHeight(MText->height() - vH.dotProduct(offset)); idxFix = 3; break; case 0x14://0b10100: // grips 24 (right edge) MText->setWidth(MText->width() + vW.dotProduct(offset)); idxFix = 0; break; case 0x18://0b11000: // grips 34 (bottom edge) MText->setHeight(MText->height() + vH.dotProduct(offset)); idxFix = 0; break; case 0xA://0b01010: // grips 13 (left edge) MText->setWidth(MText->width() - vW.dotProduct(offset)); idxFix = 3; break; } } // move the text to maintain idxFix in place OdGePoint3d ptFix = boundingPoints[idxFix]; boundingPoints.clear(); MText->getBoundingPoints(boundingPoints); OdGeVector3d vOff = ptFix - boundingPoints[idxFix]; res = pEnt->transformBy(OdGeMatrix3d::translation(vOff)); } return res; } OdResult OdDbMTextGripPointsPE::getStretchPoints( const OdDbEntity* ent, OdGePoint3dArray& stretchPoints ) const { OdResult res = getGripPoints( ent, stretchPoints ); return res; } OdResult OdDbMTextGripPointsPE::moveStretchPointsAt( OdDbEntity* ent, const OdIntArray& indices, const OdGeVector3d& offset ) { return moveGripPointsAt( ent, indices, offset); } OdResult OdDbMTextGripPointsPE::getOsnapPoints(const OdDbEntity* pEnt, OdDb::OsnapMode osnapMode, OdGsMarker /*gsSelectionMark*/, const OdGePoint3d& /*pickPoint*/, const OdGePoint3d& /*lastPoint*/, const OdGeMatrix3d& /*xWorldToEye*/, OdGePoint3dArray& snapPoints ) const { OdGePoint3dArray gripPoints; getGripPoints(pEnt, gripPoints); switch (osnapMode) { case OdDb::kOsModeEnd: // Endpoint - set bounding box corners for (unsigned i = 1; i < gripPoints.size(); i++) snapPoints.append(gripPoints[i]); break; case OdDb::kOsModeMid: // Midpoint - middles of sides if (gripPoints.size() >= 5) { snapPoints.append((gripPoints[1] + gripPoints[2].asVector()) * 0.5); snapPoints.append((gripPoints[2] + gripPoints[4].asVector()) * 0.5); snapPoints.append((gripPoints[3] + gripPoints[4].asVector()) * 0.5); snapPoints.append((gripPoints[3] + gripPoints[1].asVector()) * 0.5); } break; case OdDb::kOsModeCen: // Center - Bonding box center if (gripPoints.size() >= 5) { snapPoints.append((gripPoints[1] + gripPoints[4].asVector()) * 0.5); } break; case OdDb::kOsModeNode: // Node, case OdDb::kOsModeIns: // Insertion point - base point if (gripPoints.size() > 0) snapPoints.append(gripPoints[0]); break; default: break; } return eOk; }