/////////////////////////////////////////////////////////////////////////////// // 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 "OdaCommon.h" #include "DgGeoDataReprojection.h" #include "DgBRepEntityPE.h" #include "Ge/GePlane.h" #define MAX_NUMBER_OF_EXTRA_POINTS 64 //---------------------------------------------------------------------------------------------------------------------------------- bool transformLineSegment2dByGeoData(const OdGePoint2d& ptLast, const OdGePoint2d& ptNext, const OdGePoint2d& ptLastMod, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, double dStrokeTolerance, OdUInt64 nTotalPts, std::list& listSegmentPts, OdGePoint2d& ptNextMod) { bool bRet = true; ptNextMod = ptNext; if (pTransformer->transformPoint(ptNextMod) != eOk) return false; if( nTotalPts >= MAX_NUMBER_OF_EXTRA_POINTS ) listSegmentPts.insert(listSegmentPts.begin(), ptNextMod); else { if (ptLastMod.isEqualTo(ptNextMod, dStrokeTolerance)) { listSegmentPts.insert(listSegmentPts.begin(), ptNextMod); return true; } OdGePoint2d ptCenter = (ptNext + ptLast.asVector()) / 2.0; OdGePoint2d ptCenterMod = ptCenter; if( pTransformer->transformPoint(ptCenterMod) != eOk ) return false; double dAngle = (ptCenterMod - ptLastMod).angleTo(ptNextMod - ptLastMod); if( !OdZero(dAngle) ) { double dCurTolerance = ptLastMod.distanceTo(ptCenterMod) * sin(dAngle); if( dCurTolerance <= dStrokeTolerance ) listSegmentPts.insert(listSegmentPts.begin(), ptNextMod); else { std::list listLastCenter; std::list listCenterNext; if( transformLineSegment2dByGeoData(ptLast, ptCenter, ptLastMod, pTransformer, dStrokeTolerance, nTotalPts * 2, listLastCenter, ptCenterMod) ) listSegmentPts.insert(listSegmentPts.begin(), listLastCenter.begin(), listLastCenter.end()); else return false; if (transformLineSegment2dByGeoData(ptCenter, ptNext, ptCenterMod, pTransformer, dStrokeTolerance, nTotalPts * 2, listCenterNext, ptNextMod)) listSegmentPts.insert(listSegmentPts.begin(), listCenterNext.begin(), listCenterNext.end()); else return false; } } else listSegmentPts.insert(listSegmentPts.begin(), ptNextMod); } return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool transformLineSegment3dByGeoData(const OdGePoint3d& ptLast, const OdGePoint3d& ptNext, const OdGePoint3d& ptLastMod, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, double dStrokeTolerance, OdUInt64 nTotalPts, std::list& listSegmentPts, OdGePoint3d& ptNextMod) { bool bRet = true; ptNextMod = ptNext; if (pTransformer->transformPoint(ptNextMod) != eOk) return false; if (nTotalPts >= MAX_NUMBER_OF_EXTRA_POINTS) listSegmentPts.insert(listSegmentPts.begin(), ptNextMod); else { if (ptLastMod.isEqualTo(ptNextMod, dStrokeTolerance)) { listSegmentPts.insert(listSegmentPts.begin(), ptNextMod); return true; } OdGePoint3d ptCenter = (ptNext + ptLast.asVector()) / 2.0; OdGePoint3d ptCenterMod = ptCenter; if (pTransformer->transformPoint(ptCenterMod) != eOk) return false; double dAngle = (ptCenterMod - ptLastMod).angleTo(ptNextMod - ptLastMod); if (!OdZero(dAngle)) { double dCurTolerance = ptLastMod.distanceTo(ptCenterMod) * sin(dAngle); if (dCurTolerance <= dStrokeTolerance) listSegmentPts.insert(listSegmentPts.begin(), ptNextMod); else { std::list listLastCenter; std::list listCenterNext; if (transformLineSegment3dByGeoData(ptLast, ptCenter, ptLastMod, pTransformer, dStrokeTolerance, nTotalPts * 2, listLastCenter, ptCenterMod)) listSegmentPts.insert(listSegmentPts.begin(), listLastCenter.begin(), listLastCenter.end()); else return false; if (transformLineSegment3dByGeoData(ptCenter, ptNext, ptCenterMod, pTransformer, dStrokeTolerance, nTotalPts * 2, listCenterNext, ptNextMod)) listSegmentPts.insert(listSegmentPts.begin(), listCenterNext.begin(), listCenterNext.end()); else return false; } } else listSegmentPts.insert(listSegmentPts.begin(), ptNextMod); } return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool transformPolylineByGeoData( const OdGePoint2dArray& arrLinePts, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings, OdGePoint2dArray& arrTransformedPts, bool bAllowToAddPoints, bool bCheckBreaks ) { if( arrLinePts.isEmpty() ) return true; bool bRet = true; bool bAddPoints = reprojectionSettings.m_bAddPointsIfNeeded && bAllowToAddPoints && !OdZero(reprojectionSettings.m_dStrokeTolerance); if( bAddPoints ) { OdGePoint2d ptLast = arrLinePts[0]; OdGePoint2d ptLastMod = ptLast; if( pTransformer->transformPoint(ptLastMod) != eOk ) { arrTransformedPts = arrLinePts; bRet = false; } if( bRet ) { OdGePoint2d ptNext; OdGePoint2d ptNextMod; std::list listPts; listPts.insert(listPts.begin(), ptLastMod); for( OdUInt32 i = 1; i < arrLinePts.size(); i++ ) { OdGePoint2d ptNext = arrLinePts[i]; if (bCheckBreaks && ((ptNext.x > 1e100) || (ptNext.y > 1e100))) { listPts.insert(listPts.end(), ptLastMod); continue; } std::list listSegmentPts; if( transformLineSegment2dByGeoData(ptLast, ptNext, ptLastMod, pTransformer, reprojectionSettings.m_dStrokeTolerance, 2, listSegmentPts, ptNextMod) ) { listPts.insert(listPts.end(), listSegmentPts.begin(), listSegmentPts.end()); ptLast = ptNext; ptLastMod = ptNextMod; } else { arrTransformedPts = arrLinePts; bRet = false; break; } } if( bRet ) { arrTransformedPts.reserve((OdUInt32)listPts.size()); std::list::const_iterator pIter = listPts.begin(); for(; pIter != listPts.end(); pIter++) arrTransformedPts.push_back(*pIter); } } } else { arrTransformedPts.resize(arrLinePts.size()); for (OdUInt32 i = 0; i < arrLinePts.size(); i++) { OdGePoint2d ptCur = arrLinePts[i]; arrTransformedPts[i] = ptCur; if (bCheckBreaks && ((ptCur.x > 1e100) || (ptCur.y > 1e100))) continue; if (pTransformer->transformPoint(ptCur) != eOk) { arrTransformedPts = arrLinePts; bRet = false; break; } arrTransformedPts[i] = ptCur; } } return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool transformPolylineByGeoData(const OdGePoint3dArray& arrLinePts, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings, OdGePoint3dArray& arrTransformedPts, bool bAllowToAddPoints, bool bCheckBreaks) { if (arrLinePts.isEmpty()) return true; bool bRet = true; bool bAddPoints = reprojectionSettings.m_bAddPointsIfNeeded && bAllowToAddPoints && !OdZero(reprojectionSettings.m_dStrokeTolerance); if (bAddPoints) { OdGePoint3d ptLast = arrLinePts[0]; OdGePoint3d ptLastMod = ptLast; if (pTransformer->transformPoint(ptLastMod) != eOk) { arrTransformedPts = arrLinePts; bRet = false; } if (bRet) { OdGePoint3d ptNext; OdGePoint3d ptNextMod; std::list listPts; listPts.insert(listPts.begin(), ptLastMod); for (OdUInt32 i = 1; i < arrLinePts.size(); i++) { OdGePoint3d ptNext = arrLinePts[i]; if (bCheckBreaks && ((ptNext.x > 1e100) || (ptNext.y > 1e100) || (ptNext.z > 1e100))) { listPts.insert(listPts.end(), ptLastMod); continue; } std::list listSegmentPts; if (transformLineSegment3dByGeoData(ptLast, ptNext, ptLastMod, pTransformer, reprojectionSettings.m_dStrokeTolerance, 2, listSegmentPts, ptNextMod)) { listPts.insert(listPts.end(), listSegmentPts.begin(), listSegmentPts.end()); ptLast = ptNext; ptLastMod = ptNextMod; } else { arrTransformedPts = arrLinePts; bRet = false; break; } } if (bRet) { arrTransformedPts.reserve((OdUInt32)listPts.size()); std::list::const_iterator pIter = listPts.begin(); for (; pIter != listPts.end(); pIter++) arrTransformedPts.push_back(*pIter); } } } else { arrTransformedPts.resize(arrLinePts.size()); for (OdUInt32 i = 0; i < arrLinePts.size(); i++) { OdGePoint3d ptCur = arrLinePts[i]; arrTransformedPts[i] = ptCur; if (bCheckBreaks && ((ptCur.x > 1e100) || (ptCur.y > 1e100 || (ptCur.z > 1e100)))) continue; if (pTransformer->transformPoint(ptCur) != eOk) { arrTransformedPts = arrLinePts; bRet = false; break; } arrTransformedPts[i] = ptCur; } } return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- void setCurveElementPropertiesFrom(OdDgElement* pEntTo, const OdDgElement* pEntFrom, bool doSubents) { if(!pEntTo && !pEntFrom) return; pEntTo->setPropertiesFrom(pEntFrom, doSubents); // thickness if (!pEntTo->isKindOf(OdDgGraphicsElement::desc()) || !pEntFrom->isKindOf(OdDgGraphicsElement::desc())) return; OdDgGraphicsElement* pGrElmTo = (OdDgGraphicsElement*)(pEntTo); const OdDgGraphicsElement* pGrElmFrom = (const OdDgGraphicsElement*)(pEntFrom); pGrElmTo->setThickness(pGrElmFrom->getThickness()); // transparency pGrElmTo->setTransparency(pGrElmFrom->getTransparency()); // material, fill style, pattern bool bToClosed = false; bool bFromClosed = false; if (pEntTo->isKindOf(OdDgCurveElement2d::desc())) { OdDgCurveElement2d* pTo = (OdDgCurveElement2d*)pEntTo; bToClosed = pTo->isClosed(); } else if (pEntTo->isKindOf(OdDgCurveElement3d::desc())) { OdDgCurveElement3d* pTo = (OdDgCurveElement3d*)pEntTo; bToClosed = pTo->isClosed(); } if (pEntFrom->isKindOf(OdDgCurveElement2d::desc())) { OdDgCurveElement2d* pFrom = (OdDgCurveElement2d*)pEntFrom; bFromClosed = pFrom->isClosed(); } else if (pEntFrom->isKindOf(OdDgCurveElement3d::desc())) { OdDgCurveElement3d* pFrom = (OdDgCurveElement3d*)pEntFrom; bFromClosed = pFrom->isClosed(); } if (bToClosed && bFromClosed) { pGrElmTo->setMaterial(pGrElmFrom->getMaterial()); if (pGrElmFrom->getFillType() == OdDg::kFillColor) pGrElmTo->setFillColor(pGrElmFrom->getFillColorIndex()); else if (pGrElmFrom->getFillType() == OdDg::kGradientFill) pGrElmTo->setGradientFill(pGrElmFrom->getGradientFill()); pGrElmTo->setFillType(pGrElmFrom->getFillType()); pGrElmTo->setHatchPattern(pGrElmFrom->getHatchPattern()); } } //---------------------------------------------------------------------------------------------------------------------------------- bool calculateArc2dPoints(const OdGePoint2d& ptCenter, const OdGePoint2d& ptRef, const OdGePoint2d& ptStart, const OdGePoint2d& ptBase, OdGePoint2d& ptCenterMod, OdGeVector2d& vrMajor, OdGeVector2d& vrMinor, double& dMajorRadius, double& dMinorRadius) { bool bRet = false; vrMajor = ptRef - ptCenter; if( vrMajor.isZeroLength() ) return false; double dMajorR = vrMajor.length(); vrMajor.normalize(); vrMinor = vrMajor; vrMinor.rotateBy(OdaPI2); double dRotAngle = OdGeVector2d::kXAxis.angleToCCW(vrMajor); OdGeMatrix2d matTransform = OdGeMatrix2d::translation(ptCenter.asVector())*OdGeMatrix2d::rotation(dRotAngle); OdGeMatrix2d matTransformBack = matTransform; matTransformBack.invert(); OdGePoint2d ptCenterM = ptCenter; OdGePoint2d ptRefM = ptRef; OdGePoint2d ptStartM = ptStart; OdGePoint2d ptBaseM = ptBase; if( ptBase.isEqualTo(ptRef, 1e-7) ) { ptBaseM = ptStart; ptStartM = ptBase; } ptCenterM.transformBy(matTransformBack); ptRefM.transformBy(matTransformBack); ptStartM.transformBy(matTransformBack); ptBaseM.transformBy(matTransformBack); ODA_ASSERT_ONCE(ptCenterM.isEqualTo(OdGePoint2d::kOrigin)); // Calculate first value of major radius and minor radius. if ((fabs(ptBaseM.x) >= dMajorR) && (fabs(ptBaseM.y) >= dMajorR)) return false; double dMinorR = 0.0; if( (fabs(ptBaseM.x) >= dMajorR) ) { dMinorR = dMajorR; dMajorR = fabs(dMinorR * ptBaseM.x / sqrt(dMinorR * dMajorR - ptBaseM.y * ptBaseM.y)); } else { dMinorR = fabs(dMajorR * ptBaseM.y / sqrt(dMajorR * dMajorR - ptBaseM.x * ptBaseM.x)); } bool bAllowMinorRadiusCorrection = false; bool bAllowMajorRadiusCorrection = false; double dCorrectedMinorRadius = 0.0; double dCorrectedMajorRadius = 0.0; double dCorrectedMinorCenterYOffset = 0.0; double dCorrectedMajorCenterYOffset = 0.0; // Try to calculate offset of center point and new minor radius by fixing of major radius and moving center point through y axis. if( fabs(ptStartM.x) < dMajorR ) { double m = 1.0 - ptBaseM.x * ptBaseM.x / dMajorR / dMajorR; double n = 1.0 - ptStartM.x * ptStartM.x / dMajorR / dMajorR; double a = n - m; double b = 2 * (m*ptStartM.y - n * ptBaseM.y); double c = n * ptBaseM.y * ptBaseM.y - m * ptStartM.y * ptStartM.y; double dDet = b * b - 4*a*c; if( dDet >= 0 ) { double dCenterY1 = (-b - sqrt(dDet)) / (2 * a); double dCenterY2 = (-b + sqrt(dDet)) / (2 * a); double dSqrMinorR1 = (ptStartM.y - dCenterY1) * (ptStartM.y - dCenterY1)*dMajorR*dMajorR / (dMajorR * dMajorR - ptStartM.x * ptStartM.x); double dSqrMinorR2 = (ptStartM.y - dCenterY2) * (ptStartM.y - dCenterY2)*dMajorR*dMajorR / (dMajorR * dMajorR - ptStartM.x * ptStartM.x); if( (dSqrMinorR1 > 0) && (dSqrMinorR2 > 0) ) { if( (dSqrMinorR1 - dMinorR * dMinorR) < (dSqrMinorR2 - dMinorR * dMinorR) ) { dCorrectedMinorRadius = sqrt(dSqrMinorR1); dCorrectedMinorCenterYOffset = dCenterY1; } else { dCorrectedMinorRadius = sqrt(dSqrMinorR2); dCorrectedMinorCenterYOffset = dCenterY2; } bAllowMinorRadiusCorrection = dCorrectedMinorRadius < 1e100; } else if (dSqrMinorR1 > 0) { dCorrectedMinorRadius = sqrt(dSqrMinorR1); dCorrectedMinorCenterYOffset = dCenterY1; bAllowMinorRadiusCorrection = dCorrectedMinorRadius < 1e100; } else if (dSqrMinorR2 > 0) { dCorrectedMinorRadius = sqrt(dSqrMinorR2); dCorrectedMinorCenterYOffset = dCenterY2; bAllowMinorRadiusCorrection = dCorrectedMinorRadius < 1e100; } } } // Try to calculate offset of center point and new major radius by fixing of minor radius and moving center point through y axis. if (fabs(ptStartM.y) < dMinorR) { double a = ptStartM.x*ptStartM.x - ptBaseM.x*ptBaseM.x; double b = 2 * (ptBaseM.x*ptBaseM.x*ptStartM.y - ptStartM.x*ptStartM.x * ptBaseM.y); double c = ptStartM.x*ptStartM.x * ptBaseM.y * ptBaseM.y - ptBaseM.x*ptBaseM.x * ptStartM.y * ptStartM.y + (ptBaseM.x*ptBaseM.x - ptStartM.x*ptStartM.x) * dMinorR * dMinorR; double dDet = b * b - 4 * a*c; if (dDet >= 0) { double dCenterY1 = (-b - sqrt(dDet)) / (2 * a); double dCenterY2 = (-b + sqrt(dDet)) / (2 * a); double dSqrMajorR1 = ptStartM.x*ptStartM.x*dMinorR*dMinorR / (dMinorR*dMinorR - (ptStartM.y - dCenterY1)*(ptStartM.y - dCenterY1)); double dSqrMajorR2 = ptStartM.x*ptStartM.x*dMinorR*dMinorR / (dMinorR*dMinorR - (ptStartM.y - dCenterY2)*(ptStartM.y - dCenterY2)); if ((dSqrMajorR1 > 0) && (dSqrMajorR2 > 0)) { if ((dSqrMajorR1 - dMajorR * dMajorR) < (dSqrMajorR2 - dMajorR * dMajorR)) { dCorrectedMajorRadius = sqrt(dSqrMajorR1); dCorrectedMajorCenterYOffset = dCenterY1; } else { dCorrectedMajorRadius = sqrt(dSqrMajorR2); dCorrectedMajorCenterYOffset = dCenterY2; } bAllowMajorRadiusCorrection = dCorrectedMajorRadius < 1e100; } else if (dSqrMajorR1 > 0) { dCorrectedMajorRadius = sqrt(dSqrMajorR1); dCorrectedMajorCenterYOffset = dCenterY1; bAllowMajorRadiusCorrection = dCorrectedMajorRadius < 1e100; } else if (dSqrMajorR2 > 0) { dCorrectedMajorRadius = sqrt(dSqrMajorR2); dCorrectedMajorCenterYOffset = dCenterY2; bAllowMajorRadiusCorrection = dCorrectedMajorRadius < 1e100; } } } if( bAllowMajorRadiusCorrection && bAllowMinorRadiusCorrection ) { if( fabs(dMajorR - dCorrectedMajorRadius) < fabs(dMinorR - dCorrectedMinorRadius) ) { dMajorRadius = dCorrectedMajorRadius; dMinorRadius = dMinorR; ptCenterM.y += dCorrectedMajorCenterYOffset; ptCenterMod = ptCenterM; ptCenterMod.transformBy(matTransform); } else { dMajorRadius = dMajorR; dMinorRadius = dCorrectedMinorRadius; ptCenterM.y += dCorrectedMinorCenterYOffset; ptCenterMod = ptCenterM; ptCenterMod.transformBy(matTransform); } return true; } else if (bAllowMajorRadiusCorrection) { dMajorRadius = dCorrectedMajorRadius; dMinorRadius = dMinorR; ptCenterM.y += dCorrectedMajorCenterYOffset; ptCenterMod = ptCenterM; ptCenterMod.transformBy(matTransform); return true; } else if (bAllowMinorRadiusCorrection) { dMajorRadius = dMajorR; dMinorRadius = dCorrectedMinorRadius; ptCenterM.y += dCorrectedMinorCenterYOffset; ptCenterMod = ptCenterM; ptCenterMod.transformBy(matTransform); return true; } double dCorrectedMinorCenterXOffset = 0.0; double dCorrectedMajorCenterXOffset = 0.0; // Try to calculate offset of center point and new minor radius by fixing of major radius and moving center point through x axis. if (fabs(ptStartM.x) < dMajorR) { double a = ptStartM.y*ptStartM.y - ptBaseM.y*ptBaseM.y; double b = 2 * (ptBaseM.y*ptBaseM.y*ptStartM.x - ptStartM.y*ptStartM.y * ptBaseM.x); double c = ptStartM.y*ptStartM.y * ptBaseM.x * ptBaseM.x - ptBaseM.y*ptBaseM.y * ptStartM.x * ptStartM.x + (ptBaseM.y*ptBaseM.y - ptStartM.y*ptStartM.y) * dMajorR * dMajorR; double dDet = b * b - 4 * a*c; if (dDet >= 0) { double dCenterX1 = (-b - sqrt(dDet)) / (2 * a); double dCenterX2 = (-b + sqrt(dDet)) / (2 * a); double dSqrMinorR1 = ptStartM.y*ptStartM.y*dMajorR*dMajorR / (dMajorR*dMajorR - (ptStartM.x - dCenterX1)*(ptStartM.x - dCenterX1)); double dSqrMinorR2 = ptStartM.y*ptStartM.y*dMajorR*dMajorR / (dMajorR*dMajorR - (ptStartM.x - dCenterX2)*(ptStartM.x - dCenterX2)); double dMinorR1 = sqrt(dSqrMinorR1); double dMinorR2 = sqrt(dSqrMinorR2); if ((dSqrMinorR1 > 0) && (dSqrMinorR2 > 0)) { if ((dSqrMinorR1 - dMinorR * dMinorR) < (dSqrMinorR2 - dMinorR * dMinorR)) { dCorrectedMinorRadius = sqrt(dSqrMinorR1); dCorrectedMinorCenterXOffset = dCenterX1; } else { dCorrectedMinorRadius = sqrt(dSqrMinorR2); dCorrectedMinorCenterXOffset = dCenterX2; } bAllowMinorRadiusCorrection = dCorrectedMinorRadius < 1e100; } else if (dSqrMinorR1 > 0) { dCorrectedMinorRadius = sqrt(dSqrMinorR1); dCorrectedMinorCenterXOffset = dCenterX1; bAllowMinorRadiusCorrection = dCorrectedMinorRadius < 1e100; } else if (dSqrMinorR2 > 0) { dCorrectedMinorRadius = sqrt(dSqrMinorR2); dCorrectedMinorCenterXOffset = dCenterX2; bAllowMinorRadiusCorrection = dCorrectedMinorRadius < 1e100; } } } // Try to calculate offset of center point and new major radius by fixing of minor radius and moving center point through x axis. if (fabs(ptStartM.y) < dMinorR) { double m = 1.0 - ptBaseM.y * ptBaseM.y / dMinorR / dMinorR; double n = 1.0 - ptStartM.y * ptStartM.y / dMinorR / dMinorR; double a = n - m; double b = 2 * (m*ptStartM.x - n * ptBaseM.x); double c = n * ptBaseM.x * ptBaseM.x - m * ptStartM.x * ptStartM.x; double dDet = b * b - 4 * a*c; if (dDet >= 0) { double dCenterX1 = (-b - sqrt(dDet)) / (2 * a); double dCenterX2 = (-b + sqrt(dDet)) / (2 * a); double dSqrMajorR1 = (ptStartM.x - dCenterX1) * (ptStartM.x - dCenterX1)*dMinorR*dMinorR / (dMinorR * dMinorR - ptStartM.y * ptStartM.y); double dSqrMajorR2 = (ptStartM.x - dCenterX2) * (ptStartM.x - dCenterX2)*dMinorR*dMinorR / (dMinorR * dMinorR - ptStartM.y * ptStartM.y); if ((dSqrMajorR1 > 0) && (dSqrMajorR2 > 0)) { if ((dSqrMajorR1 - dMajorR * dMajorR) < (dSqrMajorR2 - dMajorR * dMajorR)) { dCorrectedMajorRadius = sqrt(dSqrMajorR1); dCorrectedMajorCenterXOffset = dCenterX1; } else { dCorrectedMajorRadius = sqrt(dSqrMajorR2); dCorrectedMajorCenterXOffset = dCenterX2; } bAllowMajorRadiusCorrection = dCorrectedMajorRadius < 1e100; } else if (dSqrMajorR1 > 0) { dCorrectedMajorRadius = sqrt(dSqrMajorR1); dCorrectedMajorCenterXOffset = dCenterX1; bAllowMajorRadiusCorrection = dCorrectedMajorRadius < 1e100; } else if (dSqrMajorR2 > 0) { dCorrectedMajorRadius = sqrt(dSqrMajorR2); dCorrectedMajorCenterXOffset = dCenterX2; bAllowMajorRadiusCorrection = dCorrectedMajorRadius < 1e100; } } } if (bAllowMajorRadiusCorrection && bAllowMinorRadiusCorrection) { if (fabs(dMajorR - dCorrectedMajorRadius) < fabs(dMinorR - dCorrectedMinorRadius)) { dMajorRadius = dCorrectedMajorRadius; dMinorRadius = dMinorR; ptCenterM.x += dCorrectedMajorCenterXOffset; ptCenterMod = ptCenterM; ptCenterMod.transformBy(matTransform); } else { dMajorRadius = dMajorR; dMinorRadius = dCorrectedMinorRadius; ptCenterM.x += dCorrectedMinorCenterXOffset; ptCenterMod = ptCenterM; ptCenterMod.transformBy(matTransform); } return true; } else if (bAllowMajorRadiusCorrection) { dMajorRadius = dCorrectedMajorRadius; dMinorRadius = dMinorR; ptCenterM.x += dCorrectedMajorCenterXOffset; ptCenterMod = ptCenterM; ptCenterMod.transformBy(matTransform); return true; } else if (bAllowMinorRadiusCorrection) { dMajorRadius = dMajorR; dMinorRadius = dCorrectedMinorRadius; ptCenterM.x += dCorrectedMinorCenterXOffset; ptCenterMod = ptCenterM; ptCenterMod.transformBy(matTransform); return true; } return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectGeArc2d(const OdGeEllipArc2d& ellipArc, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, OdGeEllipArc2d& ellipArcMod) { OdGeInterval ellipInterval; ellipArc.getInterval(ellipInterval); double dInterval = ellipInterval.upperBound() - ellipInterval.lowerBound(); OdGePoint2d ptCenter = ellipArc.center(); OdGePoint2d ptStart = ellipArc.startPoint(); OdGePoint2d ptEnd = ellipArc.endPoint(); OdGePoint2d ptRef = ptCenter + ellipArc.majorAxis() * ellipArc.majorRadius(); OdGePoint2d ptCheck = ellipArc.evalPoint((ellipInterval.lowerBound() + ellipInterval.upperBound()) / 2.0); bool bEllipse = false; if (OdEqual(dInterval, Oda2PI, 1e-6)) { ptCheck = ellipArc.evalPoint((ellipInterval.lowerBound() + ellipInterval.upperBound()) / 4.0); bEllipse = true; } OdGePoint2d ptCenterMod = ptCenter; OdGePoint2d ptStartMod = ptStart; OdGePoint2d ptEndMod = ptEnd; OdGePoint2d ptRefMod = ptRef; OdGePoint2d ptCheckMod = ptCheck; if( pTransformer->transformPoint(ptCenterMod) != eOk ) return false; if( OdZero(ellipArc.majorRadius()) || OdZero(ellipArc.minorRadius()) ) { ellipArcMod = ellipArc; OdGeVector2d vrOffset = ptCenterMod - ptCenter; OdGeMatrix2d matTransform = OdGeMatrix2d::translation(vrOffset); ellipArcMod.transformBy(matTransform); return true; } if( pTransformer->transformPoint(ptStartMod) != eOk ) return false; if( pTransformer->transformPoint(ptEndMod) != eOk ) return false; if( pTransformer->transformPoint(ptRefMod) != eOk ) return false; if( pTransformer->transformPoint(ptCheckMod) != eOk ) return false; OdGePoint2d ptBase = ptEndMod; if( OdEqual(dInterval, Oda2PI, 1e-6) || OdEqual(dInterval, OdaPI, 1e-6)) { if (!ptStartMod.isEqualTo(ptEndMod)) ptCenterMod = (ptStartMod + ptEndMod.asVector()) / 2.0; ptBase = ptCheckMod; } double dMajorRadius, dMinorRadius; OdGeVector2d vrMajor, vrMinor; if( !calculateArc2dPoints(ptCenterMod, ptRefMod, ptStartMod, ptBase, ptCenterMod, vrMajor, vrMinor, dMajorRadius, dMinorRadius) ) return false; if( dMajorRadius > dMinorRadius ) { OdGeVector2d vrTmp = vrMajor; vrMajor = vrMinor; vrMinor = vrTmp; double dTmp = dMajorRadius; dMajorRadius = dMinorRadius; dMinorRadius = dTmp; } ellipArcMod.set(ptCenterMod, vrMajor, vrMinor, dMajorRadius, dMinorRadius); if( !bEllipse ) { double dStartAngle = ellipArcMod.paramOf(ptStartMod); double dEndAngle = ellipArcMod.paramOf(ptEndMod); double dCheckAngle = ellipArcMod.paramOf(ptCheckMod); if (dEndAngle < dStartAngle) dEndAngle += Oda2PI; bool bChangeDirection = false; if ((dStartAngle > dCheckAngle) || (dEndAngle < dCheckAngle)) bChangeDirection = true; if (bChangeDirection) { double dTmp = dEndAngle; dEndAngle = dStartAngle; dStartAngle = dTmp; } ellipArcMod.setAngles(dStartAngle, dEndAngle); OdGePoint2d ptArcStart = ellipArcMod.startPoint(); if (ptArcStart.distanceTo(ptEndMod) < ptArcStart.distanceTo(ptStartMod)) ellipArcMod.reverseParam(); } return true; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectGeArc3d(const OdGeEllipArc3d& ellipArc, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, bool bRecalculateNormal, OdGeEllipArc3d& ellipArcMod) { OdGeInterval ellipInterval; ellipArc.getInterval(ellipInterval); double dInterval = ellipInterval.upperBound() - ellipInterval.lowerBound(); OdGePoint3d ptCenter = ellipArc.center(); OdGePoint3d ptStart = ellipArc.startPoint(); OdGePoint3d ptEnd = ellipArc.endPoint(); OdGePoint3d ptRef = ptCenter + ellipArc.majorAxis() * ellipArc.majorRadius(); OdGePoint3d ptCheck = ellipArc.evalPoint((ellipInterval.lowerBound() + ellipInterval.upperBound()) / 2.0); bool bEllipse = false; if (OdEqual(dInterval, Oda2PI)) { ptCheck = ellipArc.evalPoint((ellipInterval.lowerBound() + ellipInterval.upperBound()) / 4.0); bEllipse = true; } OdGePoint3d ptCenterMod = ptCenter; OdGePoint3d ptStartMod = ptStart; OdGePoint3d ptEndMod = ptEnd; OdGePoint3d ptRefMod = ptRef; OdGePoint3d ptCheckMod = ptCheck; OdGeVector3d vrNormal = ellipArc.normal(); if (pTransformer->transformPoint(ptCenterMod) != eOk) return false; if (OdZero(ellipArc.majorRadius()) || OdZero(ellipArc.minorRadius())) { ellipArcMod = ellipArc; OdGeVector3d vrOffset = ptCenterMod - ptCenter; OdGeMatrix3d matTransform = OdGeMatrix3d::translation(vrOffset); ellipArcMod.transformBy(matTransform); return true; } if (pTransformer->transformPoint(ptStartMod) != eOk) return false; if (pTransformer->transformPoint(ptEndMod) != eOk) return false; if (pTransformer->transformPoint(ptRefMod) != eOk) return false; if (pTransformer->transformPoint(ptCheckMod) != eOk) return false; OdGePoint3d ptBase = ptEndMod; OdGeVector3d vrStart = ptStartMod - ptCenterMod; OdGeVector3d vrEnd = ptEndMod - ptCenterMod; double dAngle = vrStart.angleTo(vrEnd); if (dAngle > OdaPI2) dAngle -= OdaPI; if( fabs(dAngle) < 1e-6 ) { if( !ptStartMod.isEqualTo(ptEndMod) ) ptCenterMod = (ptStartMod + ptEndMod.asVector()) / 2.0; ptBase = ptCheckMod; vrEnd = ptCheckMod - ptCenterMod; } if( bRecalculateNormal ) { vrNormal = vrStart.crossProduct(vrEnd); vrNormal.normalize(); } else { OdGeVector3d vrStartEnd = ptStartMod - ptBase; vrStartEnd.normalize(); if( !vrStartEnd.isPerpendicularTo(vrNormal) ) { OdGeVector3d vrYNormal = vrNormal.crossProduct(vrStartEnd); vrYNormal.normalize(); vrNormal = vrStartEnd.crossProduct(vrYNormal); vrNormal.normalize(); OdGePlane planeBase(ptStartMod, vrNormal); ptCenterMod = ptCenterMod.project(planeBase, vrNormal); } } OdGePlane planeEllipse(ptCenterMod, vrNormal); ptRefMod = ptRefMod.project(planeEllipse, vrNormal); ptCheckMod = ptCheckMod.project(planeEllipse, vrNormal); OdGeMatrix3d matToPlane = OdGeMatrix3d::worldToPlane(vrNormal); OdGeMatrix3d matToWorld = matToPlane; matToWorld.invert(); ptCenterMod.transformBy(matToPlane); ptRefMod.transformBy(matToPlane); ptStartMod.transformBy(matToPlane); ptBase.transformBy(matToPlane); double dMajorRadius, dMinorRadius; OdGePoint2d ptNewCenter; OdGeVector2d vrMajor, vrMinor; if (!calculateArc2dPoints(ptCenterMod.convert2d(), ptRefMod.convert2d(), ptStartMod.convert2d(), ptBase.convert2d(), ptNewCenter, vrMajor, vrMinor, dMajorRadius, dMinorRadius)) return false; if (dMajorRadius > dMinorRadius) { OdGeVector2d vrTmp = vrMajor; vrMajor = vrMinor; vrMinor = vrTmp; double dTmp = dMajorRadius; dMajorRadius = dMinorRadius; dMinorRadius = dTmp; } ptCenterMod.set(ptNewCenter.x, ptNewCenter.y, ptCenterMod.z); OdGeVector3d vrMajor3d(vrMajor.x, vrMajor.y, 0.0); OdGeVector3d vrMinor3d(vrMinor.x, vrMinor.y, 0.0); ptCenterMod.transformBy(matToWorld); ptStartMod.transformBy(matToWorld); vrMajor3d.transformBy(matToWorld); vrMinor3d.transformBy(matToWorld); ellipArcMod.set(ptCenterMod, vrMajor3d, vrMinor3d, dMajorRadius, dMinorRadius); if( !bEllipse ) { double dStartAngle = ellipArcMod.paramOf(ptStartMod); double dEndAngle = ellipArcMod.paramOf(ptEndMod); double dCheckAngle = ellipArcMod.paramOf(ptCheckMod); if (dEndAngle < dStartAngle) dEndAngle += Oda2PI; bool bChangeDirection = false; if ((dStartAngle > dCheckAngle) || (dEndAngle < dCheckAngle)) bChangeDirection = true; if (bChangeDirection) { double dTmp = dEndAngle; dEndAngle = dStartAngle; dStartAngle = dTmp; } ellipArcMod.setAngles(dStartAngle, dEndAngle); OdGePoint3d ptArcStart = ellipArcMod.startPoint(); if (ptArcStart.distanceTo(ptEndMod) < ptArcStart.distanceTo(ptStartMod)) ellipArcMod.reverseParam(); } return true; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgnElementByGeoData(OdDgElement* pElm, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { if( !pElm || !pTransformer ) return false; if( pElm->isKindOf(OdDgModel::desc()) ) return reprojectDgModelByGeoData((OdDgModel*)pElm, pTransformer, reprojectionSettings); else if( pElm->isKindOf(OdDgLine2d::desc()) ) return reprojectDgLine2dByGeoData((OdDgLine2d*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgLine3d::desc())) return reprojectDgLine3dByGeoData((OdDgLine3d*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgLineString2d::desc())) return reprojectDgMultiVertex2dByGeoData((OdDgMultiVertex2d*)pElm, pTransformer, reprojectionSettings, true, true); else if (pElm->isKindOf(OdDgLineString3d::desc())) return reprojectDgMultiVertex3dByGeoData((OdDgMultiVertex3d*)pElm, pTransformer, reprojectionSettings, true, true); else if (pElm->isKindOf(OdDgShape2d::desc())) return reprojectDgMultiVertex2dByGeoData((OdDgMultiVertex2d*)pElm, pTransformer, reprojectionSettings, true); else if (pElm->isKindOf(OdDgShape3d::desc())) return reprojectDgMultiVertex3dByGeoData((OdDgMultiVertex3d*)pElm, pTransformer, reprojectionSettings, true); else if (pElm->isKindOf(OdDgPointString2d::desc())) return reprojectDgMultiVertex2dByGeoData((OdDgMultiVertex2d*)pElm, pTransformer, reprojectionSettings, false); else if (pElm->isKindOf(OdDgPointString3d::desc())) return reprojectDgMultiVertex3dByGeoData((OdDgMultiVertex3d*)pElm, pTransformer, reprojectionSettings, false); else if (pElm->isKindOf(OdDgArc2d::desc())) return reprojectDgArc2dByGeoData((OdDgArc2d*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgArc3d::desc())) return reprojectDgArc3dByGeoData((OdDgArc3d*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgEllipse2d::desc())) return reprojectDgEllipse2dByGeoData((OdDgEllipse2d*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgEllipse3d::desc())) return reprojectDgEllipse3dByGeoData((OdDgEllipse3d*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgCurve2d::desc())) return reprojectDgCurve2dByGeoData((OdDgCurve2d*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgCurve3d::desc())) return reprojectDgCurve3dByGeoData((OdDgCurve3d*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgBSplineCurve2d::desc())) return reprojectDgBSplineCurve2dByGeoData((OdDgBSplineCurve2d*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgBSplineCurve3d::desc())) return reprojectDgBSplineCurve3dByGeoData((OdDgBSplineCurve3d*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgComplexCurve::desc())) return reprojectDgComplexCurveByGeoData((OdDgComplexCurve*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgMultiline::desc())) return reprojectDgMultiLineByGeoData((OdDgMultiline*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgText2d::desc())) return reprojectDgText2dByGeoData((OdDgText2d*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgText3d::desc())) return reprojectDgText3dByGeoData((OdDgText3d*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgTagElement::desc())) return reprojectDgTagElementByGeoData((OdDgTagElement*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgTextNode2d::desc())) return reprojectDgTextNode2dByGeoData((OdDgTextNode2d*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgTextNode3d::desc())) return reprojectDgTextNode3dByGeoData((OdDgTextNode3d*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgTerrain::desc())) return reprojectDgTerrainByGeoData((OdDgTerrain*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgCellHeader2d::desc())) return reprojectDgCellHeader2dByGeoData((OdDgCellHeader2d*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgCellHeader3d::desc())) return reprojectDgCellHeader3dByGeoData((OdDgCellHeader3d*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgSharedCellReference::desc())) return reprojectDgSharedCellByGeoData((OdDgSharedCellReference*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgMesh::desc())) return reprojectDgMeshByGeoData((OdDgMesh*)pElm, pTransformer, reprojectionSettings); else if (pElm->isKindOf(OdDgBSplineSurface::desc())) return reprojectDgBSplineSurfaceByGeoData((OdDgBSplineSurface*)pElm, pTransformer, reprojectionSettings); else return reprojectDgElementByGeoData(pElm, pTransformer, reprojectionSettings); } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgTerrainByGeoData(OdDgTerrain* pTerrain, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { if (reprojectionSettings.m_bReprojectTerrainElementPoints) { OdDgElementId idCtrl = pTerrain->getTerrainControlElementId(); if( !idCtrl.isNull() ) { OdGeMatrix3d matTransform = pTerrain->getTransformation(); OdGeMatrix3d matTransformBack = matTransform; matTransformBack.invert(); OdDgTerrainControlElementPtr pTerrainCtrl = idCtrl.openObject(OdDg::kForWrite); OdGePoint3dArray arrPts = pTerrainCtrl->getTerrainVertices(); OdGePoint3dArray arrTransformedPts; arrTransformedPts.resize(arrPts.size()); for (OdUInt32 i = 0; i < arrPts.size(); i++) { OdGePoint3d ptCur = arrPts[i]; ptCur.transformBy(matTransform); arrTransformedPts[i] = ptCur; if (pTransformer->transformPoint(ptCur) != eOk) return false; ptCur.transformBy(matTransformBack); arrTransformedPts[i] = ptCur; } pTerrainCtrl->setTerrainVertices(arrTransformedPts); } return true; } else return reprojectDgElementByGeoData(pTerrain, pTransformer, reprojectionSettings); } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgCellHeader2dByGeoData(OdDgCellHeader2d* pCell2d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { if( pCell2d->isA() != OdDgCellHeader2d::desc() ) return reprojectDgElementByGeoData(pCell2d, pTransformer, reprojectionSettings); bool bReprojectCellComponents = false; bool bCalculateRange = false; OdGeExtents2d extData; if( reprojectionSettings.m_uReprojectCellComponents == OdDgGeoDataReprojectionSettings::kAlways ) bReprojectCellComponents = true; else if( reprojectionSettings.m_uReprojectCellComponents == OdDgGeoDataReprojectionSettings::kIfSpatiallyLarge ) { bCalculateRange = true; if( pCell2d->getRangeExtents(extData) == eOk ) { double dArea = (extData.maxPoint().x - extData.minPoint().x)*(extData.maxPoint().y - extData.minPoint().y); if (dArea > reprojectionSettings.m_dSpatiallyLargeDistance) bReprojectCellComponents = true; } } OdGePoint2d ptOrigin = pCell2d->getOrigin(); OdGePoint2d ptOriginMod = ptOrigin; if (pTransformer->transformPoint(ptOriginMod) != eOk) return false; if( bReprojectCellComponents ) { pCell2d->setOrigin(ptOriginMod); OdDgElementIteratorPtr pIter = pCell2d->createIterator(); for (; !pIter->done(); pIter->step()) { OdDgElementPtr pElm = pIter->item().openObject(OdDg::kForWrite); reprojectDgnElementByGeoData(pElm, pTransformer, reprojectionSettings); } } else { OdGeMatrix3d matTransform = OdGeMatrix3d::translation(OdGePoint3d(ptOriginMod.x, ptOriginMod.y, 0.0) - OdGePoint3d(ptOrigin.x, ptOrigin.y, 0.0)); if( !reprojectionSettings.m_bRotateCells && !reprojectionSettings.m_bScaleCells ) pCell2d->transformBy(matTransform); else { if (!bCalculateRange) pCell2d->getRangeExtents(extData); if( extData.isValidExtents() ) { double dOldLength = extData.maxPoint().distanceTo(extData.minPoint()) / 2.0; OdGeVector2d vrDir = OdGeVector2d::kXAxis; vrDir.transformBy(pCell2d->getTransformation()); vrDir.normalize(); OdGePoint2d ptDir = ptOrigin + vrDir * dOldLength; OdGePoint2d ptDirMod = ptDir; if( pTransformer->transformPoint(ptDirMod) == eOk ) { double dOldAngle = OdGeVector2d::kXAxis.angleToCCW(vrDir); double dNewAngle = dOldAngle; double dNewScale = dOldLength; if (reprojectionSettings.m_bScaleCells) dNewScale = ptOriginMod.distanceTo(ptDirMod); if (reprojectionSettings.m_bRotateCells) dNewAngle = OdGeVector2d::kXAxis.angleToCCW(ptDirMod - ptOriginMod); matTransform = OdGeMatrix3d::translation(OdGeVector3d(-ptOrigin.x, -ptOrigin.y, 0.0)); matTransform = OdGeMatrix3d::rotation(-dOldAngle, OdGeVector3d::kZAxis) * matTransform; matTransform = OdGeMatrix3d::scaling(dNewScale / dOldLength) * matTransform; matTransform = OdGeMatrix3d::rotation(dNewAngle, OdGeVector3d::kZAxis) * matTransform; matTransform = OdGeMatrix3d::translation(OdGeVector3d(ptOriginMod.x, ptOriginMod.y, 0.0)) * matTransform; } } pCell2d->transformBy(matTransform); } } return true; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgCellHeader3dByGeoData(OdDgCellHeader3d* pCell3d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { bool bSpecialCell = pCell3d->isA() != OdDgCellHeader3d::desc(); OdDgBRepEntityPEPtr pBrepPE = pCell3d; if( !bSpecialCell && !pBrepPE.isNull() && pBrepPE->type(pCell3d) != OdDgBRepEntityPE::eNotBRepEntity) bSpecialCell = true; if(bSpecialCell) return reprojectDgElementByGeoData(pCell3d, pTransformer, reprojectionSettings); bool bReprojectCellComponents = false; bool bCalculateRange = false; OdGeExtents3d extData; if (reprojectionSettings.m_uReprojectCellComponents == OdDgGeoDataReprojectionSettings::kAlways) bReprojectCellComponents = true; else if (reprojectionSettings.m_uReprojectCellComponents == OdDgGeoDataReprojectionSettings::kIfSpatiallyLarge) { bCalculateRange = true; if (pCell3d->getRangeExtents(extData) == eOk) { double dArea = (extData.maxPoint().x - extData.minPoint().x)*(extData.maxPoint().y - extData.minPoint().y); if (dArea > reprojectionSettings.m_dSpatiallyLargeDistance) bReprojectCellComponents = true; } } OdGePoint3d ptOrigin = pCell3d->getOrigin(); OdGePoint3d ptOriginMod = ptOrigin; if (pTransformer->transformPoint(ptOriginMod) != eOk) return false; if (bReprojectCellComponents) { pCell3d->setOrigin(ptOriginMod); OdDgElementIteratorPtr pIter = pCell3d->createIterator(); for (; !pIter->done(); pIter->step()) { OdDgElementPtr pElm = pIter->item().openObject(OdDg::kForWrite); reprojectDgnElementByGeoData(pElm, pTransformer, reprojectionSettings); } } else { OdGeMatrix3d matTransform = OdGeMatrix3d::translation(ptOriginMod - ptOrigin); if (!reprojectionSettings.m_bRotateCells && !reprojectionSettings.m_bScaleCells) pCell3d->transformBy(matTransform); else { if (!bCalculateRange) pCell3d->getRangeExtents(extData); if (extData.isValidExtents()) { OdGePoint3d ptRef(extData.maxPoint().distanceTo(extData.minPoint()) / 2.0, 0.0, 0.0); ptRef.transformBy(pCell3d->getTransformation()); OdGePoint3d ptDir = ptOrigin + ptRef.asVector(); OdGePoint3d ptDirMod = ptDir; if (pTransformer->transformPoint(ptDirMod) == eOk) { OdGeVector3d vrStart = ptDir - ptOrigin; OdGeVector3d vrStartMod = ptDirMod - ptOriginMod; OdGeVector3d vrNormal = OdGeVector3d::kZAxis; OdGeMatrix3d matRotate = pCell3d->getTransformation(); vrNormal = vrNormal.transformBy(matRotate); double dLength = vrStart.length(); double dLengthMod = vrStartMod.length(); OdGeVector3d vrCellY = vrNormal.crossProduct(vrStart); OdGeVector3d vrCellYMod = vrNormal.crossProduct(vrStartMod); vrStartMod = vrCellYMod.crossProduct(vrNormal); double dStartAngle = 0.0; double dStartAngleMod = 0.0; if (!OdZero(dLength) && !OdZero(dLengthMod)) { vrStart.normalize(); vrCellY.normalize(); vrStartMod.normalize(); vrCellYMod.normalize(); dStartAngle = OdGeVector3d::kXAxis.angleTo(vrStart, vrNormal); dStartAngleMod = OdGeVector3d::kXAxis.angleTo(vrStartMod, vrNormal); } if (!reprojectionSettings.m_bRotateTexts) dStartAngleMod = dStartAngle; if (!reprojectionSettings.m_bScaleTexts) dLengthMod = dLength; OdGeMatrix3d matTransformOriginal; OdGeMatrix3d matTransformMod; matTransformOriginal.setCoordSystem(ptOrigin, vrStart, vrCellY, vrNormal); if (reprojectionSettings.m_bRotateTexts) matTransformMod.setCoordSystem(ptOriginMod, vrStartMod, vrCellYMod, vrNormal); else matTransformMod.setCoordSystem(ptOriginMod, vrStart, vrCellY, vrNormal); OdGeMatrix3d matTransformBack = matTransformOriginal; matTransformBack.invert(); matTransform = matTransformMod * OdGeMatrix3d::scaling(dLengthMod / dLength) * matTransformBack; } } pCell3d->transformBy(matTransform); } } return true; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgSharedCellByGeoData(OdDgSharedCellReference* pSharedCell, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { if (!reprojectionSettings.m_bRotateCells) { OdGePoint3d ptOrigin = pSharedCell->getOrigin(); OdGePoint3d ptOriginMod = ptOrigin; if (pTransformer->transformPoint(ptOriginMod) != eOk) return false; OdGeMatrix3d matTransform = OdGeMatrix3d::translation(ptOriginMod - ptOrigin); pSharedCell->transformBy(matTransform); } else return reprojectDgElementByGeoData(pSharedCell, pTransformer, reprojectionSettings); return true; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgModelByGeoData(OdDgModel* pModel, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { OdDgElementIteratorPtr pIter = pModel->createGraphicsElementsIterator(); for (; !pIter->done(); pIter->step()) { OdDgElementPtr pElm = pIter->item().openObject(OdDg::kForWrite); reprojectDgnElementByGeoData(pElm, pTransformer, reprojectionSettings); } pIter = pModel->createControlElementsIterator(); for (; !pIter->done(); pIter->step()) { OdDgElementPtr pElm = pIter->item().openObject(OdDg::kForWrite); if (!pElm->isKindOf(OdDgReferenceAttachmentHeader::desc())) continue; reprojectDgnElementByGeoData(pElm, pTransformer, reprojectionSettings); } return true; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgMeshByGeoData(OdDgMesh* pMesh, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { if (reprojectionSettings.m_bReprojectMeshPoints) { if( pMesh->isKindOf(OdDgMeshFaceLoops::desc()) ) { OdDgMeshFaceLoops* pMeshFaceLoops = (OdDgMeshFaceLoops*)(pMesh); OdGePoint3dArray arrPts; arrPts.resize(pMeshFaceLoops->getPointsNumber()); OdUInt32 j; for( j = 0; j < pMeshFaceLoops->getPointsNumber(); j++) arrPts[j] = pMeshFaceLoops->getPoint(j); OdGePoint3dArray arrTransformedPts; arrTransformedPts.resize(arrPts.size()); for( j = 0; j < arrPts.size(); j++) { OdGePoint3d ptCur = arrPts[j]; arrTransformedPts[j] = ptCur; if (pTransformer->transformPoint(ptCur) != eOk) return false; arrTransformedPts[j] = ptCur; } for (j = 0; j < pMeshFaceLoops->getPointsNumber(); j++) pMeshFaceLoops->setPoint(j, arrTransformedPts[j]); } else if( pMesh->isKindOf(OdDgMeshPointCloud::desc()) ) { OdDgMeshPointCloud* pMeshFaceLoops = (OdDgMeshPointCloud*)(pMesh); OdGePoint3dArray arrPts; arrPts.resize(pMeshFaceLoops->getPointsNumber()); OdUInt32 j; for (j = 0; j < pMeshFaceLoops->getPointsNumber(); j++) arrPts[j] = pMeshFaceLoops->getPoint(j); OdGePoint3dArray arrTransformedPts; arrTransformedPts.resize(arrPts.size()); for (j = 0; j < arrPts.size(); j++) { OdGePoint3d ptCur = arrPts[j]; arrTransformedPts[j] = ptCur; if (pTransformer->transformPoint(ptCur) != eOk) return false; arrTransformedPts[j] = ptCur; } for (j = 0; j < pMeshFaceLoops->getPointsNumber(); j++) pMeshFaceLoops->setPoint(j, arrTransformedPts[j]); } else if (pMesh->isKindOf(OdDgMeshTriangleList::desc())) { OdDgMeshTriangleList* pMeshFaceLoops = (OdDgMeshTriangleList*)(pMesh); OdArray arrTriangles; arrTriangles.resize(pMeshFaceLoops->getTrianglesNumber()); OdUInt32 j; for (j = 0; j < pMeshFaceLoops->getTrianglesNumber(); j++) pMeshFaceLoops->getTriangle(j, arrTriangles[j]); OdArray arrTrianglesMod; arrTrianglesMod.resize(arrTriangles.size()); for (j = 0; j < arrTriangles.size(); j++) { OdGePoint3d ptCur1 = arrTriangles[j].m_points[0]; OdGePoint3d ptCur2 = arrTriangles[j].m_points[1]; OdGePoint3d ptCur3 = arrTriangles[j].m_points[2]; if (pTransformer->transformPoint(ptCur1) != eOk) return false; if (pTransformer->transformPoint(ptCur2) != eOk) return false; if (pTransformer->transformPoint(ptCur3) != eOk) return false; arrTrianglesMod[j].m_points[0] = ptCur1; arrTrianglesMod[j].m_points[1] = ptCur2; arrTrianglesMod[j].m_points[2] = ptCur3; } for (j = 0; j < pMeshFaceLoops->getTrianglesNumber(); j++) pMeshFaceLoops->setTriangle(j, arrTrianglesMod[j]); } else if (pMesh->isKindOf(OdDgMeshQuadList::desc())) { OdDgMeshQuadList* pMeshFaceLoops = (OdDgMeshQuadList*)(pMesh); OdArray arrTriangles; arrTriangles.resize(pMeshFaceLoops->getQuadsNumber()); OdUInt32 j; for (j = 0; j < pMeshFaceLoops->getQuadsNumber(); j++) pMeshFaceLoops->getQuad(j, arrTriangles[j]); OdArray arrTrianglesMod; arrTrianglesMod.resize(arrTriangles.size()); for (j = 0; j < arrTriangles.size(); j++) { OdGePoint3d ptCur1 = arrTriangles[j].m_points[0]; OdGePoint3d ptCur2 = arrTriangles[j].m_points[1]; OdGePoint3d ptCur3 = arrTriangles[j].m_points[2]; OdGePoint3d ptCur4 = arrTriangles[j].m_points[3]; if (pTransformer->transformPoint(ptCur1) != eOk) return false; if (pTransformer->transformPoint(ptCur2) != eOk) return false; if (pTransformer->transformPoint(ptCur3) != eOk) return false; if (pTransformer->transformPoint(ptCur4) != eOk) return false; arrTrianglesMod[j].m_points[0] = ptCur1; arrTrianglesMod[j].m_points[1] = ptCur2; arrTrianglesMod[j].m_points[2] = ptCur3; arrTrianglesMod[j].m_points[3] = ptCur4; } for (j = 0; j < pMeshFaceLoops->getQuadsNumber(); j++) pMeshFaceLoops->setQuad(j, arrTrianglesMod[j]); } else if (pMesh->isKindOf(OdDgMeshTriangleGrid::desc())) { OdDgMeshTriangleGrid* pMeshFaceLoops = (OdDgMeshTriangleGrid*)(pMesh); OdGePoint3dArray arrPts; for( OdUInt32 n = 0; n < pMeshFaceLoops->getColumnsNumber(); n++ ) for (OdUInt32 m = 0; m < pMeshFaceLoops->getRowsNumber(); m++) arrPts.push_back(pMeshFaceLoops->getPoint(m,n)); OdUInt32 j; OdGePoint3dArray arrTransformedPts; arrTransformedPts.resize(arrPts.size()); for (j = 0; j < arrPts.size(); j++) { OdGePoint3d ptCur = arrPts[j]; arrTransformedPts[j] = ptCur; if (pTransformer->transformPoint(ptCur) != eOk) return false; arrTransformedPts[j] = ptCur; } OdUInt32 uIndex = 0; for (OdUInt32 n = 0; n < pMeshFaceLoops->getColumnsNumber(); n++) for (OdUInt32 m = 0; m < pMeshFaceLoops->getRowsNumber(); m++) { pMeshFaceLoops->setPoint(m, n, arrTransformedPts[uIndex]); uIndex++; } } else if (pMesh->isKindOf(OdDgMeshQuadGrid::desc())) { OdDgMeshQuadGrid* pMeshFaceLoops = (OdDgMeshQuadGrid*)(pMesh); OdGePoint3dArray arrPts; for (OdUInt32 n = 0; n < pMeshFaceLoops->getColumnsNumber(); n++) for (OdUInt32 m = 0; m < pMeshFaceLoops->getRowsNumber(); m++) arrPts.push_back(pMeshFaceLoops->getPoint(m, n)); OdUInt32 j; OdGePoint3dArray arrTransformedPts; arrTransformedPts.resize(arrPts.size()); for (j = 0; j < arrPts.size(); j++) { OdGePoint3d ptCur = arrPts[j]; arrTransformedPts[j] = ptCur; if (pTransformer->transformPoint(ptCur) != eOk) return false; arrTransformedPts[j] = ptCur; } OdUInt32 uIndex = 0; for (OdUInt32 n = 0; n < pMeshFaceLoops->getColumnsNumber(); n++) for (OdUInt32 m = 0; m < pMeshFaceLoops->getRowsNumber(); m++) { pMeshFaceLoops->setPoint(m, n, arrTransformedPts[uIndex]); uIndex++; } } return true; } else return reprojectDgElementByGeoData(pMesh, pTransformer, reprojectionSettings); } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgBSplineSurfaceByGeoData(OdDgBSplineSurface* pSurface, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { if (reprojectionSettings.m_bReprojectBSplineSurfacePoints ) { OdUInt32 iCountU, iCountV; OdGePoint3dArray arrPts; pSurface->getControlPoints(iCountU, iCountV, arrPts); OdUInt32 j; OdGePoint3dArray arrTransformedPts; arrTransformedPts.resize(arrPts.size()); for (j = 0; j < arrPts.size(); j++) { OdGePoint3d ptCur = arrPts[j]; arrTransformedPts[j] = ptCur; if (pTransformer->transformPoint(ptCur) != eOk) return false; arrTransformedPts[j] = ptCur; } pSurface->setControlPoints(iCountU, iCountV, arrTransformedPts); return true; } else return reprojectDgElementByGeoData(pSurface, pTransformer, reprojectionSettings); } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgElementByGeoData(OdDgElement* pElm, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { OdGeExtents3d extData; pElm->getGeomExtents(extData); if( extData.isValidExtents() ) { OdGePoint3d ptCenter = extData.center(); OdGePoint3d ptLeft = ptCenter + OdGeVector3d::kXAxis * extData.diagonal().length() / 2.0; OdGePoint3d ptCenterMod = ptCenter; OdGePoint3d ptLeftMod = ptLeft; if (pTransformer->transformPoint(ptCenterMod) != eOk) return false; if (pTransformer->transformPoint(ptLeftMod) != eOk) return false; ptLeftMod.z = 0; double dAngle = OdGeVector3d::kXAxis.angleTo((ptLeftMod - ptCenterMod), OdGeVector3d::kZAxis); double dScale = (ptLeftMod - ptCenterMod).length() / (ptLeft - ptCenter).length(); OdGeMatrix3d matTransform = OdGeMatrix3d::translation(-ptCenter.asVector()); matTransform = OdGeMatrix3d::scaling(dScale) * matTransform; matTransform = OdGeMatrix3d::rotation(dAngle, OdGeVector3d::kZAxis) * matTransform; matTransform = OdGeMatrix3d::translation(ptCenterMod.asVector()) * matTransform; pElm->transformBy(matTransform); } return true; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgText2dByGeoData(OdDgText2d* pText2d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { OdGePoint2dArray arrTextPts; pText2d->getBoundingPoints(arrTextPts); OdGePoint2d ptPosition = pText2d->getPosition(); OdGePoint2d ptOrigin = arrTextPts[0]; OdGePoint2d ptLength = arrTextPts[3]; OdGePoint2d ptPositionMod = ptPosition; OdGePoint2d ptOriginMod = ptOrigin; OdGePoint2d ptLengthMod = ptLength; if (pTransformer->transformPoint(ptPositionMod) != eOk) return false; if (pTransformer->transformPoint(ptOriginMod) != eOk) return false; if( pTransformer->transformPoint(ptLengthMod) != eOk) return false; OdGeVector2d vrStart = ptLength - ptOrigin; OdGeVector2d vrStartMod = ptLengthMod - ptOriginMod; double dLength = vrStart.length(); double dLengthMod = vrStartMod.length(); double dStartAngle = 0.0; double dStartAngleMod = 0.0; if( !OdZero(dLength) && !OdZero(dLengthMod) ) { vrStart.normalize(); vrStartMod.normalize(); dStartAngle = OdGeVector2d::kXAxis.angleToCCW(vrStart); dStartAngleMod = OdGeVector2d::kXAxis.angleToCCW(vrStartMod); } if( !reprojectionSettings.m_bRotateTexts ) dStartAngleMod = dStartAngle; if( !reprojectionSettings.m_bScaleTexts ) dLengthMod = dLength; OdGeMatrix3d matTransform = OdGeMatrix3d::translation( OdGeVector3d(-ptPosition.x, -ptPosition.y, 0.0)); if( !OdEqual(dStartAngle, dStartAngleMod) ) matTransform = OdGeMatrix3d::rotation(-dStartAngle, OdGeVector3d::kZAxis) * matTransform; if( !OdEqual(dLength, dLengthMod) ) matTransform = OdGeMatrix3d::scaling(dLengthMod / dLength) * matTransform; if (!OdEqual(dStartAngle, dStartAngleMod)) matTransform = OdGeMatrix3d::rotation(dStartAngleMod, OdGeVector3d::kZAxis) * matTransform; matTransform = OdGeMatrix3d::translation(OdGeVector3d(ptPositionMod.x, ptPositionMod.y, 0.0))*matTransform; pText2d->transformBy(matTransform); return true; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgText3dByGeoData(OdDgText3d* pText3d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { OdGePoint3dArray arrTextPts; pText3d->getBoundingPoints(arrTextPts); OdGePoint3d ptPosition = pText3d->getPosition(); OdGePoint3d ptOrigin = arrTextPts[0]; OdGePoint3d ptLength = arrTextPts[3]; OdGePoint3d ptPositionMod = ptPosition; OdGePoint3d ptOriginMod = ptOrigin; OdGePoint3d ptLengthMod = ptLength; if (pTransformer->transformPoint(ptPositionMod) != eOk) return false; if (pTransformer->transformPoint(ptOriginMod) != eOk) return false; if (pTransformer->transformPoint(ptLengthMod) != eOk) return false; OdGeVector3d vrStart = ptLength - ptOrigin; OdGeVector3d vrStartMod = ptLengthMod - ptOriginMod; OdGeVector3d vrNormal = OdGeVector3d::kZAxis; OdGeMatrix3d matRotate = pText3d->getRotation().getMatrix(); matRotate.transposeIt(); vrNormal = vrNormal.transformBy(matRotate); double dLength = vrStart.length(); double dLengthMod = vrStartMod.length(); OdGeVector3d vrTextY = vrNormal.crossProduct(vrStart); OdGeVector3d vrTextYMod = vrNormal.crossProduct(vrStartMod); vrStartMod = vrTextYMod.crossProduct(vrNormal); double dStartAngle = 0.0; double dStartAngleMod = 0.0; if (!OdZero(dLength) && !OdZero(dLengthMod)) { vrStart.normalize(); vrTextY.normalize(); vrStartMod.normalize(); vrTextYMod.normalize(); dStartAngle = OdGeVector3d::kXAxis.angleTo(vrStart, vrNormal); dStartAngleMod = OdGeVector3d::kXAxis.angleTo(vrStartMod, vrNormal); } if (!reprojectionSettings.m_bRotateTexts) dStartAngleMod = dStartAngle; if (!reprojectionSettings.m_bScaleTexts) dLengthMod = dLength; OdGeMatrix3d matTransformOriginal; OdGeMatrix3d matTransformMod; matTransformOriginal.setCoordSystem(ptPosition, vrStart, vrTextY, vrNormal); if( reprojectionSettings.m_bRotateTexts ) matTransformMod.setCoordSystem(ptPositionMod, vrStartMod, vrTextYMod, vrNormal); else matTransformMod.setCoordSystem(ptPositionMod, vrStart, vrTextY, vrNormal); OdGeMatrix3d matTransformBack = matTransformOriginal; matTransformBack.invert(); OdGeMatrix3d matTransform = matTransformMod * OdGeMatrix3d::scaling(dLengthMod/dLength) * matTransformBack; pText3d->transformBy(matTransform); return true; } OdString getTagString(OdDgTagElement* pTag) { OdString strRet; switch (pTag->getDataType()) { case OdDgTagDefinition::kChar: { strRet = pTag->getString(); } break; case OdDgTagDefinition::kInt16: { strRet.format(L"%d", pTag->getInt16()); } break; case OdDgTagDefinition::kInt32: { strRet.format(L"%d", pTag->getInt32()); } break; case OdDgTagDefinition::kDouble: { strRet.format(L"%f", pTag->getDouble()); if (strRet.find(L'.') != -1 || strRet.find(L',') != -1) { while (strRet.getLength() && (strRet[strRet.getLength() - 1] == L'0' || strRet[strRet.getLength() - 1] == L'.' || strRet[strRet.getLength() - 1] == L',' ) ) { bool bBreak = (strRet[strRet.getLength() - 1] == L'.') || (strRet[strRet.getLength() - 1] == L','); strRet = strRet.left(strRet.getLength() - 1); if (bBreak) break; } } } break; } return strRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgTagElementByGeoData(OdDgTagElement* pTagElement, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { OdGePoint3d ptOrigin = pTagElement->getOrigin(); OdGeVector3d vrStart = OdGeVector3d::kXAxis; OdGeVector3d vrNormal = OdGeVector3d::kZAxis; if( pTagElement->get3dFormatFlag() ) { OdGeMatrix3d matRotate = pTagElement->getRotation3d().getMatrix(); matRotate.transposeIt(); vrStart.transformBy(matRotate); vrNormal.transformBy(matRotate); } else { double dAngle = pTagElement->getRotation2d(); vrStart.transformBy(OdGeMatrix3d::rotation(dAngle, vrNormal)); } OdString strText = getTagString(pTagElement); if( !strText.isEmpty() && !OdZero(pTagElement->getLengthMultiplier())) vrStart *= pTagElement->getLengthMultiplier() * strText.getLength(); OdGePoint3d ptLength = ptOrigin + vrStart; OdGePoint3d ptOriginMod = ptOrigin; OdGePoint3d ptLengthMod = ptLength; if (pTransformer->transformPoint(ptOriginMod) != eOk) return false; if (pTransformer->transformPoint(ptLengthMod) != eOk) return false; OdGeVector3d vrStartMod = ptLengthMod - ptOriginMod; double dLength = vrStart.length(); double dLengthMod = vrStartMod.length(); OdGeVector3d vrTextY = vrNormal.crossProduct(vrStart); OdGeVector3d vrTextYMod = vrNormal.crossProduct(vrStartMod); vrStartMod = vrTextYMod.crossProduct(vrNormal); double dStartAngle = 0.0; double dStartAngleMod = 0.0; if (!OdZero(dLength) && !OdZero(dLengthMod)) { vrStart.normalize(); vrTextY.normalize(); vrStartMod.normalize(); vrTextYMod.normalize(); dStartAngle = OdGeVector3d::kXAxis.angleTo(vrStart, vrNormal); dStartAngleMod = OdGeVector3d::kXAxis.angleTo(vrStartMod, vrNormal); } if (!reprojectionSettings.m_bRotateTexts) dStartAngleMod = dStartAngle; if (!reprojectionSettings.m_bScaleTexts) dLengthMod = dLength; OdGeMatrix3d matTransformOriginal; OdGeMatrix3d matTransformMod; matTransformOriginal.setCoordSystem(ptOrigin, vrStart, vrTextY, vrNormal); if (reprojectionSettings.m_bRotateTexts) matTransformMod.setCoordSystem(ptOriginMod, vrStartMod, vrTextYMod, vrNormal); else matTransformMod.setCoordSystem(ptOriginMod, vrStart, vrTextY, vrNormal); OdGeMatrix3d matTransformBack = matTransformOriginal; matTransformBack.invert(); OdGeMatrix3d matTransform = matTransformMod * OdGeMatrix3d::scaling(dLengthMod / dLength) * matTransformBack; pTagElement->transformBy(matTransform); return true; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgTextNode2dByGeoData(OdDgTextNode2d* pTextNode2d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { OdGePoint2dArray arrTextPts; pTextNode2d->getBoundingPoints(arrTextPts); bool bReprojectTexts = false; if( reprojectionSettings.m_uReprojectMTextComponents == OdDgGeoDataReprojectionSettings::kAlways ) bReprojectTexts = true; else if (reprojectionSettings.m_uReprojectMTextComponents == OdDgGeoDataReprojectionSettings::kIfSpatiallyLarge) { double dArea = arrTextPts[0].distanceTo(arrTextPts[1]) * arrTextPts[0].distanceTo(arrTextPts[3]); if (dArea > reprojectionSettings.m_dSpatiallyLargeDistance) bReprojectTexts = true; } OdGePoint2d ptPosition = (arrTextPts[0] + arrTextPts[2].asVector()) / 2.0; OdGePoint2d ptOrigin = arrTextPts[0]; OdGePoint2d ptLength = arrTextPts[3]; OdGePoint2d ptPositionMod = ptPosition; OdGePoint2d ptOriginMod = ptOrigin; OdGePoint2d ptLengthMod = ptLength; if (pTransformer->transformPoint(ptPositionMod) != eOk) return false; if (pTransformer->transformPoint(ptOriginMod) != eOk) return false; if (pTransformer->transformPoint(ptLengthMod) != eOk) return false; OdGeVector2d vrStart = ptLength - ptOrigin; OdGeVector2d vrStartMod = ptLengthMod - ptOriginMod; double dLength = vrStart.length(); double dLengthMod = vrStartMod.length(); double dStartAngle = 0.0; double dStartAngleMod = 0.0; if (!OdZero(dLength) && !OdZero(dLengthMod)) { vrStart.normalize(); vrStartMod.normalize(); dStartAngle = OdGeVector2d::kXAxis.angleToCCW(vrStart); dStartAngleMod = OdGeVector2d::kXAxis.angleToCCW(vrStartMod); } if (!reprojectionSettings.m_bRotateTexts) dStartAngleMod = dStartAngle; if (!reprojectionSettings.m_bScaleTexts) dLengthMod = dLength; OdGeMatrix3d matTransform = OdGeMatrix3d::translation(OdGeVector3d(-ptPosition.x, -ptPosition.y, 0.0)); if (!OdEqual(dStartAngle, dStartAngleMod)) matTransform = OdGeMatrix3d::rotation(-dStartAngle, OdGeVector3d::kZAxis) * matTransform; if (!OdEqual(dLength, dLengthMod)) matTransform = OdGeMatrix3d::scaling(dLengthMod / dLength) * matTransform; if (!OdEqual(dStartAngle, dStartAngleMod)) matTransform = OdGeMatrix3d::rotation(dStartAngleMod, OdGeVector3d::kZAxis) * matTransform; matTransform = OdGeMatrix3d::translation(OdGeVector3d(ptPositionMod.x, ptPositionMod.y, 0.0)) * matTransform; if( bReprojectTexts ) { pTextNode2d->transformTextNodeSettings(matTransform); OdDgElementIteratorPtr pIter = pTextNode2d->createIterator(); for(; !pIter->done(); pIter->step()) { OdDgElementPtr pElm = pIter->item().openObject(OdDg::kForWrite); reprojectDgnElementByGeoData(pElm, pTransformer, reprojectionSettings); } } else { pTextNode2d->transformBy(matTransform); } return true; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgTextNode3dByGeoData(OdDgTextNode3d* pTextNode3d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { OdGePoint3dArray arrTextPts; pTextNode3d->getBoundingPoints(arrTextPts); bool bReprojectTexts = false; if (reprojectionSettings.m_uReprojectMTextComponents == OdDgGeoDataReprojectionSettings::kAlways) bReprojectTexts = true; else if (reprojectionSettings.m_uReprojectMTextComponents == OdDgGeoDataReprojectionSettings::kIfSpatiallyLarge) { double dArea = arrTextPts[0].distanceTo(arrTextPts[1]) * arrTextPts[0].distanceTo(arrTextPts[3]); if (dArea > reprojectionSettings.m_dSpatiallyLargeDistance) bReprojectTexts = true; } OdGePoint3d ptPosition = (arrTextPts[0] + arrTextPts[2].asVector()) / 2.0; OdGePoint3d ptOrigin = arrTextPts[0]; OdGePoint3d ptLength = arrTextPts[3]; OdGePoint3d ptPositionMod = ptPosition; OdGePoint3d ptOriginMod = ptOrigin; OdGePoint3d ptLengthMod = ptLength; if (pTransformer->transformPoint(ptPositionMod) != eOk) return false; if (pTransformer->transformPoint(ptOriginMod) != eOk) return false; if (pTransformer->transformPoint(ptLengthMod) != eOk) return false; OdGeVector3d vrStart = ptLength - ptOrigin; OdGeVector3d vrStartMod = ptLengthMod - ptOriginMod; OdGeVector3d vrNormal = OdGeVector3d::kZAxis; OdGeMatrix3d matRotate = pTextNode3d->getRotation().getMatrix(); matRotate.transposeIt(); vrNormal = vrNormal.transformBy(matRotate); double dLength = vrStart.length(); double dLengthMod = vrStartMod.length(); OdGeVector3d vrTextY = vrNormal.crossProduct(vrStart); OdGeVector3d vrTextYMod = vrNormal.crossProduct(vrStartMod); vrStartMod = vrTextYMod.crossProduct(vrNormal); double dStartAngle = 0.0; double dStartAngleMod = 0.0; if (!OdZero(dLength) && !OdZero(dLengthMod)) { vrStart.normalize(); vrTextY.normalize(); vrStartMod.normalize(); vrTextYMod.normalize(); dStartAngle = OdGeVector3d::kXAxis.angleTo(vrStart, vrNormal); dStartAngleMod = OdGeVector3d::kXAxis.angleTo(vrStartMod, vrNormal); } if (!reprojectionSettings.m_bRotateTexts) dStartAngleMod = dStartAngle; if (!reprojectionSettings.m_bScaleTexts) dLengthMod = dLength; OdGeMatrix3d matTransformOriginal; OdGeMatrix3d matTransformMod; matTransformOriginal.setCoordSystem(ptPosition, vrStart, vrTextY, vrNormal); if (reprojectionSettings.m_bRotateTexts) matTransformMod.setCoordSystem(ptPositionMod, vrStartMod, vrTextYMod, vrNormal); else matTransformMod.setCoordSystem(ptPositionMod, vrStart, vrTextY, vrNormal); OdGeMatrix3d matTransformBack = matTransformOriginal; matTransformBack.invert(); OdGeMatrix3d matTransform = matTransformMod * OdGeMatrix3d::scaling(dLengthMod / dLength) * matTransformBack; if (bReprojectTexts) { pTextNode3d->transformTextNodeSettings(matTransform); OdDgElementIteratorPtr pIter = pTextNode3d->createIterator(); for (; !pIter->done(); pIter->step()) { OdDgElementPtr pElm = pIter->item().openObject(OdDg::kForWrite); reprojectDgnElementByGeoData(pElm, pTransformer, reprojectionSettings); } } else { pTextNode3d->transformBy(matTransform); } return true; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgMultiLineByGeoData(OdDgMultiline* pMLine, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { OdGePoint3dArray arrLinePts; arrLinePts.resize(pMLine->getPointsCount()); for( OdUInt32 i = 0; i < pMLine->getPointsCount(); i++ ) { OdDgMultilinePoint ptMLine; pMLine->getPoint(i, ptMLine); OdGePoint3d ptLineMod; ptMLine.getPoint(ptLineMod); arrLinePts[i] = ptLineMod; } OdGePoint3dArray arrTransformedPts; bool bRet = transformPolylineByGeoData(arrLinePts, pTransformer, reprojectionSettings, arrTransformedPts, false, false); if (bRet) { for (OdUInt32 j = 0; j < pMLine->getPointsCount(); j++) { OdDgMultilinePoint ptMLine; pMLine->getPoint(j, ptMLine); ptMLine.setPoint(arrTransformedPts[j]); pMLine->setPoint(j, ptMLine); } } return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgLine2dByGeoData(OdDgLine2d* pLine2d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { OdGePoint2d ptStart = pLine2d->getStartPoint(); OdGePoint2d ptEnd = pLine2d->getEndPoint(); OdGePoint2dArray arrLinePts; arrLinePts.push_back(ptStart); arrLinePts.push_back(ptEnd); OdGePoint2dArray arrTransformedPts; bool bRet = transformPolylineByGeoData(arrLinePts, pTransformer, reprojectionSettings, arrTransformedPts, true, false); if (bRet) { if (arrTransformedPts.size() == 2) { pLine2d->setStartPoint(arrTransformedPts[0]); pLine2d->setEndPoint(arrTransformedPts[1]); } else { OdDgLineString2dPtr pLineString = OdDgLineString2d::createObject(); setCurveElementPropertiesFrom(pLineString, pLine2d, false); for (OdUInt32 i = 0; i < arrTransformedPts.size(); i++) pLineString->addVertex(arrTransformedPts[i]); pLine2d->handOverTo(pLineString); } } return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgLine3dByGeoData(OdDgLine3d* pLine3d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { OdGePoint3d ptStart = pLine3d->getStartPoint(); OdGePoint3d ptEnd = pLine3d->getEndPoint(); OdGePoint3dArray arrLinePts; arrLinePts.push_back(ptStart); arrLinePts.push_back(ptEnd); OdGePoint3dArray arrTransformedPts; bool bRet = transformPolylineByGeoData(arrLinePts, pTransformer, reprojectionSettings, arrTransformedPts, true, false); if (bRet) { if (arrTransformedPts.size() == 2) { pLine3d->setStartPoint(arrTransformedPts[0]); pLine3d->setEndPoint(arrTransformedPts[1]); } else { OdDgLineString3dPtr pLineString = OdDgLineString3d::createObject(); setCurveElementPropertiesFrom(pLineString, pLine3d, false); for (OdUInt32 i = 0; i < arrTransformedPts.size(); i++) pLineString->addVertex(arrTransformedPts[i]); pLine3d->handOverTo(pLineString); } } return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgMultiVertex2dByGeoData(OdDgMultiVertex2d* pMultiVertex2d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings, bool bAddPoints, bool bCheckBreaks) { OdGePoint2dArray arrLinePts; arrLinePts.resize(pMultiVertex2d->getVerticesCount()); for (OdUInt32 i = 0; i < pMultiVertex2d->getVerticesCount(); i++) arrLinePts[i] = pMultiVertex2d->getVertexAt(i); OdGePoint2dArray arrTransformedPts; bool bRet = transformPolylineByGeoData(arrLinePts, pTransformer, reprojectionSettings, arrTransformedPts, bAddPoints, bCheckBreaks); if (bRet) { pMultiVertex2d->removeAllVertices(); for (OdUInt32 j = 0; j < arrTransformedPts.size(); j++) pMultiVertex2d->addVertex(arrTransformedPts[j]); } return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgMultiVertex3dByGeoData(OdDgMultiVertex3d* pMultiVertex3d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings, bool bAddPoints, bool bCheckBreaks) { OdGePoint3dArray arrLinePts; arrLinePts.resize(pMultiVertex3d->getVerticesCount()); for (OdUInt32 i = 0; i < pMultiVertex3d->getVerticesCount(); i++) arrLinePts[i] = pMultiVertex3d->getVertexAt(i); OdGePoint3dArray arrTransformedPts; bool bRet = transformPolylineByGeoData(arrLinePts, pTransformer, reprojectionSettings, arrTransformedPts, bAddPoints, bCheckBreaks); if (bRet) { pMultiVertex3d->removeAllVertices(); for (OdUInt32 j = 0; j < arrTransformedPts.size(); j++) pMultiVertex3d->addVertex(arrTransformedPts[j]); } return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgArc2dByGeoData(OdDgArc2d* pArc2d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { bool bRet = true; bool bConvertArcToPolyline = false; if( reprojectionSettings.m_uStrokeArcsToLineStrings == OdDgGeoDataReprojectionSettings::kAlways ) bConvertArcToPolyline = true; else if( reprojectionSettings.m_uStrokeArcsToLineStrings == OdDgGeoDataReprojectionSettings::kIfSpatiallyLarge ) { OdGeEllipArc2d ellipArc = pArc2d->getEllipArc(); if(ellipArc.length() > reprojectionSettings.m_dSpatiallyLargeDistance ) bConvertArcToPolyline = true; } OdGeEllipArc2d ellipArc = pArc2d->getEllipArc(); if( !bConvertArcToPolyline ) { OdGeEllipArc2d ellipArcMod; if (reprojectGeArc2d(ellipArc, pTransformer, ellipArcMod)) bConvertArcToPolyline = pArc2d->setFromOdGeCurve(ellipArcMod) != eOk; else bConvertArcToPolyline = true; if (!bConvertArcToPolyline) bRet = true; } if( bConvertArcToPolyline ) { OdGePoint2dArray arrArcPts; OdGePoint2dArray arrTransformedPts; OdGeInterval arcInverval; ellipArc.getInterval(arcInverval); ellipArc.getSamplePoints(arcInverval.lowerBound(), arcInverval.upperBound(), reprojectionSettings.m_dStrokeTolerance, arrArcPts); bRet = transformPolylineByGeoData(arrArcPts, pTransformer, reprojectionSettings, arrTransformedPts, false, false); if( bRet ) { OdDgLineString2dPtr pLineString = OdDgLineString2d::createObject(); setCurveElementPropertiesFrom(pLineString, pArc2d, false); for (OdUInt32 i = 0; i < arrTransformedPts.size(); i++) pLineString->addVertex(arrTransformedPts[i]); pArc2d->handOverTo(pLineString); } } return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgArc3dByGeoData(OdDgArc3d* pArc3d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { bool bRet = true; bool bConvertArcToPolyline = false; if (reprojectionSettings.m_uStrokeArcsToLineStrings == OdDgGeoDataReprojectionSettings::kAlways) bConvertArcToPolyline = true; else if (reprojectionSettings.m_uStrokeArcsToLineStrings == OdDgGeoDataReprojectionSettings::kIfSpatiallyLarge) { OdGeEllipArc3d ellipArc = pArc3d->getEllipArc(); if (ellipArc.length() > reprojectionSettings.m_dSpatiallyLargeDistance) bConvertArcToPolyline = true; } OdGeEllipArc3d ellipArc = pArc3d->getEllipArc(); if (bConvertArcToPolyline) { OdGePoint3dArray arrArcPts; OdGePoint3dArray arrTransformedPts; OdGeInterval arcInverval; ellipArc.getInterval(arcInverval); ellipArc.getSamplePoints(arcInverval.lowerBound(), arcInverval.upperBound(), reprojectionSettings.m_dStrokeTolerance, arrArcPts); bRet = transformPolylineByGeoData(arrArcPts, pTransformer, reprojectionSettings, arrTransformedPts, false, false); if (bRet) { OdDgLineString3dPtr pLineString = OdDgLineString3d::createObject(); setCurveElementPropertiesFrom(pLineString, pArc3d, false); for (OdUInt32 i = 0; i < arrTransformedPts.size(); i++) pLineString->addVertex(arrTransformedPts[i]); pArc3d->handOverTo(pLineString); } } else { OdGeEllipArc3d ellipArcMod; if( reprojectGeArc3d(ellipArc, pTransformer, reprojectionSettings.m_bReprojectEllevations, ellipArcMod) ) bRet = pArc3d->setFromOdGeCurve(ellipArcMod) == eOk; } return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgEllipse2dByGeoData(OdDgEllipse2d* pEllipse2d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { bool bRet = true; bool bConvertArcToPolyline = false; if (reprojectionSettings.m_uStrokeEllipsesToLineStrings == OdDgGeoDataReprojectionSettings::kAlways) bConvertArcToPolyline = true; else if (reprojectionSettings.m_uStrokeEllipsesToLineStrings == OdDgGeoDataReprojectionSettings::kIfSpatiallyLarge) { OdGeEllipArc2d ellipArc = pEllipse2d->getEllipArc(); if (ellipArc.length() > reprojectionSettings.m_dSpatiallyLargeDistance) bConvertArcToPolyline = true; } OdGeEllipArc2d ellipArc = pEllipse2d->getEllipArc(); if (bConvertArcToPolyline) { OdGePoint2dArray arrArcPts; OdGePoint2dArray arrTransformedPts; OdGeInterval arcInverval; ellipArc.getInterval(arcInverval); ellipArc.getSamplePoints(arcInverval.lowerBound(), arcInverval.upperBound(), reprojectionSettings.m_dStrokeTolerance, arrArcPts); bRet = transformPolylineByGeoData(arrArcPts, pTransformer, reprojectionSettings, arrTransformedPts, false, false); if (bRet) { OdDgShape2dPtr pLineString = OdDgShape2d::createObject(); setCurveElementPropertiesFrom(pLineString, pEllipse2d, false); for (OdUInt32 i = 0; i < arrTransformedPts.size(); i++) pLineString->addVertex(arrTransformedPts[i]); pEllipse2d->handOverTo(pLineString); } } else { OdGeEllipArc2d ellipArcMod; if (reprojectGeArc2d(ellipArc, pTransformer, ellipArcMod)) bRet = pEllipse2d->setFromOdGeCurve(ellipArcMod) == eOk; } return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgEllipse3dByGeoData(OdDgEllipse3d* pEllipse3d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { bool bRet = true; bool bConvertArcToPolyline = false; if (reprojectionSettings.m_uStrokeEllipsesToLineStrings == OdDgGeoDataReprojectionSettings::kAlways) bConvertArcToPolyline = true; else if (reprojectionSettings.m_uStrokeEllipsesToLineStrings == OdDgGeoDataReprojectionSettings::kIfSpatiallyLarge) { OdGeEllipArc3d ellipArc = pEllipse3d->getEllipArc(); if (ellipArc.length() > reprojectionSettings.m_dSpatiallyLargeDistance) bConvertArcToPolyline = true; } OdGeEllipArc3d ellipArc = pEllipse3d->getEllipArc(); if (bConvertArcToPolyline) { OdGePoint3dArray arrArcPts; OdGePoint3dArray arrTransformedPts; OdGeInterval arcInverval; ellipArc.getInterval(arcInverval); ellipArc.getSamplePoints(arcInverval.lowerBound(), arcInverval.upperBound(), reprojectionSettings.m_dStrokeTolerance, arrArcPts); bRet = transformPolylineByGeoData(arrArcPts, pTransformer, reprojectionSettings, arrTransformedPts, false, false); if (bRet) { OdDgShape3dPtr pLineString = OdDgShape3d::createObject(); setCurveElementPropertiesFrom(pLineString, pEllipse3d, false); for (OdUInt32 i = 0; i < arrTransformedPts.size(); i++) pLineString->addVertex(arrTransformedPts[i]); pEllipse3d->handOverTo(pLineString); } } else { OdGeEllipArc3d ellipArcMod; if (reprojectGeArc3d(ellipArc, pTransformer, reprojectionSettings.m_bReprojectEllevations, ellipArcMod)) bRet = pEllipse3d->setFromOdGeCurve(ellipArcMod) == eOk; } return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgCurve2dByGeoData(OdDgCurve2d* pCurve2d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { bool bRet = true; bool bConvertToPolyline = false; OdGeNurbCurve3d nurbCurve; if (reprojectionSettings.m_uStrokeCurvesToLineStrings == OdDgGeoDataReprojectionSettings::kAlways) bConvertToPolyline = true; else if (reprojectionSettings.m_uStrokeCurvesToLineStrings == OdDgGeoDataReprojectionSettings::kIfSpatiallyLarge) { if( !pCurve2d->getGeNurbCurve(nurbCurve) ) return true; if (nurbCurve.length() > reprojectionSettings.m_dSpatiallyLargeDistance) bConvertToPolyline = true; } if (bConvertToPolyline) { if (!pCurve2d->getGeNurbCurve(nurbCurve)) return true; OdGePoint3dArray arrArcPts; OdGeInterval arcInverval; nurbCurve.getInterval(arcInverval); nurbCurve.getSamplePoints(arcInverval.lowerBound(), arcInverval.upperBound(), reprojectionSettings.m_dStrokeTolerance, arrArcPts); OdGePoint2dArray arrArcPts2d; OdGePoint2dArray arrTransformedPts; arrArcPts2d.resize(arrArcPts.size()); for (OdUInt32 i = 0; i < arrArcPts.size(); i++) arrArcPts2d[i] = arrArcPts[i].convert2d(); bRet = transformPolylineByGeoData(arrArcPts2d, pTransformer, reprojectionSettings, arrTransformedPts, false, false); if (bRet) { OdDgLineString2dPtr pLineString = OdDgLineString2d::createObject(); setCurveElementPropertiesFrom(pLineString, pCurve2d, false); for (OdUInt32 i = 0; i < arrTransformedPts.size(); i++) pLineString->addVertex(arrTransformedPts[i]); pCurve2d->handOverTo(pLineString); } } else { OdGePoint2dArray arrLinePts; arrLinePts.resize(pCurve2d->getVerticesCount()); for (OdUInt32 i = 0; i < pCurve2d->getVerticesCount(); i++) arrLinePts[i] = pCurve2d->getVertexAt(i); OdGePoint2dArray arrTransformedPts; bool bRet = transformPolylineByGeoData(arrLinePts, pTransformer, reprojectionSettings, arrTransformedPts, false, false); if (bRet) { pCurve2d->removeAllVertices(); for (OdUInt32 j = 0; j < arrTransformedPts.size(); j++) pCurve2d->addVertex(arrTransformedPts[j]); } } return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgCurve3dByGeoData(OdDgCurve3d* pCurve3d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { bool bRet = true; bool bConvertToPolyline = false; OdGeNurbCurve3d nurbCurve; if (reprojectionSettings.m_uStrokeCurvesToLineStrings == OdDgGeoDataReprojectionSettings::kAlways) bConvertToPolyline = true; else if (reprojectionSettings.m_uStrokeCurvesToLineStrings == OdDgGeoDataReprojectionSettings::kIfSpatiallyLarge) { if (!pCurve3d->getGeNurbCurve(nurbCurve)) return true; if (nurbCurve.length() > reprojectionSettings.m_dSpatiallyLargeDistance) bConvertToPolyline = true; } if (bConvertToPolyline) { if (!pCurve3d->getGeNurbCurve(nurbCurve)) return true; OdGePoint3dArray arrArcPts; OdGeInterval arcInverval; nurbCurve.getInterval(arcInverval); nurbCurve.getSamplePoints(arcInverval.lowerBound(), arcInverval.upperBound(), reprojectionSettings.m_dStrokeTolerance, arrArcPts); OdGePoint3dArray arrTransformedPts; bRet = transformPolylineByGeoData(arrArcPts, pTransformer, reprojectionSettings, arrTransformedPts, false, false); if (bRet) { OdDgLineString3dPtr pLineString = OdDgLineString3d::createObject(); setCurveElementPropertiesFrom(pLineString, pCurve3d, false); for (OdUInt32 i = 0; i < arrTransformedPts.size(); i++) pLineString->addVertex(arrTransformedPts[i]); pCurve3d->handOverTo(pLineString); } } else { OdGePoint3dArray arrLinePts; arrLinePts.resize(pCurve3d->getVerticesCount()); for (OdUInt32 i = 0; i < pCurve3d->getVerticesCount(); i++) arrLinePts[i] = pCurve3d->getVertexAt(i); OdGePoint3dArray arrTransformedPts; bool bRet = transformPolylineByGeoData(arrLinePts, pTransformer, reprojectionSettings, arrTransformedPts, false, false); if (bRet) { pCurve3d->removeAllVertices(); for (OdUInt32 j = 0; j < arrTransformedPts.size(); j++) pCurve3d->addVertex(arrTransformedPts[j]); } } return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgBSplineCurve2dByGeoData(OdDgBSplineCurve2d* pBSplineCurve2d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { bool bRet = true; bool bConvertToPolyline = false; OdGeCurve2d* pGeCurve = NULL; if (reprojectionSettings.m_uStrokeCurvesToLineStrings == OdDgGeoDataReprojectionSettings::kAlways) bConvertToPolyline = true; else if (reprojectionSettings.m_uStrokeCurvesToLineStrings == OdDgGeoDataReprojectionSettings::kIfSpatiallyLarge) { if( pBSplineCurve2d->getOdGeCurve(pGeCurve) != eOk ) return true; if (pGeCurve->length() > reprojectionSettings.m_dSpatiallyLargeDistance) bConvertToPolyline = true; } if (bConvertToPolyline) { if(!pGeCurve && pBSplineCurve2d->getOdGeCurve(pGeCurve) != eOk) return true; OdGePoint2dArray arrArcPts; OdGeInterval arcInverval; pGeCurve->getInterval(arcInverval); pGeCurve->getSamplePoints(arcInverval.lowerBound(), arcInverval.upperBound(), reprojectionSettings.m_dStrokeTolerance, arrArcPts); OdGePoint2dArray arrTransformedPts; bRet = transformPolylineByGeoData(arrArcPts, pTransformer, reprojectionSettings, arrTransformedPts, false, false); if (bRet) { if( !pBSplineCurve2d->isClosed() ) { OdDgLineString2dPtr pLineString = OdDgLineString2d::createObject(); setCurveElementPropertiesFrom(pLineString, pBSplineCurve2d, false); for (OdUInt32 i = 0; i < arrTransformedPts.size(); i++) pLineString->addVertex(arrTransformedPts[i]); pBSplineCurve2d->handOverTo(pLineString); } else { OdDgShape2dPtr pLineString = OdDgShape2d::createObject(); setCurveElementPropertiesFrom(pLineString, pBSplineCurve2d, false); for (OdUInt32 i = 0; i < arrTransformedPts.size(); i++) pLineString->addVertex(arrTransformedPts[i]); pBSplineCurve2d->handOverTo(pLineString); } } } else { OdGePoint2dArray arrLinePts; arrLinePts.resize(pBSplineCurve2d->numControlPoints()); for (OdUInt32 i = 0; i < pBSplineCurve2d->numControlPoints(); i++) pBSplineCurve2d->getControlPointAt(i, arrLinePts[i]); OdGePoint2dArray arrTransformedPts; bool bRet = transformPolylineByGeoData(arrLinePts, pTransformer, reprojectionSettings, arrTransformedPts, false, false); if (bRet) { for (OdUInt32 j = 0; j < arrTransformedPts.size(); j++) pBSplineCurve2d->setControlPointAt(j, arrTransformedPts[j]); } } if (pGeCurve) delete pGeCurve; return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgBSplineCurve3dByGeoData(OdDgBSplineCurve3d* pBSplineCurve3d, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { bool bRet = true; bool bConvertToPolyline = false; OdGeCurve3d* pGeCurve = NULL; if (reprojectionSettings.m_uStrokeCurvesToLineStrings == OdDgGeoDataReprojectionSettings::kAlways) bConvertToPolyline = true; else if (reprojectionSettings.m_uStrokeCurvesToLineStrings == OdDgGeoDataReprojectionSettings::kIfSpatiallyLarge) { if (pBSplineCurve3d->getOdGeCurve(pGeCurve) != eOk) return true; if (pGeCurve->length() > reprojectionSettings.m_dSpatiallyLargeDistance) bConvertToPolyline = true; } if (bConvertToPolyline) { if (!pGeCurve && pBSplineCurve3d->getOdGeCurve(pGeCurve) != eOk) return true; OdGePoint3dArray arrArcPts; OdGeInterval arcInverval; pGeCurve->getInterval(arcInverval); pGeCurve->getSamplePoints(arcInverval.lowerBound(), arcInverval.upperBound(), reprojectionSettings.m_dStrokeTolerance, arrArcPts); OdGePoint3dArray arrTransformedPts; bRet = transformPolylineByGeoData(arrArcPts, pTransformer, reprojectionSettings, arrTransformedPts, false, false); if (bRet) { if( !pBSplineCurve3d->isClosed() ) { OdDgLineString3dPtr pLineString = OdDgLineString3d::createObject(); setCurveElementPropertiesFrom(pLineString, pBSplineCurve3d, false); for (OdUInt32 i = 0; i < arrTransformedPts.size(); i++) pLineString->addVertex(arrTransformedPts[i]); pBSplineCurve3d->handOverTo(pLineString); } else { OdDgShape3dPtr pLineString = OdDgShape3d::createObject(); setCurveElementPropertiesFrom(pLineString, pBSplineCurve3d, false); for (OdUInt32 i = 0; i < arrTransformedPts.size(); i++) pLineString->addVertex(arrTransformedPts[i]); pBSplineCurve3d->handOverTo(pLineString); } } } else { OdGePoint3dArray arrLinePts; arrLinePts.resize(pBSplineCurve3d->numControlPoints()); for (OdUInt32 i = 0; i < pBSplineCurve3d->numControlPoints(); i++) pBSplineCurve3d->getControlPointAt(i, arrLinePts[i]); OdGePoint3dArray arrTransformedPts; bool bRet = transformPolylineByGeoData(arrLinePts, pTransformer, reprojectionSettings, arrTransformedPts, false, false); if (bRet) { for (OdUInt32 j = 0; j < arrTransformedPts.size(); j++) pBSplineCurve3d->setControlPointAt(j, arrTransformedPts[j]); } } if (pGeCurve) delete pGeCurve; return bRet; } //---------------------------------------------------------------------------------------------------------------------------------- bool reprojectDgComplexCurveByGeoData(OdDgComplexCurve* pComplexCurve, const OdDgGeoDataReprojectionCoordinateTransformer* pTransformer, const OdDgGeoDataReprojectionSettings& reprojectionSettings) { OdDgElementIteratorPtr pIter = pComplexCurve->createIterator(); for(; !pIter->done(); pIter->step()) { OdDgElementPtr pElm = pIter->item().openObject(OdDg::kForWrite); reprojectDgnElementByGeoData(pElm, pTransformer, reprojectionSettings); } return true; } //----------------------------------------------------------------------------------------------------------------------------------