📄 tabtext.cpp
字号:
// tabtext.cpp: implementation of the TABText class.////////////////////////////////////////////////////////////////////////#include "tabtext.h"#include "ugk_errhandle.h"#include "ugk_memopr.h"#include "ugk_string.h"#include "ugkpoint.h"#include "tabmapobjtext.h"/********************************************************************** * TABText::TABText() * * Constructor. **********************************************************************/TABText::TABText(UGKFeatureDefn *poDefnIn): TABFeature(poDefnIn){ m_pszString = NULL; m_dAngle = m_dHeight = 0.0; m_dfLineEndX = m_dfLineEndY = 0.0; m_bLineEndSet = FALSE; m_rgbForeground = 0x000000; m_rgbBackground = 0xffffff; m_nTextAlignment = 0; m_nFontStyle = 0; m_dWidth = 0;}/********************************************************************** * TABText::~TABText() * * Destructor. **********************************************************************/TABText::~TABText(){ UGK_Free(m_pszString);}/********************************************************************** * TABText::CloneTABFeature() * * Duplicate feature, including stuff specific to each TABFeature type. * * This method calls the generic TABFeature::CopyTABFeatureBase() and * then copies any members specific to its own type. **********************************************************************/TABFeature *TABText::CloneTABFeature(UGKFeatureDefn *poNewDefn/*=NULL*/){ /*----------------------------------------------------------------- * Alloc new feature and copy the base stuff *----------------------------------------------------------------*/ TABText *poNew = new TABText(poNewDefn ? poNewDefn : GetDefnRef()); CopyTABFeatureBase(poNew); /*----------------------------------------------------------------- * And members specific to this class *----------------------------------------------------------------*/ // ITABFeaturePen *(poNew->GetPenDefRef()) = *GetPenDefRef(); // ITABFeatureFont *(poNew->GetFontDefRef()) = *GetFontDefRef(); poNew->SetTextString( GetTextString() ); poNew->SetTextAngle( GetTextAngle() ); poNew->SetTextBoxHeight( GetTextBoxHeight() ); poNew->SetTextBoxWidth( GetTextBoxWidth() ); poNew->SetFontStyleTABValue( GetFontStyleTABValue() ); poNew->SetFontBGColor( GetFontBGColor() ); poNew->SetFontFGColor( GetFontFGColor() ); poNew->SetTextJustification( GetTextJustification() ); poNew->SetTextSpacing( GetTextSpacing() ); // Note: Text arrow/line coordinates are not transported... but // we ignore them most of the time anyways. poNew->SetTextLineType( TABTLNoLine ); return poNew;}/********************************************************************** * TABText::ValidateMapInfoType() * * Check the feature's geometry part and return the corresponding * mapinfo object type code. The m_nMapInfoType member will also * be updated for further calls to GetMapInfoType(); * * Returns TAB_GEOM_NONE if the geometry is not compatible with what * is expected for this object class. **********************************************************************/int TABText::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/){ UGKGeometry *poGeom; /*----------------------------------------------------------------- * Fetch and validate geometry *----------------------------------------------------------------*/ poGeom = GetGeometryRef(); if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint) { m_nMapInfoType = TAB_GEOM_TEXT; } else { UGKError(ET_Failure, UGKErr_AssertionFailed, "TABText: Missing or Invalid Geometry!"); m_nMapInfoType = TAB_GEOM_NONE; } /*----------------------------------------------------------------- * Decide if coordinates should be compressed or not. *----------------------------------------------------------------*/ // __TODO__ For now we always write uncompressed for this class... // ValidateCoordType(poMapFile); return m_nMapInfoType;}/********************************************************************** * TABText::ReadGeometryFromMAPFile() * * Fill the geometry and representation (color, etc...) part of the * feature from the contents of the .MAP object pointed to by poMAPFile. * * It is assumed that poMAPFile currently points to the beginning of * a map object. * * Returns 0 on success, -1 on error, in which case CPLError() will have * been called. **********************************************************************/int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *poObjHdr){ double dXMin, dYMin, dXMax, dYMax; UGKGeometry *poGeometry; TABMAPObjectBlock *poObjBlock; UGKBool bComprCoord; /*----------------------------------------------------------------- * Fetch and validate geometry type *----------------------------------------------------------------*/ m_nMapInfoType = poMapFile->GetCurObjType(); poObjBlock = poMapFile->GetCurObjBlock(); bComprCoord = (m_nMapInfoType == TAB_GEOM_TEXT_C); if (m_nMapInfoType == TAB_GEOM_TEXT || m_nMapInfoType == TAB_GEOM_TEXT_C ) { /*============================================================= * TEXT *============================================================*/ int nStringLen; UGKInt32 nCoordBlockPtr; UGKInt32 nX, nY; double dJunk; TABMAPCoordBlock *poCoordBlock; /*------------------------------------------------------------- * Read data from poObjBlock *------------------------------------------------------------*/ nCoordBlockPtr = poObjBlock->ReadInt32(); // String position nStringLen = poObjBlock->ReadInt16(); // String length m_nTextAlignment = poObjBlock->ReadInt16(); // just./spacing/arrow /*------------------------------------------------------------- * Text Angle, in thenths of degree. * Contrary to arc start/end angles, no conversion based on * origin quadrant is required here *------------------------------------------------------------*/ m_dAngle = poObjBlock->ReadInt16()/10.0; m_nFontStyle = poObjBlock->ReadInt16(); // Font style m_rgbForeground = poObjBlock->ReadByte()*256*256 + poObjBlock->ReadByte()*256 + poObjBlock->ReadByte(); m_rgbBackground = poObjBlock->ReadByte()*256*256 + poObjBlock->ReadByte()*256 + poObjBlock->ReadByte(); poObjBlock->ReadIntCoord(bComprCoord, nX, nY); // arrow endpoint poMapFile->Int2Coordsys(nX, nY, m_dfLineEndX, m_dfLineEndY); m_bLineEndSet = TRUE; // Text Height nY = bComprCoord? poObjBlock->ReadInt16():poObjBlock->ReadInt32(); poMapFile->Int2CoordsysDist(0, nY, dJunk, m_dHeight); m_nFontDefIndex = poObjBlock->ReadByte(); // Font name index poMapFile->ReadFontDef(m_nFontDefIndex, &m_sFontDef); poObjBlock->ReadIntCoord(bComprCoord, nX, nY); // Read MBR poMapFile->Int2Coordsys(nX, nY, dXMin, dYMin); poObjBlock->ReadIntCoord(bComprCoord, nX, nY); poMapFile->Int2Coordsys(nX, nY, dXMax, dYMax); m_nPenDefIndex = poObjBlock->ReadByte(); // Pen index for line poMapFile->ReadPenDef(m_nPenDefIndex, &m_sPenDef); /*------------------------------------------------------------- * Read text string from the coord. block * Note that the string may contain binary '\n' and '\\' chars * that we have to convert to an escaped form internally. *------------------------------------------------------------*/ char *pszTmpString = (char*)UGK_Malloc((nStringLen+1)*sizeof(char)); if (nStringLen > 0) { assert(nCoordBlockPtr > 0); poCoordBlock = poMapFile->GetCoordBlock(nCoordBlockPtr); if (poCoordBlock == NULL || poCoordBlock->ReadBytes(nStringLen,(UGKByte*)pszTmpString) != 0) { UGKError(ET_Failure, UGKErr_FileIO, "Failed reading text string at offset %d", nCoordBlockPtr); UGK_Free(pszTmpString); return -1; } } pszTmpString[nStringLen] = '\0'; UGK_Free(m_pszString); m_pszString = TABEscapeString(pszTmpString); if (pszTmpString != m_pszString) UGK_Free(pszTmpString); } else { UGKError(ET_Failure, UGKErr_AssertionFailed, "ReadGeometryFromMAPFile(): unsupported geometry type %d (0x%2.2x)", m_nMapInfoType, m_nMapInfoType); return -1; } /* Set/retrieve the MBR to make sure Mins are smaller than Maxs */ SetMBR(dXMin, dYMin, dXMax, dYMax); GetMBR(dXMin, dYMin, dXMax, dYMax); /*----------------------------------------------------------------- * Create an UGKPoint Geometry... * The point X,Y values will be the coords of the lower-left corner before * rotation is applied. (Note that the rotation in MapInfo is done around * the upper-left corner) * We need to calculate the true lower left corner of the text based * on the MBR after rotation, the text height and the rotation angle. *----------------------------------------------------------------*/ double dCos, dSin, dX, dY; dSin = sin(m_dAngle*PI/180.0); dCos = cos(m_dAngle*PI/180.0); if (dSin > 0.0 && dCos > 0.0) { dX = dXMin + m_dHeight * dSin; dY = dYMin; } else if (dSin > 0.0 && dCos < 0.0) { dX = dXMax; dY = dYMin - m_dHeight * dCos; } else if (dSin < 0.0 && dCos < 0.0) { dX = dXMax + m_dHeight * dSin; dY = dYMax; } else // dSin < 0 && dCos > 0 { dX = dXMin; dY = dYMax - m_dHeight * dCos; } poGeometry = new UGKPoint(dX, dY); SetGeometryDirectly(poGeometry); /*----------------------------------------------------------------- * Compute Text Width: the width of the Text MBR before rotation * in ground units... unfortunately this value is not stored in the * file, so we have to compute it with the MBR after rotation and * the height of the MBR before rotation: * With W = Width of MBR before rotation * H = Height of MBR before rotation * dX = Width of MBR after rotation * dY = Height of MBR after rotation * teta = rotation angle * * For [-PI/4..teta..+PI/4] or [3*PI/4..teta..5*PI/4], we'll use: * W = H * (dX - H * sin(teta)) / (H * cos(teta)) * * and for other teta values, use: * W = H * (dY - H * cos(teta)) / (H * sin(teta)) *----------------------------------------------------------------*/ dSin = ABS(dSin); dCos = ABS(dCos); if (m_dHeight == 0.0) m_dWidth = 0.0; else if ( dCos > dSin ) m_dWidth = m_dHeight * ((dXMax-dXMin) - m_dHeight*dSin) / (m_dHeight*dCos); else m_dWidth = m_dHeight * ((dYMax-dYMin) - m_dHeight*dCos) / (m_dHeight*dSin); m_dWidth = ABS(m_dWidth); return 0;}/********************************************************************** * TABText::WriteGeometryToMAPFile() * * Write the geometry and representation (color, etc...) part of the * feature to the .MAP object pointed to by poMAPFile. * * It is assumed that poMAPFile currently points to a valid map object. * * Returns 0 on success, -1 on error, in which case CPLError() will have * been called. **********************************************************************/int TABText::WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *poObjHdr){ UGKInt32 nX, nY, nXMin, nYMin, nXMax, nYMax; UGKGeometry *poGeom; UGKPoint *poPoint; UGKInt32 nCoordBlockPtr; TABMAPCoordBlock *poCoordBlock; int nStringLen; /*----------------------------------------------------------------- * We assume that ValidateMapInfoType() was called already and that * the type in poObjHdr->m_nType is valid. *----------------------------------------------------------------*/ assert(m_nMapInfoType == poObjHdr->m_nType); /*----------------------------------------------------------------- * Fetch and validate geometry *----------------------------------------------------------------*/ poGeom = GetGeometryRef(); if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint) poPoint = (UGKPoint*)poGeom; else { UGKError(ET_Failure, UGKErr_AssertionFailed, "TABText: Missing or Invalid Geometry!"); return -1; } poMapFile->Coordsys2Int(poPoint->getX(), poPoint->getY(), nX, nY); /*----------------------------------------------------------------- * Write string to a coord block first... * Note that the string may contain escaped "\"+"n" and "\"+"\" * sequences that we have to convert to binary chars '\n' and '\\' * for the MAP file. *----------------------------------------------------------------*/ poCoordBlock = poMapFile->GetCurCoordBlock(); poCoordBlock->StartNewFeature(); nCoordBlockPtr = poCoordBlock->GetCurAddress(); char *pszTmpString = TABUnEscapeString(m_pszString, TRUE); nStringLen = strlen(pszTmpString); if (nStringLen > 0) { poCoordBlock->WriteBytes(nStringLen, (UGKByte *)pszTmpString); } else { nCoordBlockPtr = 0; } if (pszTmpString != m_pszString) UGK_Free(pszTmpString); pszTmpString = NULL; /*----------------------------------------------------------------- * Copy object information *----------------------------------------------------------------*/ TABMAPObjText *poTextHdr = (TABMAPObjText *)poObjHdr; poTextHdr->m_nCoordBlockPtr = nCoordBlockPtr; // String position poTextHdr->m_nCoordDataSize = nStringLen; // String length poTextHdr->m_nTextAlignment = m_nTextAlignment; // just./spacing/arrow /*----------------------------------------------------------------- * Text Angle, (written in thenths of degrees) * Contrary to arc start/end angles, no conversion based on * origin quadrant is required here *----------------------------------------------------------------*/ poTextHdr->m_nAngle = ROUND_INT(m_dAngle*10.0); poTextHdr->m_nFontStyle = m_nFontStyle; // Font style/effect poTextHdr->m_nFGColorR = COLOR_R(m_rgbForeground); poTextHdr->m_nFGColorG = COLOR_G(m_rgbForeground); poTextHdr->m_nFGColorB = COLOR_B(m_rgbForeground); poTextHdr->m_nBGColorR = COLOR_R(m_rgbBackground); poTextHdr->m_nBGColorG = COLOR_G(m_rgbBackground); poTextHdr->m_nBGColorB = COLOR_B(m_rgbBackground); /*----------------------------------------------------------------- * The UGKPoint's X,Y values were the coords of the lower-left corner * before rotation was applied. (Note that the rotation in MapInfo is * done around the upper-left corner) * The Feature's MBR is the MBR of the text after rotation... that's * what MapInfo uses to define the text location. *----------------------------------------------------------------*/ double dXMin, dYMin, dXMax, dYMax; // Make sure Feature MBR is in sync with other params UpdateTextMBR();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -