/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, 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-2025 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 "OdDbGeoMapPEImpl.h" #include "OdDbGeoDataDrawingPE.h" #include "OdGeoMapTilesCache.h" #include "OdDbGeoMapHelper.h" #include "DbGeoMapFieldsPE.h" #include "DbViewportTable.h" #include "DbViewportTableRecord.h" ODRX_CONS_DEFINE_MEMBERS(OdDbGeoMapPEImpl, OdDbGeoMapPE, RXIMPL_CONSTR); OdResult getViewportDiagonalLength(const OdDbDatabase * pDb, double & dViewportDiagonalLength) { OdDbViewportTablePtr pVt = pDb->getViewportTableId().safeOpenObject(); OdDbViewportTableRecordPtr pVp = pVt->getActiveViewportId().safeOpenObject(); OdGsView* pView = pVp->gsView(); if (pView == NULL) { return eNullPtr; } OdGsDCRect screenRect; pView->getViewport(screenRect); OdGeVector2d ptViewportBox(screenRect.m_max.x - screenRect.m_min.x, screenRect.m_max.y - screenRect.m_min.y); dViewportDiagonalLength = ptViewportBox.length(); return eOk; } OdResult OdDbGeoMapPEImpl::updateMapImage(OdDbGeoMap* pGeoMap, bool bReset) { if (pGeoMap == NULL) { return eNullPtr; } OdDbGeoMapFieldsPEPtr pExt = OdDbGeoMap::desc()->getX(OdDbGeoMapFieldsPE::desc()); if (pExt.isNull()) { return eNoInterface; } OdDbGeoDataChunksPEPtr extGeoData = OdDbGeoData::desc()->getX(OdDbGeoDataChunksPE::desc()); if (!extGeoData.isNull() && !extGeoData->getMode()) { pExt->setIsOutOfDate(pGeoMap, true); return eDisabledInConfig; } //if update failed, values must be restored pExt->setIsOutOfDate(pGeoMap, false); // disable updateMapImage() in subClose() OdDbGeoMapPtr pBackupGeoMap = pGeoMap->clone(); OdDbObjectId objId; oddbGetGeoDataObjId(pGeoMap->database(), objId); OdDbGeoDataPtr pGeoData = objId.openObject(); if (pGeoData.isNull()) { pGeoMap->copyFrom(pBackupGeoMap); pExt->setIsOutOfDate(pGeoMap, true); return eNullPtr; } // determine OdGeoMapType: OdGeoMapType eGeoMapType = pGeoMap->mapType(); //get tile info: OdUInt32 uTileSize = 0; OdUInt8 uMinLOD = 0; OdUInt8 uMaxLOD = 0; OdResult res = g_OdGeoMapTilesCache->getTileInfo(eGeoMapType, uTileSize, uMinLOD, uMaxLOD); if (eOk != res) { return res; } OdGePoint3dArray arrVertices; pGeoMap->getVertices(arrVertices); OdGeExtents3d extents; extents.addPoints(arrVertices); double dMapDiagLength = extents.diagonal().length(); OdResult status = eOk; if (bReset) { double dViewportDiagLength = 0.; if (eOk != (status = getViewportDiagonalLength(pGeoData->database(), dViewportDiagLength))) { pGeoMap->copyFrom(pBackupGeoMap); pExt->setIsOutOfDate(pGeoMap, true); return status; } OdUInt8 uLOD = OdDbGeoMapHelper::getOptimalLOD(pGeoData, uMinLOD, uMaxLOD, uTileSize, dViewportDiagLength, dMapDiagLength); pExt->setLOD(pGeoMap, uLOD); pExt->setResolution(pGeoMap, kOptimal); } OdUInt8 uLOD = OdUInt8(odmin(odmax(pGeoMap->LOD() + pGeoMap->resolution(), uMinLOD), uMaxLOD)); // pre-request to check if we should reset geomap LOD { // create global map extents OdGePoint2dArray arrGlobalMapExtents; OdDbGeoMapHelper::getGlobalMapExtents(pGeoData, arrGlobalMapExtents); // get map extents OdGePoint2dArray arrViewExtents; { arrViewExtents.resize(arrVertices.size()); for (OdUInt32 i = 0; i < arrVertices.size(); ++i) { arrViewExtents[i] = arrVertices[i].convert2d(); } } // get all needed tiles std::set arrTiles; if (eOk != OdDbGeoMapHelper::getGeoMapTiles(arrTiles, pGeoData, eGeoMapType, uLOD, uTileSize, arrViewExtents, arrGlobalMapExtents)) { //reset double dViewportDiagLength; if (eOk != (status = getViewportDiagonalLength(pGeoData->database(), dViewportDiagLength))) { pGeoMap->copyFrom(pBackupGeoMap); pExt->setIsOutOfDate(pGeoMap, true); return status; } uLOD = OdDbGeoMapHelper::getOptimalLOD(pGeoData, uMinLOD, uMaxLOD, uTileSize, dViewportDiagLength, dMapDiagLength); pExt->setLOD(pGeoMap, uLOD); pExt->setResolution(pGeoMap, kOptimal); } } double dScale = 1.; OdDbGeoMapHelper::getImageScale(pGeoData, uLOD, uTileSize, dScale); OdGePoint3d ptImageBottomLeft; double dImageWidth, dImageHeight; OdUInt32 uWidth, uHeight; if (eOk != (status = OdDbGeoMapHelper::getImageSize(dScale, arrVertices, ptImageBottomLeft, uWidth, uHeight, dImageWidth, dImageHeight))) { pGeoMap->copyFrom(pBackupGeoMap); pExt->setIsOutOfDate(pGeoMap, true); return status; } pExt->setPtImageBottomLeft(pGeoMap, ptImageBottomLeft); pExt->setImageWidth(pGeoMap, dImageWidth); pExt->setImageHeight(pGeoMap, dImageHeight); pExt->setWidth(pGeoMap, uWidth); pExt->setHeight(pGeoMap, uHeight); //if image resolution is changed UV must be updated: OdGeVector3d vU(dImageWidth / uWidth, 0., 0.); OdGeVector3d vV(0., dImageHeight / uHeight, 0.); pExt->setvU(pGeoMap, vU); pExt->setvV(pGeoMap, vV); OdGePoint2dArray arrImageArea; arrImageArea.resize(arrVertices.size()); OdGePoint2dArray arrClipBnd; arrClipBnd.resize(arrVertices.size()); OdGeMatrix3d mat = pixelToModelTransform(ptImageBottomLeft, vU, vV, uHeight).inverse(); for (OdUInt32 i = 0; i < arrVertices.size(); ++i) { arrClipBnd[i] = (mat * arrVertices[i]).convert2d(); arrImageArea[i] = arrVertices[i].convert2d(); } pExt->setPtClipBnd(pGeoMap, arrClipBnd); OdBinaryData pixelData; if (eOk != (status = OdDbGeoMapHelper::getMap(pGeoMap, pixelData))) { pGeoMap->copyFrom(pBackupGeoMap); pExt->setIsOutOfDate(pGeoMap, true); return status; } pExt->setPixelData(pGeoMap, pixelData); // get copyright strings OdStringArray arrCopyrightStrings; res = g_OdGeoMapTilesCache->getCopyrightStrings(eGeoMapType, pGeoData, uLOD, arrImageArea, arrCopyrightStrings); if (eOk != res) { pGeoMap->copyFrom(pBackupGeoMap); pExt->setIsOutOfDate(pGeoMap, true); return res; } pExt->setStrings(pGeoMap, arrCopyrightStrings); //calculate text parameters: { // loading logo OdUInt32 uBrandLogoWidth = 0; OdUInt32 uBrandLogoHeight = 20; OdGiRasterImagePtr pRasterLogo; g_OdGeoMapTilesCache->getBrandLogo(eGeoMapType, pRasterLogo); if (pRasterLogo.get()) { uBrandLogoWidth = pRasterLogo->pixelWidth(); uBrandLogoHeight = pRasterLogo->pixelHeight(); } double dWidth = (arrVertices[1] - arrVertices[0]).length() * dScale; double dHeight = (arrVertices[2] - arrVertices[1]).length() * dScale; uWidth = 0; uHeight = 0; if (!OdDbGeoMapHelper::normalizeSize(dWidth, dHeight, uWidth, uHeight)) { uWidth = 1; uHeight = 1; } double dResolutionScale = pow(2.0, pGeoMap->resolution()); OdGeVector3d vVerticalShift = (arrVertices[2] - arrVertices[1]) * uBrandLogoHeight * 0.75 / uHeight * dResolutionScale; OdGeVector3d vHorizontalShift = (arrVertices[1] - arrVertices[0]).normal() * uBrandLogoWidth * vVerticalShift.length() / uBrandLogoHeight; OdGePoint3d ptTextPosition = arrVertices[1] + vVerticalShift / 2. - vHorizontalShift; double dTextHeight = vVerticalShift.length() * 0.25; pExt->setTextHeight(pGeoMap, dTextHeight); pExt->setPtTextPosition(pGeoMap, ptTextPosition); } OdCmColor color; OdDbGeoMapHelper::getTextColor(eGeoMapType, color); pExt->setTextColor(pGeoMap, color); pExt->setIsOutOfDate(pGeoMap, false); return eOk; }