/////////////////////////////////////////////////////////////////////////////// // 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 #include "DgnImportImpl.h" #include #include #include #include #include #include #include "DbSymUtl.h" #include "DgShape.h" #include #include "DgGiContext.h" #include "DgnImportCommon.h" #include "DgnImportContext.h" #include "DgnImportPatterns.h" #include #include #include #include #include #include #include #include #include "Ge/GeCircArc3d.h" #include "Ge/GeNurbCurve3d.h" #include "Ge/GeEllipArc3d.h" #include "OdRound.h" using namespace TD_DGN_IMPORT; namespace TD_DGN_IMPORT { #define MAX_DWG_HATCH_LINES 20000 //----------------------------------------------------------------------------------------- // Import hatch and gradient //----------------------------------------------------------------------------------------- extern void importSymbolPatternOnly(OdDgElement* e, OdDbBlockTableRecord* owner); void importGradient( OdDbHatchPtr& pHatch, const OdDgGradientFill& gradientFill ) { pHatch->setHatchObjectType( OdDbHatch::kGradientObject ); pHatch->setGradientAngle( gradientFill.getAngle() ); pHatch->setGradientOneColorMode( gradientFill.getKeyCount() < 2 ); switch( gradientFill.getGradientType() ) { case OdDgGradientFill::kLinear: { if( gradientFill.getInvertFlag() ) { pHatch->setGradient( OdDbHatch::kPreDefinedGradient, L"INVLINEAR" ); } else { pHatch->setGradient( OdDbHatch::kPreDefinedGradient, L"LINEAR" ); } } break; case OdDgGradientFill::kCurved: { if( gradientFill.getInvertFlag() ) { pHatch->setGradient( OdDbHatch::kPreDefinedGradient, L"INVCURVED" ); } else { pHatch->setGradient( OdDbHatch::kPreDefinedGradient, L"CURVED" ); } } break; case OdDgGradientFill::kCylindrical: { if( gradientFill.getInvertFlag() ) { pHatch->setGradient( OdDbHatch::kPreDefinedGradient, L"INVCYLINDER" ); } else { pHatch->setGradient( OdDbHatch::kPreDefinedGradient, L"CYLINDER" ); } } break; case OdDgGradientFill::kSpherical: { if( gradientFill.getInvertFlag() ) { pHatch->setGradient( OdDbHatch::kPreDefinedGradient, L"INVSPHERICAL" ); } else { pHatch->setGradient( OdDbHatch::kPreDefinedGradient, L"SPHERICAL" ); } } break; case OdDgGradientFill::kHemispherical: { if( gradientFill.getInvertFlag() ) { pHatch->setGradient( OdDbHatch::kPreDefinedGradient, L"INVHEMISPHERICAL" ); } else { pHatch->setGradient( OdDbHatch::kPreDefinedGradient, L"HEMISPHERICAL" ); } } break; } OdArray arrValues; OdArray arrColors; if( gradientFill.getKeyCount() == 0 ) { OdCmColor curColor = pHatch->color(); arrColors.push_back( curColor ); curColor.setRGB( (OdUInt8)(255 * gradientFill.getWhiteIntensity()), (OdUInt8)(255 * gradientFill.getWhiteIntensity()), (OdUInt8)(255 * gradientFill.getWhiteIntensity()) ); arrColors.push_back( curColor ); arrValues.push_back(0); arrValues.push_back(1); } else if( gradientFill.getKeyCount() == 1 ) { OdDgGradientKey gradKey = gradientFill.getKey(0); OdCmColor curColor; curColor.setRGB( ODGETRED(gradKey.clrKeyColor), ODGETGREEN(gradKey.clrKeyColor), ODGETBLUE(gradKey.clrKeyColor) ); arrColors.push_back( curColor ); curColor.setRGB( (OdUInt8)(255 * gradientFill.getWhiteIntensity()), (OdUInt8)(255 * gradientFill.getWhiteIntensity()), (OdUInt8)(255 * gradientFill.getWhiteIntensity()) ); arrColors.push_back( curColor ); arrValues.push_back(gradKey.dKeyPosition); arrValues.push_back(1); } else { OdDgGradientKey firstKey = gradientFill.getKey(0); OdDgGradientKey lastKey = gradientFill.getKey(gradientFill.getKeyCount() - 1); arrValues.push_back(firstKey.dKeyPosition); arrValues.push_back(lastKey.dKeyPosition); OdCmColor curColor; curColor.setRGB( ODGETRED(firstKey.clrKeyColor), ODGETGREEN(firstKey.clrKeyColor), ODGETBLUE(firstKey.clrKeyColor) ); arrColors.push_back( curColor ); curColor.setRGB( ODGETRED(lastKey.clrKeyColor), ODGETGREEN(lastKey.clrKeyColor), ODGETBLUE(lastKey.clrKeyColor) ); arrColors.push_back( curColor ); } pHatch->setGradientColors(arrValues.size(), arrColors.asArrayPtr(), arrValues.asArrayPtr() ); } //----------------------------------------------------------------------------------------- void applyDgnPatternSymbologyToHatchBase(OdDbHatchPtr& pHatch, OdDgDatabase* pDb, const OdDgHatchPattern* pPaternLinkage, const OdDgGraphicsElement* pElm ) { if( !pPaternLinkage ) return; if( pPaternLinkage->isKindOf(OdDgLinearHatchPattern::desc()) ) { OdDgLinearHatchPatternPtr pPattern = pPaternLinkage; applyDgnPatternSymbologyToHatch(pHatch, pDb, pPattern, pElm); } else if (pPaternLinkage->isKindOf(OdDgCrossHatchPattern::desc())) { OdDgCrossHatchPatternPtr pPattern = pPaternLinkage; applyDgnPatternSymbologyToHatch(pHatch, pDb, pPattern, pElm); } } //----------------------------------------------------------------------------------------- template void applyDgnPatternSymbologyToHatch( OdDbHatchPtr& pHatch, OdDgDatabase* pDb, const T* pPaternLinkage, const OdDgGraphicsElement* pElm ) { if( pPaternLinkage->getUseLineColorFlag() ) { OdUInt32 color = pPaternLinkage->getLineColorIndex(); if (OdDgnImportContext::getActualViewFlags().getUseLevelSymbologyFlag()) { OdDgElementId idLevel; if (OdDgnImportContext::getLockLevelFlag()) idLevel = OdDgnImportContext::getLevelOverride(OdDgnImportContext::getLockedLevelId()); else idLevel = OdDgnImportContext::getLevelOverride(pElm->getLevelId()); OdUInt32 uLineWeight = 0; OdInt32 iLineStyleId = 0; bool bLineStyleIsFromLevelDatabase = false; applyLevelSymbologyOverrides(idLevel, color, uLineWeight, iLineStyleId, bLineStyleIsFromLevelDatabase); } setDwgColorByDgnIndex( pDb, pHatch, color); } applyDgnPatternLineTypeAndWeightToHatch( pHatch, pDb, pPaternLinkage, pElm ); } template void applyDgnPatternLineTypeAndWeightToHatch( OdDbHatchPtr& pHatch, OdDgDatabase* pDb, const T* pPaternLinkage, const OdDgGraphicsElement* pElm ) { OdUInt32 color = 0; OdUInt32 uLineWeight = 0; OdInt32 iLineStyleId = 0; if( pPaternLinkage->getUseLineWeightFlag() ) uLineWeight = pPaternLinkage->getLineWeight(); if (pPaternLinkage->getUseLineStyleFlag()) iLineStyleId = pPaternLinkage->getLineStyleEntryId(); if( (pPaternLinkage->getUseLineWeightFlag() || pPaternLinkage->getUseLineStyleFlag()) && OdDgnImportContext::getActualViewFlags().getUseLevelSymbologyFlag() ) { OdDgElementId idLevel; if (OdDgnImportContext::getLockLevelFlag()) idLevel = OdDgnImportContext::getLevelOverride(OdDgnImportContext::getLockedLevelId()); else idLevel = OdDgnImportContext::getLevelOverride(pElm->getLevelId()); bool bLineStyleIsFromLevelDatabase = false; applyLevelSymbologyOverrides(idLevel, color, uLineWeight, iLineStyleId, bLineStyleIsFromLevelDatabase); } if( pPaternLinkage->getUseLineWeightFlag() ) { pHatch->setLineWeight(odDgnImportLineweightMapping(uLineWeight)); } if( pPaternLinkage->getUseLineStyleFlag() ) { if( iLineStyleId < 8 && iLineStyleId >= 0 ) { if( iLineStyleId == 0 ) pHatch->setLinetype(pHatch->database()->getLinetypeContinuousId()); else { pHatch->setLinetype(OdString().format(OD_T("DGN%d"), iLineStyleId)); if (!pHatch->linetypeId().isNull()) OdDgnImportContext::setResourceUsage(pHatch->linetypeId(), true); } } else if( iLineStyleId == OdDg::kLineStyleByLevel ) { pHatch->setLinetype(pHatch->database()->getLinetypeByLayerId()); } else if( iLineStyleId == OdDg::kLineStyleByCell) { pHatch->setLinetype(pHatch->database()->getLinetypeByBlockId()); } else { OdDgElementId idLineStyle; if( pDb ) { OdDgLineStyleTablePtr pLSTable = pDb->getLineStyleTable( OdDg::kForRead ); if( !pLSTable.isNull() ) { idLineStyle = pLSTable->getAt(iLineStyleId); } } OdDbObjectId ltpId = pHatch->database()->getOdDbObjectId(idLineStyle.getHandle()); if( ltpId.isNull() ) { ltpId = pHatch->database()->getLinetypeContinuousId(); } pHatch->setLinetype(ltpId); if (!ltpId.isNull()) OdDgnImportContext::setResourceUsage(ltpId, true); } } } //----------------------------------------------------------------------------------------- void applyDgnSymbolPatternSymbologyToHatch( OdDbHatchPtr& pHatch, OdDgDatabase* pDb, const OdDgSymbolHatchPattern* pPaternLinkage, const OdDgGraphicsElement* pElm ) { if( pPaternLinkage->getUseColorFlag() ) { setDwgColorByDgnIndex( pDb, pHatch, pPaternLinkage->getColorIndex() ); } applyDgnPatternLineTypeAndWeightToHatch( pHatch, pDb, pPaternLinkage, pElm ); } //----------------------------------------------------------------------------------------- OdGePoint3d getHatchSeedPointBase( OdDgElement* pElm ) { switch( pElm->getElementType() ) { case OdDgElement::kTypeEllipse : { if( pElm->isKindOf( OdDgEllipse2d::desc() ) ) { OdDgEllipse2dPtr ellipse = pElm; OdGePoint2d origin = ellipse->getOrigin(); return OdGePoint3d( origin.x, origin.y, 0. ); } else { OdDgEllipse3dPtr ellipse = pElm; OdGePoint3d origin; ellipse->getOrigin( origin ); return origin; } } break; case OdDgElement::kTypeShape : { if( pElm->isKindOf( OdDgShape2d::desc() ) ) { OdDgShape2dPtr shape = pElm; OdGePoint2d origin = shape->getVertexAt( 0 ); return OdGePoint3d( origin.x, origin.y, 0. ); } else { OdDgShape3dPtr shape = pElm; return shape->getVertexAt( 0 ); } } break; case OdDgElement::kTypeBSplineCurve : { OdGeExtents3d extents; if( pElm->isKindOf(OdDgBSplineCurve2d::desc()) ) { OdDgBSplineCurve2dPtr pCurve2d = pElm; OdGePoint3dArray arrCtrlPts; OdUInt32 i; if( pCurve2d->hasFitData() ) { for( i = 0; i < pCurve2d->numFitPoints(); i++ ) { OdGePoint2d ptFit; if( pCurve2d->getFitPointAt(i, ptFit) == eOk ) { arrCtrlPts.push_back( OdGePoint3d(ptFit.x, ptFit.y, 0.0) ); } } } else { for( i = 0; i < pCurve2d->numControlPoints(); i++ ) { OdGePoint2d ptCtrl; if( pCurve2d->getControlPointAt(i, ptCtrl) == eOk ) { arrCtrlPts.push_back( OdGePoint3d(ptCtrl.x, ptCtrl.y, 0.0) ); } } } for( i = 0; i < arrCtrlPts.size(); i++ ) { extents.addPoint( arrCtrlPts[i] ); } } else { OdDgBSplineCurve3dPtr pCurve3d = pElm; OdUInt32 i; if( pCurve3d->hasFitData() ) { for( i = 0; i < pCurve3d->numFitPoints(); i++ ) { OdGePoint3d ptFit; if( pCurve3d->getFitPointAt(i, ptFit) == eOk ) { extents.addPoint( ptFit ); } } } else { for( i = 0; i < pCurve3d->numControlPoints(); i++ ) { OdGePoint3d ptCtrl; if( pCurve3d->getControlPointAt(i, ptCtrl) == eOk ) { extents.addPoint( ptCtrl ); } } } } if( extents.isValidExtents() ) { return extents.minPoint(); } } break; case OdDgElement::kTypeComplexShape: case OdDgElement::kTypeCellHeader: { OdGeExtents3d extents; pElm->getGeomExtents(extents); if( extents.isValidExtents() ) { return extents.minPoint(); } else { OdArray arrInvisibleStatus; OdArray arrElementId; pElm->getGeomExtents(extents); if( extents.isValidExtents() ) { return extents.minPoint(); } } } break; } return OdGePoint3d(); } //----------------------------------------------------------------------------------------- OdGePoint2d getHatchSeedPoint( OdDgElement* pElm, OdDgHatchPatternPtr pHatchPattern, OdDbHatchPtr& pHatch, double dUORsToModelScale ) { OdGePoint3d ptSeedBase(0,0,0); if( !pElm || pHatchPattern.isNull() || pHatch.isNull() || pHatch->isErased() ) { return ptSeedBase.convert2d(); } if( pHatchPattern->getUseOffsetFlag() ) pHatchPattern->getOffset( ptSeedBase ); OdGePoint3d ptElementOrigin(0,0,0); if( pHatchPattern->getType() == OdDgHatchPattern::kDWGPattern ) { OdDgDWGHatchPatternPtr pDwgPattern = pHatchPattern; if (!pDwgPattern->getPatternName().isEmpty()) ptSeedBase = OdGePoint3d::kOrigin; else ptElementOrigin = getHatchSeedPointBase(pElm); } else { ptElementOrigin = getHatchSeedPointBase( pElm ); } if( ptElementOrigin.distanceTo( ptSeedBase ) > 1e12 ) { ptSeedBase = ptElementOrigin; } else { ptSeedBase += ptElementOrigin.asVector(); } OdGeMatrix3d matrix; matrix.setToWorldToPlane(pHatch->normal()); ptSeedBase = ptSeedBase.transformBy(matrix); return ptSeedBase.convert2d(); } //----------------------------------------------------------------------------------------- void importLinearPattern( OdDbHatchPtr& pHatch, OdDgElement* pElm, const OdDgLinearHatchPatternPtr& pPaternLinkage, double dUORsToModelScale ) { OdDgDatabase* pDb = pElm->database(); pHatch->setHatchStyle( OdDbHatch::kNormal ); pHatch->setHatchObjectType( OdDbHatch::kHatchObject ); OdHatchPattern linearPattern; OdHatchPatternLine patternLine; patternLine.m_basePoint.set(0.0,0.5); patternLine.m_dLineAngle = 0; patternLine.m_patternOffset.set(0.0,pPaternLinkage->getSpace()); patternLine.m_dashes.push_back(pPaternLinkage->getSpace()); linearPattern.push_back( patternLine ); OdGePoint2d ptBase = getHatchSeedPoint( pElm, pPaternLinkage, pHatch, dUORsToModelScale ); pHatch->setPattern(OdDbHatch::kUserDefined, L"HATCH", pPaternLinkage->getAngle(), 1.0, linearPattern, ptBase ); OdDgGraphicsElementPtr pGrElm = pElm; applyDgnPatternSymbologyToHatch( pHatch, pDb, pPaternLinkage.get(), pGrElm); } //----------------------------------------------------------------------------------------- void importCrossPattern( OdDbHatchPtr& pHatch, OdDgElement* pElm, const OdDgCrossHatchPatternPtr& pPaternLinkage, double dUORsToModelScale ) { OdDgDatabase* pDb = pElm->database(); pHatch->setHatchStyle( OdDbHatch::kNormal ); pHatch->setHatchObjectType( OdDbHatch::kHatchObject ); OdHatchPattern crossPattern; OdHatchPatternLine patternLine; patternLine.m_basePoint.set(0.0,0.0); patternLine.m_dLineAngle = pPaternLinkage->getAngle1(); patternLine.m_patternOffset.set(0.0,pPaternLinkage->getSpace1()); patternLine.m_dashes.push_back(pPaternLinkage->getSpace1()); crossPattern.push_back( patternLine ); patternLine.m_basePoint.set(0.0,0.0); patternLine.m_dLineAngle = pPaternLinkage->getAngle2(); patternLine.m_patternOffset.set(0.0,pPaternLinkage->getSpace2()); patternLine.m_dashes.clear(); patternLine.m_dashes.push_back(pPaternLinkage->getSpace2()); crossPattern.push_back( patternLine ); OdGePoint2d ptBase = getHatchSeedPoint( pElm, pPaternLinkage, pHatch, dUORsToModelScale ); pHatch->setPattern(OdDbHatch::kUserDefined, L"CROSSHATCH", 0.0, 1.0, crossPattern, ptBase ); OdDgGraphicsElementPtr pGrElm = pElm; applyDgnPatternSymbologyToHatch( pHatch, pDb, pPaternLinkage.get(), pGrElm); } //----------------------------------------------------------------------------------------- void importSymbolPattern( OdDgElement* pElm, OdDbBlockTableRecord* owner ) { OdDbObjectId idBlockTable = owner->database()->getBlockTableId(); if( idBlockTable.isNull() ) { return; } OdDbBlockTablePtr pBlockTable = idBlockTable.openObject(OdDb::kForWrite); if( !pBlockTable.isNull() ) { OdString strDefNameBase = L"SymbolPattern"; OdString strDefName = strDefNameBase + L"_1"; OdUInt32 uCount = 2; while( !pBlockTable->getAt( strDefName).isNull() ) { strDefName.format(L"_%d", uCount ); strDefName = strDefNameBase + strDefName; uCount++; } OdString repairedName; if( OdDbSymUtil::repairSymbolName(repairedName, strDefName, owner->database() ) == eOk && !repairedName.isEmpty() ) { strDefNameBase = repairedName; strDefName = strDefNameBase; } OdDbBlockTableRecordPtr pDwgSymbolPattern = OdDbBlockTableRecord::createObject(); pDwgSymbolPattern->setName( strDefName ); pBlockTable->add( pDwgSymbolPattern ); OdGePoint3d ptPatternOrigin = OdGePoint3d::kOrigin; OdGeExtents3d extShape; pElm->getGeomExtents( extShape ); if( extShape.isValidExtents() ) { ptPatternOrigin = extShape.center(); } importSymbolPatternOnly( pElm, pDwgSymbolPattern ); OdGeMatrix3d matTransform = OdGeMatrix3d::translation(-ptPatternOrigin.asVector()); if( matTransform != OdGeMatrix3d::kIdentity) { for (OdDbObjectIteratorPtr it = pDwgSymbolPattern->newIterator(); !it->done(); it->step()) { OdDbEntityPtr e = it->objectId().safeOpenObject(OdDb::kForWrite); e->transformBy(matTransform); } } OdDbBlockReferencePtr pBlockReference = OdDbBlockReference::createObject(); pBlockReference->setBlockTableRecord( pDwgSymbolPattern->objectId() ); owner->appendOdDbEntity( pBlockReference ); pBlockReference->setBlockTransform( OdGeMatrix3d::kIdentity ); pBlockReference->setPosition( ptPatternOrigin ); if( pElm->isKindOf( OdDgGraphicsElement::desc()) ) { OdDgGraphicsElement* pGrElm = dynamic_cast(pElm); copyEntityProperties( pGrElm, pBlockReference ); } } } //========================================================================================= OdDgnImportSymbolToHatchConverter::OdDgnImportSymbolToHatchConverter() { OdGiBaseVectorizer::m_flags |= (kDrawInvisibleEnts|kDrawLayerOff|kDrawLayerFrozen); setContext(this); OdGiGeometrySimplifier::setDrawContext(OdGiBaseVectorizer::drawContext()); m_pModelToEyeProc->setDrawContext(OdGiBaseVectorizer::drawContext()); output().setDestGeometry(*this); } //----------------------------------------------------------------------------------------- bool OdDgnImportSymbolToHatchConverter::convertSymbolToHatch( const OdDgSharedCellDefinition* pCell, double dTolerance, OdUInt32 nMaxLineNumber, OdUInt32 nMinLineNumber, OdUInt32 nArcSegNum, double dRowSpacing, double dColSpacing, OdHatchPattern& dwgPattern, double& dScaleFactor, OdUInt32& uHatchColorIndex ) { bool bRet = false; OdGeExtents3d extSymbol; pCell->getGeomExtents( extSymbol ); if( extSymbol.isValidExtents() ) { m_dTolerance = dTolerance; m_maxLineNumber = nMaxLineNumber; m_minLineNumber = nMinLineNumber; m_uSircleSegNum = nArcSegNum; m_dSymbolWidth = extSymbol.maxPoint().x - extSymbol.minPoint().x + dRowSpacing; m_dSymbolHeight = extSymbol.maxPoint().y - extSymbol.minPoint().y + dColSpacing; if( !OdZero( m_dSymbolWidth, 1e-8 ) && !OdZero( m_dSymbolHeight, 1e-8 ) ) { m_dBorderAngle = atan( m_dSymbolHeight / m_dSymbolWidth ); double dMaxValue = (m_dSymbolWidth > m_dSymbolHeight) ? m_dSymbolWidth : m_dSymbolHeight; m_ptOffset = extSymbol.minPoint(); m_dScaleFactor = dMaxValue; m_dSymbolWidth /= dMaxValue; m_dSymbolHeight /= dMaxValue; m_ptOffset.x /= dMaxValue; m_ptOffset.y /= dMaxValue; std::map colorMap; OdDgElementIteratorPtr pIter = pCell->createIterator(); for(; !pIter->done(); pIter->step() ) { OdDgElementPtr pItem = pIter->item().openObject(OdDg::kForRead); if( pItem->isKindOf( OdDgGraphicsElement::desc()) ) { OdUInt32 uColorIndex = ((OdDgGraphicsElementPtr)(pItem))->getColorIndex(); std::map::iterator pColorIter = colorMap.find( uColorIndex ); if( pColorIter != colorMap.end() ) { colorMap[uColorIndex]++; } else { colorMap[uColorIndex] = 1; } draw( pItem ); } } if( colorMap.size() > 2 ) { uHatchColorIndex = (OdUInt32)(-2); } else { std::map::iterator pColorIter = colorMap.begin(); uHatchColorIndex = pColorIter->first; OdUInt32 uMaxColors = pColorIter->second; for(; pColorIter != colorMap.end(); pColorIter++ ) { if( pColorIter->second > uMaxColors ) { uMaxColors = pColorIter->second; uHatchColorIndex = pColorIter->first; } } } dwgPattern = m_hatchPattern; dScaleFactor = m_dScaleFactor; bRet = true; } } return bRet; } //----------------------------------------------------------------------------------------- OdGiRegenType OdDgnImportSymbolToHatchConverter::regenType() const { return kOdGiStandardDisplay; } //----------------------------------------------------------------------------------------- void OdDgnImportSymbolToHatchConverter::createYTopLine( double dCurAngle, OdGePoint2d& ptStart, OdGePoint2d& ptEnd ) { OdUInt32 n = 0; OdUInt32 m = 0; OdUInt32 bestN = 0; double dMErrorMin = 1.0; bool bIdexesFound = false; double dScaleMN = m_dSymbolWidth * tan(dCurAngle) / m_dSymbolHeight; double dNMax = m_maxLineNumber * 1.0 / dScaleMN; OdUInt32 nMax = (OdUInt32)OdRound(dNMax); if( nMax < m_minLineNumber ) { nMax = m_minLineNumber; } for( n = 1; n < nMax; n++ ) { double dMFull = n * dScaleMN; double dMError = dMFull - OdRound(dMFull); if( fabs(dMError) < m_dTolerance ) { m = (OdUInt32)(OdRound(dMFull)); bIdexesFound = true; break; } else if( fabs(dMError) < dMErrorMin ) { dMErrorMin = fabs(dMError); bestN = n; } } if( !bIdexesFound ) { n = bestN; m = (OdUInt32)(OdRound(n * dScaleMN)); } OdGeVector2d vrDirection( n * m_dSymbolWidth, m*m_dSymbolHeight ); vrDirection.normalize(); dCurAngle = vrDirection.angle(); dScaleMN = m_dSymbolWidth * tan(dCurAngle) / m_dSymbolHeight; double dDashLength = ptStart.distanceTo(ptEnd); OdGePoint2d ptNewEnd = ptStart + vrDirection * dDashLength; if( !OdZero( ptNewEnd.distanceTo(ptEnd), 1e-3) ) { m_arrBasePoints.push_back( ptEnd ); m_arrCorrectedPoints.push_back( ptNewEnd ); } OdHatchPatternLine newLine; newLine.m_basePoint = ptStart; newLine.m_dLineAngle = dCurAngle; OdUInt32 nNext = 1; dMErrorMin = 1.0; for( OdUInt32 t = 1; t < n; t++ ) { double dMFull = t * dScaleMN; double dMError = dMFull - OdRound(dMFull); if( (dMError > 0) && (dMError < dMErrorMin) ) { dMErrorMin = dMError; nNext = t; } } double dYOffset = m_dSymbolWidth / m * sin( dCurAngle); double dXOffset = ( m_dSymbolWidth*nNext - m_dSymbolWidth / m )/cos(dCurAngle) + dYOffset / tan( dCurAngle ); newLine.m_patternOffset.set( -dXOffset, dYOffset ); newLine.m_dashes.push_back( dDashLength ); double dSectorGapLength = m_dSymbolHeight / sin( dCurAngle ) - dDashLength; if( !OdZero(dSectorGapLength) && (dSectorGapLength > 0) ) { newLine.m_dashes.push_back( -dSectorGapLength ); } double dSubSectorGap = m_dSymbolHeight * ( m - 1 ) / sin( dCurAngle ); if( !OdZero(dSubSectorGap) ) { newLine.m_dashes.push_back( -dSubSectorGap ); } m_hatchPattern.push_back( newLine ); } //----------------------------------------------------------------------------------------- void OdDgnImportSymbolToHatchConverter::createXTopLine( double dCurAngle, OdGePoint2d& ptStart, OdGePoint2d& ptEnd ) { OdUInt32 n = 0; OdUInt32 m = 0; OdUInt32 bestM = 0; double dNErrorMin = 1.0; bool bIdexesFound = false; double dScaleMN = m_dSymbolHeight / ( tan(dCurAngle) * m_dSymbolWidth ); double dMMax = m_maxLineNumber * 1.0 / dScaleMN; OdUInt32 mMax = (OdUInt32)OdRound(dMMax); if( mMax < m_minLineNumber ) { mMax = m_minLineNumber; } for( m = 1; m < mMax; m++ ) { double dNFull = m * dScaleMN; double dNError = dNFull - OdRound(dNFull); if( fabs(dNError) < m_dTolerance ) { n = (OdUInt32)(OdRound(dNFull)); bIdexesFound = true; break; } else if( fabs(dNError) < dNErrorMin ) { dNErrorMin = fabs(dNError); bestM = m; } } if( !bIdexesFound ) { m = bestM; n = (OdUInt32)(OdRound(m * dScaleMN)); } OdGeVector2d vrDirection( n * m_dSymbolWidth, m*m_dSymbolHeight ); vrDirection.normalize(); dCurAngle = vrDirection.angle(); dScaleMN = m_dSymbolHeight / ( tan(dCurAngle) * m_dSymbolWidth ); double dDashLength = ptStart.distanceTo(ptEnd); OdGePoint2d ptNewEnd = ptStart + vrDirection * dDashLength; if( !OdZero( ptNewEnd.distanceTo(ptEnd), 1e-3) ) { m_arrBasePoints.push_back( ptEnd ); m_arrCorrectedPoints.push_back( ptNewEnd ); } OdHatchPatternLine newLine; newLine.m_basePoint = ptStart; newLine.m_dLineAngle = dCurAngle; OdUInt32 mNext = 1; dNErrorMin = 1.0; for( OdUInt32 t = 1; t < m; t++ ) { double dNFull = t * dScaleMN; double dNError = dNFull - OdRound(dNFull); if( (dNError > 0) && (dNError < dNErrorMin) ) { dNErrorMin = dNError; mNext = t; } } double dYOffset = m_dSymbolHeight / n * cos( dCurAngle); double dXOffset = ( m_dSymbolHeight*mNext - m_dSymbolHeight / n )/sin(dCurAngle) + dYOffset * tan( dCurAngle ); newLine.m_patternOffset.set( dXOffset, dYOffset ); newLine.m_dashes.push_back( dDashLength ); double dSectorGapLength = m_dSymbolWidth / cos( dCurAngle ) - dDashLength; if( !OdZero(dSectorGapLength) && (dSectorGapLength > 0) ) { newLine.m_dashes.push_back( -dSectorGapLength ); } double dSubSectorGap = m_dSymbolWidth * ( n - 1 ) / cos( dCurAngle ); if( !OdZero(dSubSectorGap) ) { newLine.m_dashes.push_back( -dSubSectorGap ); } m_hatchPattern.push_back( newLine ); } //----------------------------------------------------------------------------------------- void OdDgnImportSymbolToHatchConverter::createYBottomLine( double dCurAngle, OdGePoint2d& ptStart, OdGePoint2d& ptEnd ) { OdUInt32 n = 0; OdUInt32 m = 0; OdUInt32 bestN = 0; double dMErrorMin = 1.0; bool bIdexesFound = false; double dScaleMN = m_dSymbolWidth * fabs(tan(dCurAngle)) / m_dSymbolHeight; double dNMax = m_maxLineNumber * 1.0 / dScaleMN; OdUInt32 nMax = (OdUInt32)OdRound(dNMax); if( nMax < m_minLineNumber ) { nMax = m_minLineNumber; } for( n = 1; n < nMax; n++ ) { double dMFull = n * dScaleMN; double dMError = dMFull - OdRound(dMFull); if( fabs(dMError) < m_dTolerance ) { m = (OdUInt32)(OdRound(dMFull)); bIdexesFound = true; break; } else if( fabs(dMError) < dMErrorMin ) { dMErrorMin = fabs(dMError); bestN = n; } } if( !bIdexesFound ) { n = bestN; m = (OdUInt32)(OdRound(n * dScaleMN)); } OdGeVector2d vrDirection( -1.0 * n * m_dSymbolWidth, m*m_dSymbolHeight ); vrDirection.normalize(); dCurAngle = vrDirection.angle(); dScaleMN = m_dSymbolWidth * fabs(tan(dCurAngle)) / m_dSymbolHeight; double dDashLength = ptStart.distanceTo(ptEnd); OdGePoint2d ptNewEnd = ptStart + vrDirection * dDashLength; if( !OdZero( ptNewEnd.distanceTo(ptEnd), 1e-3) ) { m_arrBasePoints.push_back( ptEnd ); m_arrCorrectedPoints.push_back( ptNewEnd ); } OdHatchPatternLine newLine; newLine.m_basePoint = ptStart; newLine.m_dLineAngle = dCurAngle; OdUInt32 nNext = 1; dMErrorMin = 1.0; for( OdUInt32 t = 1; t < n; t++ ) { double dMFull = t * dScaleMN; double dMError = dMFull - OdRound(dMFull); if( (dMError > 0) && (dMError < dMErrorMin) ) { dMErrorMin = dMError; nNext = t; } } double dYOffset = m_dSymbolWidth / m * fabs(sin( dCurAngle)); double dXOffset = ( m_dSymbolWidth*nNext - m_dSymbolWidth / m )/cos(dCurAngle) + dYOffset / fabs(tan( dCurAngle )); newLine.m_patternOffset.set( -dXOffset, dYOffset ); newLine.m_dashes.push_back( dDashLength ); double dSectorGapLength = m_dSymbolHeight / fabs(sin( dCurAngle )) - dDashLength; if( !OdZero(dSectorGapLength) && (dSectorGapLength > 0) ) { newLine.m_dashes.push_back( -dSectorGapLength ); } double dSubSectorGap = m_dSymbolHeight * ( m - 1 ) / fabs(sin( dCurAngle )); if( !OdZero(dSubSectorGap) ) { newLine.m_dashes.push_back( -dSubSectorGap ); } m_hatchPattern.push_back( newLine ); } //----------------------------------------------------------------------------------------- void OdDgnImportSymbolToHatchConverter::createXBottomLine( double dCurAngle, OdGePoint2d& ptStart, OdGePoint2d& ptEnd ) { OdUInt32 n = 0; OdUInt32 m = 0; OdUInt32 bestM = 0; double dNErrorMin = 1.0; bool bIdexesFound = false; double dScaleMN = m_dSymbolHeight / (fabs(tan(dCurAngle)) * m_dSymbolWidth); double dMMax = m_maxLineNumber * 1.0 / dScaleMN; OdUInt32 mMax = (OdUInt32)OdRound(dMMax); if( mMax < m_minLineNumber ) { mMax = m_minLineNumber; } for( m = 1; m < mMax; m++ ) { double dNFull = m * dScaleMN; double dNError = dNFull - OdRound(dNFull); if( fabs(dNError) < m_dTolerance ) { n = (OdUInt32)(OdRound(dNFull)); bIdexesFound = true; break; } else if( fabs(dNError) < dNErrorMin ) { dNErrorMin = fabs(dNError); bestM = m; } } if( !bIdexesFound ) { m = bestM; n = (OdUInt32)(OdRound(m * dScaleMN)); } OdGeVector2d vrDirection( n * m_dSymbolWidth, -1.0 * m*m_dSymbolHeight ); vrDirection.normalize(); dCurAngle = vrDirection.angle(); dScaleMN = m_dSymbolHeight / (fabs(tan(dCurAngle)) * m_dSymbolWidth); double dDashLength = ptStart.distanceTo(ptEnd); OdGePoint2d ptNewEnd = ptStart + vrDirection * dDashLength; if( !OdZero( ptNewEnd.distanceTo(ptEnd), 1e-3) ) { m_arrBasePoints.push_back( ptEnd ); m_arrCorrectedPoints.push_back( ptNewEnd ); } OdHatchPatternLine newLine; newLine.m_basePoint = ptStart; newLine.m_dLineAngle = dCurAngle; OdUInt32 mNext = 1; dNErrorMin = 1.0; for( OdUInt32 t = 1; t < m; t++ ) { double dNFull = t * dScaleMN; double dNError = dNFull - OdRound(dNFull); if( (dNError > 0) && (dNError < dNErrorMin) ) { dNErrorMin = dNError; mNext = t; } } double dYOffset = m_dSymbolHeight / n * cos( dCurAngle); double dXOffset = ( m_dSymbolHeight*mNext - m_dSymbolHeight / n )/fabs(sin(dCurAngle)) + dYOffset * fabs(tan( dCurAngle )); newLine.m_patternOffset.set( -dXOffset, dYOffset ); newLine.m_dashes.push_back( dDashLength ); double dSectorGapLength = m_dSymbolWidth / cos( dCurAngle ) - dDashLength; if( !OdZero(dSectorGapLength) && (dSectorGapLength > 0) ) { newLine.m_dashes.push_back( -dSectorGapLength ); } double dSubSectorGap = m_dSymbolWidth * ( n - 1 ) / cos( dCurAngle ); if( !OdZero(dSubSectorGap) ) { newLine.m_dashes.push_back( -dSubSectorGap ); } m_hatchPattern.push_back( newLine ); } //----------------------------------------------------------------------------------------- void OdDgnImportSymbolToHatchConverter::addHatchLine( OdGePoint2d ptStart, OdGePoint2d ptEnd ) { if( OdZero(ptStart.distanceTo( ptEnd )) ) { OdHatchPatternLine newLine; newLine.m_basePoint = ptStart; newLine.m_dLineAngle = 0; newLine.m_patternOffset.set( 0 , m_dSymbolHeight ); newLine.m_dashes.push_back(0); newLine.m_dashes.push_back(-m_dSymbolWidth); m_hatchPattern.push_back( newLine ); } else { OdGeVector2d vrLine = ptEnd - ptStart; vrLine.normalize(); double dCurAngle = vrLine.angle(); if( OdZero( dCurAngle, 1e-2) || OdZero( dCurAngle - OdaPI, 1e-2) || OdZero( dCurAngle - Oda2PI, 1e-2) ) { OdHatchPatternLine newLine; newLine.m_basePoint.set(0, ptStart.y); newLine.m_dLineAngle = 0; newLine.m_patternOffset.set( 0 , m_dSymbolHeight ); double dStartGap = 0; double dDash = 0; double dEndGap = 0; if( ptStart.x < ptEnd.x ) { dStartGap = ptStart.x; dDash = ptEnd.x - ptStart.x; dEndGap = m_dSymbolWidth - ptEnd.x; } else { dStartGap = ptEnd.x; dDash = ptStart.x - ptEnd.x; dEndGap = m_dSymbolWidth - ptStart.x; } if( !OdZero( dStartGap, 1e-8) ) { newLine.m_dashes.push_back(-dStartGap); } newLine.m_dashes.push_back(dDash); if( !OdZero( dEndGap, 1e-8) ) { newLine.m_dashes.push_back(-dEndGap); } m_hatchPattern.push_back( newLine ); OdGePoint2d ptNewEnd( ptEnd.x, ptStart.y); if( !OdZero( ptNewEnd.distanceTo(ptEnd), 1e-3) ) { m_arrBasePoints.push_back( ptEnd ); m_arrCorrectedPoints.push_back( ptNewEnd ); } } else if( OdZero( dCurAngle - OdaPI2, 1e-2) || OdZero( dCurAngle - 3*OdaPI2, 1e-2) ) { OdHatchPatternLine newLine; newLine.m_basePoint.set(ptStart.x, 0); newLine.m_dLineAngle = OdaPI2; newLine.m_patternOffset.set( 0 , m_dSymbolWidth ); double dStartGap = 0; double dDash = 0; double dEndGap = 0; if( ptStart.y < ptEnd.y ) { dStartGap = ptStart.y; dDash = ptEnd.y - ptStart.y; dEndGap = m_dSymbolHeight - ptEnd.y; } else { dStartGap = ptEnd.y; dDash = ptStart.y - ptEnd.y; dEndGap = m_dSymbolHeight - ptStart.y; } if( !OdZero( dStartGap, 1e-8) ) { newLine.m_dashes.push_back(-dStartGap); } newLine.m_dashes.push_back(dDash); if( !OdZero( dEndGap, 1e-8) ) { newLine.m_dashes.push_back(-dEndGap); } m_hatchPattern.push_back( newLine ); OdGePoint2d ptNewEnd( ptStart.x, ptEnd.y); if( !OdZero( ptNewEnd.distanceTo(ptEnd), 1e-3) ) { m_arrBasePoints.push_back( ptEnd ); m_arrCorrectedPoints.push_back( ptNewEnd ); } } else { if( (dCurAngle > OdaPI2) && (dCurAngle < 3*OdaPI2) ) { dCurAngle -= OdaPI; if( dCurAngle < 0 ) { dCurAngle = Oda2PI - dCurAngle; } OdGePoint2d ptTmp = ptStart; ptStart = ptEnd; ptEnd = ptTmp; } if( (dCurAngle < OdaPI2) && (dCurAngle > m_dBorderAngle) ) { createYTopLine( dCurAngle, ptStart, ptEnd ); } else if( m_dBorderAngle >= dCurAngle ) { createXTopLine( dCurAngle, ptStart, ptEnd ); } else if( dCurAngle > OdaPI ) { createXBottomLine( dCurAngle, ptStart, ptEnd ); } else { createYBottomLine( dCurAngle, ptStart, ptEnd ); } } } } //----------------------------------------------------------------------------------------- void OdDgnImportSymbolToHatchConverter::addHatchPolyline(const OdGePoint3dArray& arrPts) { addHatchPolyline( arrPts.asArrayPtr(), arrPts.size() ); } //----------------------------------------------------------------------------------------- void OdDgnImportSymbolToHatchConverter::addHatchPolyline(const OdGePoint3d* arrPts, OdUInt32 uNumPts ) { m_arrBasePoints.clear(); m_arrCorrectedPoints.clear(); for( OdUInt32 i = 0; i < uNumPts - 1; i++ ) { OdGePoint2d ptStart = arrPts[i].convert2d(); OdGePoint2d ptEnd = arrPts[i + 1].convert2d(); ptStart /= m_dScaleFactor; ptEnd /= m_dScaleFactor; ptStart -= m_ptOffset.convert2d().asVector(); ptEnd -= m_ptOffset.convert2d().asVector(); for( OdUInt32 j = 0; j < m_arrBasePoints.size(); j++ ) { if( OdZero( ptStart.distanceTo(m_arrBasePoints[j]), 1e-4 ) ) { ptStart = m_arrCorrectedPoints[j]; break; } } addHatchLine( ptStart, ptEnd ); } } //----------------------------------------------------------------------------------------- void OdDgnImportSymbolToHatchConverter::circleProc(const OdGePoint3d& center, double radius, const OdGeVector3d& normal, const OdGeVector3d* pExtrusion ) { OdGeCircArc3d geArc( center, normal, normal.perpVector(), radius, 0, Oda2PI ); OdGePoint3dArray arrPts; geArc.getSamplePoints( m_uSircleSegNum, arrPts ); if( geArc.isClosed() ) { if( !OdZero(arrPts[0].distanceTo(arrPts[arrPts.size() - 1])) ) { arrPts.push_back(arrPts[0]); } } addHatchPolyline( arrPts ); } //----------------------------------------------------------------------------------------- void OdDgnImportSymbolToHatchConverter::circleProc(const OdGePoint3d& pt1, const OdGePoint3d& pt2, const OdGePoint3d& pt3, const OdGeVector3d* pExtrusion ) { OdGeCircArc3d geArc1( pt1, pt2, pt3 ); OdGeCircArc3d geArc( geArc1.center(), geArc1.normal(), geArc1.normal().perpVector(), geArc1.radius(), 0, Oda2PI ); OdGePoint3dArray arrPts; geArc.getSamplePoints( m_uSircleSegNum, arrPts ); if( geArc.isClosed() ) { if( !OdZero(arrPts[0].distanceTo(arrPts[arrPts.size() - 1])) ) { arrPts.push_back(arrPts[0]); } } addHatchPolyline( arrPts ); } //----------------------------------------------------------------------------------------- void OdDgnImportSymbolToHatchConverter::circularArcProc(const OdGePoint3d& center, double radius, const OdGeVector3d& normal, const OdGeVector3d& startVector, double sweepAngle, OdGiArcType arcType, const OdGeVector3d* pExtrusion ) { OdGeCircArc3d geArc( center, normal, startVector, radius, 0, sweepAngle ); OdGePoint3dArray arrPts; geArc.getSamplePoints( m_uSircleSegNum, arrPts ); if( geArc.isClosed() ) { if( !OdZero(arrPts[0].distanceTo(arrPts[arrPts.size() - 1])) ) { arrPts.push_back(arrPts[0]); } } addHatchPolyline( arrPts ); } //----------------------------------------------------------------------------------------- void OdDgnImportSymbolToHatchConverter::circularArcProc(const OdGePoint3d& start, const OdGePoint3d& point, const OdGePoint3d& end, OdGiArcType arcType, const OdGeVector3d* pExtrusion ) { OdGeCircArc3d geArc( start, point, end ); OdGePoint3dArray arrPts; geArc.getSamplePoints( m_uSircleSegNum, arrPts ); if( geArc.isClosed() ) { if( !OdZero(arrPts[0].distanceTo(arrPts[arrPts.size() - 1])) ) { arrPts.push_back(arrPts[0]); } } addHatchPolyline( arrPts ); } //----------------------------------------------------------------------------------------- void OdDgnImportSymbolToHatchConverter::polylineOut(OdInt32 nbPoints, const OdGePoint3d* pVertexList) { addHatchPolyline( pVertexList, nbPoints ); } //----------------------------------------------------------------------------------------- void OdDgnImportSymbolToHatchConverter::polygonOut(OdInt32 numPoints, const OdGePoint3d* vertexList, const OdGeVector3d* pNormal ) { addHatchPolyline( vertexList, numPoints ); } //----------------------------------------------------------------------------------------- void OdDgnImportSymbolToHatchConverter::nurbsProc( const OdGeNurbCurve3d& nurbsCurve ) { OdGePoint3dArray arrPts; nurbsCurve.getSamplePoints( m_uSircleSegNum, arrPts ); if( nurbsCurve.isClosed() ) { if( !OdZero(arrPts[0].distanceTo(arrPts[arrPts.size() - 1])) ) { arrPts.push_back(arrPts[0]); } } addHatchPolyline( arrPts ); } //----------------------------------------------------------------------------------------- void OdDgnImportSymbolToHatchConverter::ellipArcProc( const OdGeEllipArc3d& ellipArc, const OdGePoint3d* endPointOverrides, OdGiArcType arcType, const OdGeVector3d* pExtrusion ) { OdGePoint3dArray arrPts; ellipArc.getSamplePoints( m_uSircleSegNum, arrPts ); if( ellipArc.isClosed() ) { if( !OdZero(arrPts[0].distanceTo(arrPts[arrPts.size() - 1])) ) { arrPts.push_back(arrPts[0]); } } addHatchPolyline( arrPts ); } //========================================================================================= void importSymbolPattern( OdDbHatchPtr& pHatch, OdDgElement* pElm, const OdDgSymbolHatchPatternPtr& pPaternLinkage, double dUORsToModelScale, OdDbBlockTableRecord* pOwner ) { pHatch->setHatchStyle( OdDbHatch::kNormal ); pHatch->setHatchObjectType( OdDbHatch::kHatchObject ); OdDgSharedCellDefinitionPtr pSymbol; OdDgSymbolHatchPatternPtr pSymbolHatch = pPaternLinkage; if( pSymbolHatch->getSymbolId() != 0 ) { OdDgElementId elementId = pElm->database()->getElementId( OdDbHandle( pSymbolHatch->getSymbolId() ) ); OdDgElementPtr element = elementId.openObject( OdDg::kForRead ); if( element->isKindOf( OdDgSharedCellDefinition::desc() ) ) pSymbol = element; } bool bCorrectHatch = false; if( !pSymbol.isNull() ) { OdString strHatchName = pSymbol->getName(); OdString repairedName; if( OdDbSymUtil::repairSymbolName(repairedName, strHatchName, pHatch->database() ) == eOk ) { if( !repairedName.isEmpty() ) strHatchName = repairedName; } OdDgnImportSymbolHatchDescriptor hatchDesc; OdUInt32 uHatchColorIndex = 0; if( OdDgnImportContext::getSymbolHatchDesc( pSymbol->elementId(), pPaternLinkage->getSpace2() / pPaternLinkage->getScale(), pPaternLinkage->getSpace1() / pPaternLinkage->getScale(), hatchDesc) ) { OdGePoint2d ptBase = getHatchSeedPoint( pElm, pPaternLinkage, pHatch, dUORsToModelScale ); double dAngle = pPaternLinkage->getAngle1(); if (pPaternLinkage->getUseRotationFlag() && pElm->isKindOf(OdDgGraphicsElement::desc())) { OdDgGraphicsElementPtr pGrElm = pElm; if (!pGrElm->get3dFormatFlag()) { OdGeMatrix2d matRotation; pPaternLinkage->getRotation2d(matRotation); OdGeVector2d vrX = OdGeVector2d::kXAxis; vrX.rotateBy(dAngle); vrX.transformBy(matRotation); dAngle = OdGeVector2d::kXAxis.angleToCCW(vrX); } } OdDbHatch::HatchPatternType patType = OdDbHatch::kUserDefined; if (strHatchName == L"SOLID" || strHatchName == L"_SOLID") patType = OdDbHatch::kPreDefined; pHatch->setPattern(patType, strHatchName, dAngle, pPaternLinkage->getScale() * hatchDesc.m_dHatchScale, hatchDesc.m_hatchPattern, ptBase ); uHatchColorIndex = hatchDesc.m_uColorIndex; bCorrectHatch = true; } else { OdHatchPattern dwgHatch; OdStaticRxObject symbolToHatch; double dSymbolScale = 1.0; if( symbolToHatch.convertSymbolToHatch( pSymbol, 1e-2, 300, 5, 12, pPaternLinkage->getSpace2() / pPaternLinkage->getScale(), pPaternLinkage->getSpace1() / pPaternLinkage->getScale(), dwgHatch, dSymbolScale, uHatchColorIndex ) ) { hatchDesc.m_dHatchScale = dSymbolScale; hatchDesc.m_hatchPattern = dwgHatch; hatchDesc.m_uColorIndex = uHatchColorIndex; hatchDesc.m_dPatternRowSpacing = pPaternLinkage->getSpace2() / pPaternLinkage->getScale(); hatchDesc.m_dPatternColSpacing = pPaternLinkage->getSpace1() / pPaternLinkage->getScale(); OdDgnImportContext::addSymbolHatchDesc( pSymbol->elementId(), hatchDesc ); OdGePoint2d ptBase = getHatchSeedPoint( pElm, pPaternLinkage, pHatch, dUORsToModelScale ); double dAngle = pPaternLinkage->getAngle1(); if( pPaternLinkage->getUseRotationFlag() && pElm->isKindOf(OdDgGraphicsElement::desc()) ) { OdDgGraphicsElementPtr pGrElm = pElm; if( !pGrElm->get3dFormatFlag() ) { OdGeMatrix2d matRotation; pPaternLinkage->getRotation2d(matRotation); OdGeVector2d vrX = OdGeVector2d::kXAxis; vrX.rotateBy(dAngle); vrX.transformBy(matRotation); dAngle = OdGeVector2d::kXAxis.angleToCCW(vrX); } } OdDbHatch::HatchPatternType patType = OdDbHatch::kUserDefined; if (strHatchName == L"SOLID" || strHatchName == L"_SOLID") patType = OdDbHatch::kPreDefined; pHatch->setPattern(patType, strHatchName, dAngle, pPaternLinkage->getScale() * dSymbolScale, dwgHatch, ptBase ); bCorrectHatch = true; } } if( !bCorrectHatch ) { importSymbolPattern( pElm, pOwner ); } else if( !pSymbol->getViewIndependentFlag() ) { pHatch->setLinetype(OdDbObjectId(0)); if( uHatchColorIndex != OdDg::kColorByCell ) { setDwgColorByDgnIndex( pSymbol->database(), pHatch, uHatchColorIndex ); } } } else { pHatch->erase(true); } } //----------------------------------------------------------------------------------------- void importDwgBasedPattern( OdDbHatchPtr& pHatch, OdDgElement* pElm, const OdDgDWGHatchPatternPtr& pPaternLinkage, double dUORsToModelScale ) { pHatch->setHatchStyle( OdDbHatch::kNormal ); pHatch->setHatchObjectType( OdDbHatch::kHatchObject ); OdDgDWGHatchPattern::DWGHatch dwgHatch = pPaternLinkage->getHatch(); OdHatchPattern dwgPattern; for( OdUInt32 i = 0; i < dwgHatch.size(); i++ ) { OdHatchPatternLine patternLine; patternLine.m_basePoint = dwgHatch[i].m_throughPoint; patternLine.m_dLineAngle = dwgHatch[i].m_angle; patternLine.m_patternOffset = dwgHatch[i].m_offset.asVector(); for( OdUInt32 j = 0; j < dwgHatch[i].m_dashes.size(); j++ ) { patternLine.m_dashes.push_back(dwgHatch[i].m_dashes[j]); } patternLine.m_patternOffset.rotateBy( -patternLine.m_dLineAngle ); dwgPattern.push_back( patternLine ); } OdGePoint2d ptBase = getHatchSeedPoint( pElm, pPaternLinkage, pHatch, dUORsToModelScale ); OdString strHatchName = pPaternLinkage->getPatternName(); OdString repairedName; if( strHatchName.isEmpty() ) strHatchName = L"_USER"; else if( OdDbSymUtil::repairSymbolName(repairedName, strHatchName, pHatch->database() ) == eOk ) { if( !repairedName.isEmpty() ) strHatchName = repairedName; } OdDbHatch::HatchPatternType patType = OdDbHatch::kUserDefined; if (strHatchName == L"SOLID" || strHatchName == L"_SOLID") patType = OdDbHatch::kPreDefined; pHatch->setPattern(patType, strHatchName, 0.0, 1.0, dwgPattern, ptBase ); if (pHatch->evaluateHatch() != eOk) pHatch->erase(true); int iHatchLines = pHatch->numHatchLines(); if (iHatchLines > (int)(dwgPattern.size() * MAX_DWG_HATCH_LINES)) pHatch->erase(true); } //----------------------------------------------------------------------------------------- OdDbEntityPtr createHatchEntity( const OdGePoint3dArray& arrPts, bool b3dPoints, const OdGeVector3d vrBaseNormal) { if( arrPts.size() < 3 ) return OdDbEntityPtr(); bool bNormalIsCalculated = true; OdGeVector3d vNormal = vrBaseNormal; OdGeMatrix3d matrix = OdGeMatrix3d::kIdentity; if (!b3dPoints) { vNormal = OdGeVector3d::kZAxis; } else { if( !vNormal.isZeroLength() || geCalculateNormal(arrPts, &vNormal) == OdGe::kOk) { vNormal = odgiFaceNormal(arrPts.size(), arrPts.asArrayPtr()); if (vNormal.isCodirectionalTo(OdGeVector3d::kZAxis)) vNormal = OdGeVector3d::kZAxis; else matrix.setToWorldToPlane(vNormal); } else bNormalIsCalculated = false; } if( bNormalIsCalculated ) { OdDbHatchPtr pHatch = OdDbHatch::createObject(); pHatch->setNormal(vNormal); OdGePoint3d pnt = matrix * arrPts[0]; pHatch->setElevation(pnt.z); matrix.setTranslation(OdGeVector3d(0., 0., -pnt.z)); OdGePoint2dArray verts; OdGeDoubleArray bulges; for( OdUInt32 f = 0; f < arrPts.size(); ++f) { OdGePoint3d ptPos(matrix * arrPts[f]); ODA_ASSERT_ONCE(OdZero(ptPos.z / 2.)); verts.append(ptPos.convert2d()); bulges.append(0.0); } pHatch->appendLoop(OdDbHatch::kOutermost|OdDbHatch::kPolyline, verts, bulges); return pHatch; } return OdDbEntityPtr(); } //----------------------------------------------------------------------------------------- bool getLoopNormal( const OdDbObjectIdArray& arrElements, OdGeVector3d& vrNormal, bool b3dElement, OdDgHatchPattern* pPattern ) { bool bRet = false; for( OdUInt32 i = 0; i < arrElements.size(); i++ ) { OdDbObjectPtr pObject = arrElements[i].openObject( OdDb::kForRead ); if( !pObject.isNull() ) { if( pObject->isKindOf( OdDbCircle::desc() ) ) { OdDbCirclePtr pCircle = pObject; vrNormal = pCircle->normal(); bRet = true; } else if( pObject->isKindOf( OdDbEllipse::desc() ) ) { OdDbEllipsePtr pEllipse = pObject; vrNormal = pEllipse->normal(); bRet = true; } else if( pObject->isKindOf( OdDbArc::desc() ) ) { OdDbArcPtr pArc = pObject; vrNormal = pArc->normal(); bRet = true; } else if( pObject->isKindOf( OdDbPolyline::desc() ) ) { OdDbPolylinePtr pPLine = pObject; vrNormal = pPLine->normal(); bRet = true; } else if( pObject->isKindOf( OdDbHatch::desc() ) ) { OdDbHatchPtr pHatch = pObject; vrNormal = pHatch->normal(); bRet = true; } else if( pObject->isKindOf( OdDbRegion::desc() ) ) { OdDbRegionPtr pRegion = pObject; if( pRegion->getNormal( vrNormal ) == eOk ) { bRet = true; } } if( bRet ) { break; } } } if( bRet && pPattern ) { if( !b3dElement && vrNormal.isParallelTo(OdGeVector3d::kZAxis) ) vrNormal = OdGeVector3d::kZAxis; else { OdGeMatrix3d matrix; if (pPattern->getUseRotationFlag()) { matrix = pPattern->getRotation().getMatrix(); matrix.transposeIt(); } OdGeVector3d vrCheckZ = OdGeVector3d::kZAxis; vrCheckZ.transformBy(matrix); if (!vrCheckZ.isCodirectionalTo(vrNormal, 1e-5)) vrNormal *= -1; } } return bRet; } //----------------------------------------------------------------------------------------- OdGePoint3d getHatchPoint(const OdDbObjectIdArray& arrElements) { OdGePoint3d ptRet; for( OdUInt32 i = 0; i < arrElements.size(); i++ ) { OdDbEntityPtr pEnt = arrElements[i].openObject(OdDb::kForRead); if( pEnt->isKindOf(OdDbCurve::desc()) ) { OdDbCurvePtr pCurve = pEnt; if (pCurve->getStartPoint(ptRet) == eOk) { break; } } else if (pEnt->isKindOf(OdDbRegion::desc())) { OdDbRegionPtr pRegion = pEnt; OdGePlane plane; OdDb::Planarity planarity; if( pRegion->getPlane(plane, planarity) == eOk ) { ptRet = plane.pointOnPlane(); break; } } } return ptRet; } //----------------------------------------------------------------------------------------- OdDbEntityPtr createHatchEntity(const OdDbObjectIdArray& arrElements, bool bSplitContours, bool b3dPoints, OdDgHatchPattern* pPattern, const OdGeVector3d vrBaseNormal) { if (arrElements.isEmpty()) return OdDbEntityPtr(); OdDbHatchPtr pHatch = OdDbHatch::createObject(); OdGeVector3d vrNormal = vrBaseNormal; if (!b3dPoints) { vrNormal = OdGeVector3d::kZAxis; pHatch->setNormal(vrNormal); } else if ( !vrNormal.isZeroLength() || getLoopNormal(arrElements, vrNormal, b3dPoints, pPattern)) { pHatch->setNormal( vrNormal ); if( b3dPoints ) { OdGePoint3d ptBase = getHatchPoint(arrElements); OdGePlane hatchPlane(OdGePoint3d::kOrigin, vrNormal); OdGePoint3d ptElevation; hatchPlane.project(ptBase, vrNormal, ptElevation); double dElevation = ptElevation.distanceTo(ptBase); OdGeVector3d vrDir = ptBase - ptElevation; if (!vrDir.isCodirectionalTo(vrNormal)) dElevation *= -1; pHatch->setElevation(dElevation); } } if( bSplitContours ) { for( OdUInt32 i = 0; i < arrElements.size(); i++ ) { OdDbObjectIdArray arrTmp; arrTmp.push_back( arrElements[i] ); pHatch->appendLoop(OdDbHatch::kExternal, arrTmp); } } else { pHatch->appendLoop(OdDbHatch::kExternal, arrElements); pHatch->setAssociative( true ); pHatch->setAssocObjIdsAt( pHatch->numLoops() - 1, arrElements ); } return pHatch; } //----------------------------------------------------------------------------------------- void getHatchPatternNormal(OdDgGraphicsElement* pBase, OdGeVector3d& vrNormal) { if( !OdDgnImportContext::getActualViewFlags().getShowPatternsFlag() || !pBase || !pBase->get3dFormatFlag()) return; bool bImportGradient = false; OdDgGradientFill gradientFill; OdDgHatchPatternPtr pPaternLinkage; OdDgGraphicsElementPtr pBaseElement = pBase; OdDgElementId idOwner = pBase->ownerId(); if (!idOwner.isNull() && !OdDgnImportContext::getSkipPatternDrawFlag()) { OdDgElementPtr pOwner = idOwner.openObject(OdDg::kForRead); if (isCellHeaderElement(pOwner)) { OdDgGraphicsElementPtr pGrOwner = pOwner; OdDgHatchPatternPtr pHatchPattern = pGrOwner->getHatchPattern(); if (!pHatchPattern.isNull()) pPaternLinkage = pHatchPattern; } } if( pPaternLinkage.isNull() && !OdDgnImportContext::getSkipPatternDrawFlag() ) { OdDgHatchPatternPtr pHatchPattern = pBase->getHatchPattern(); if (!pHatchPattern.isNull()) pPaternLinkage = pHatchPattern; } if( !pPaternLinkage.isNull() && pPaternLinkage->getUseRotationFlag() ) { OdGeMatrix3d matrix = pPaternLinkage->getRotation().getMatrix(); matrix.transposeIt(); vrNormal = OdGeVector3d::kZAxis; vrNormal = vrNormal.transformBy(matrix); } else if( !pPaternLinkage.isNull() ) vrNormal = OdGeVector3d::kZAxis; } //----------------------------------------------------------------------------------------- void importPatterns( OdDgGraphicsElementPtr pShape, const OdGePoint3dArray& arrVertices, const OdDbObjectIdArray& arrElementIds, bool bUsePoints, OdDbBlockTableRecord* owner, bool bAssoc, OdDbObjectId idAssoc ) { if( !OdDgnImportContext::getActualViewFlags().getShowPatternsFlag() ) return; OdRxObjectPtrArray arrFillLinkages; OdArray arrPatterns; bool bImportGradient = false; OdDgGradientFill gradientFill; OdDgHatchPatternPtr pPaternLinkage; OdDgGraphicsElementPtr pBaseElement = pShape; OdDgElementId idOwner = pShape->ownerId(); if( !idOwner.isNull() && !OdDgnImportContext::getSkipPatternDrawFlag() ) { OdDgElementPtr pOwner = idOwner.openObject(OdDg::kForRead); if( isCellHeaderElement(pOwner) ) { OdDgGraphicsElementPtr pGrOwner = pOwner; OdDgHatchPatternPtr pHatchPattern = pGrOwner->getHatchPattern(); if( !pHatchPattern.isNull() ) arrPatterns.push_back(pHatchPattern); } if( arrPatterns.size() > 0 ) { pBaseElement = pOwner; } } if( pShape->getFillType() == OdDg::kGradientFill ) { bImportGradient = true; gradientFill = pShape->getGradientFill(); } if( (arrPatterns.size() == 0) && !OdDgnImportContext::getSkipPatternDrawFlag() ) { if( pShape->isKindOf(OdDgMultiline::desc()) ) { OdDgMultilinePtr pMLine = pShape; for( OdUInt32 l = 0; l < pMLine->getHatchPatternCount(); l++ ) { OdDgHatchPatternPtr pHatchPattern = pMLine->getHatchPattern(l); if( !pHatchPattern.isNull() ) arrPatterns.push_back(pHatchPattern); } } else { OdDgHatchPatternPtr pHatchPattern = pShape->getHatchPattern(); if( !pHatchPattern.isNull() ) arrPatterns.push_back(pHatchPattern); } } for( OdUInt32 j = 0; j < arrPatterns.size(); j++ ) { if( arrPatterns[j]->getType() != OdDgHatchPattern::kProxyPattern ) { pPaternLinkage = arrPatterns[j]; break; } } if( bImportGradient || !pPaternLinkage.isNull() ) { double dUORsToModelScale = 1.0; OdDgElementId idDgOwner = pShape->ownerId(); while( !idDgOwner.isNull() ) { OdDgElementPtr pDgElm = idDgOwner.openObject(OdDg::kForRead); if( pDgElm->isKindOf(OdDgModel::desc()) ) { OdDgModelPtr pModel = pDgElm; if( !pModel.isNull() ) { dUORsToModelScale = pModel->convertUORsToWorkingUnits(1.0); break; } } idDgOwner = pDgElm->ownerId(); } OdDbHatchPtr pHatch; OdGeVector3d vrBaseNormal = OdGeVector3d::kIdentity; if (!pPaternLinkage.isNull() && pPaternLinkage->getUseRotationFlag() ) { OdGeMatrix3d matrix = pPaternLinkage->getRotation().getMatrix(); matrix.transposeIt(); vrBaseNormal = OdGeVector3d::kZAxis; vrBaseNormal = vrBaseNormal.transformBy(matrix); } else if (!pPaternLinkage.isNull()) vrBaseNormal = OdGeVector3d::kZAxis; if( bUsePoints ) { pHatch = createHatchEntity( arrVertices, pShape->get3dFormatFlag(), vrBaseNormal); if( !pHatch.isNull() && !arrElementIds.isEmpty() ) { pHatch->setAssociative(true); pHatch->setAssocObjIdsAt( 0, arrElementIds ); } } else { pHatch = createHatchEntity( arrElementIds, false, pShape->get3dFormatFlag(), pPaternLinkage, vrBaseNormal); } if( !pHatch.isNull() ) { owner->appendOdDbEntity(pHatch); } else { return; } if( bAssoc && !idAssoc.isNull() ) { pHatch->setAssociative( true ); OdDbObjectIdArray arrIds; arrIds.push_back( idAssoc ); pHatch->setAssocObjIdsAt( 0, arrIds ); } if( bImportGradient ) { copyEntityProperties( pShape.get(), pHatch ); importGradient( pHatch, gradientFill ); // if( bAssoc && !idAssoc.isNull() ) // { // OdDbEntityPtr pEnt = idAssoc.openObject(OdDb::kForWrite); // // if( !pEnt.isNull() ) // { // pEnt->setVisibility( OdDb::kInvisible ); // } // } pHatch = 0; } else { copyEntityProperties( pBaseElement.get(), pHatch ); } if( !pPaternLinkage.isNull() && pHatch.isNull() ) { OdGeVector3d vrBaseNormal = OdGeVector3d::kIdentity; if (!pPaternLinkage.isNull() && pPaternLinkage->getUseRotationFlag() ) { OdGeMatrix3d matrix = pPaternLinkage->getRotation().getMatrix(); matrix.transposeIt(); vrBaseNormal = OdGeVector3d::kZAxis; vrBaseNormal = vrBaseNormal.transformBy(matrix); } else if (!pPaternLinkage.isNull()) vrBaseNormal = OdGeVector3d::kZAxis; if( bUsePoints ) { pHatch = createHatchEntity( arrVertices, pShape->get3dFormatFlag(), vrBaseNormal); } else { pHatch = createHatchEntity( arrElementIds, false, pShape->get3dFormatFlag(), pPaternLinkage, vrBaseNormal); } owner->appendOdDbEntity(pHatch); if( bAssoc && !idAssoc.isNull() ) { pHatch->setAssociative( true ); OdDbObjectIdArray arrIds; arrIds.push_back( idAssoc ); pHatch->setAssocObjIdsAt( 0, arrIds ); } copyEntityProperties( pBaseElement.get(), pHatch ); } if( !pPaternLinkage.isNull() && pPaternLinkage->isKindOf( OdDgLinearHatchPattern::desc()) ) { importLinearPattern( pHatch, pShape, pPaternLinkage, dUORsToModelScale ); } else if( !pPaternLinkage.isNull() && pPaternLinkage->isKindOf( OdDgCrossHatchPattern::desc()) ) { importCrossPattern( pHatch, pShape, pPaternLinkage, dUORsToModelScale ); } else if( !pPaternLinkage.isNull() && pPaternLinkage->isKindOf( OdDgDWGHatchPattern::desc()) ) { importDwgBasedPattern( pHatch, pShape, pPaternLinkage, dUORsToModelScale ); } else if( !pPaternLinkage.isNull() && pPaternLinkage->isKindOf( OdDgSymbolHatchPattern::desc()) ) { importSymbolPattern( pHatch, pShape, pPaternLinkage, dUORsToModelScale, owner ); //importSymbolPattern( pBaseElement, owner ); //pHatch->erase(true); } else if( !pHatch.isNull() ) { pHatch->erase(true); } } } //-------------------------------------------------------------------------------------------------------------- OdResult getAnyPoint(OdDgElement* e, OdGePoint3d& ptHatch) { OdResult retVal = eInvalidInput; if (e->isKindOf(OdDgCurveElement3d::desc())) { OdDgCurveElement3dPtr pCurve3d = e; retVal = pCurve3d->getStartPoint(ptHatch); } return retVal; } //-------------------------------------------------------------------------------------------------------------- void setHatchElevation(OdDbHatchPtr& pHatch, OdDgElement* e) { OdGePlane hatchPlane; OdDb::Planarity hatchPlanarity; if( (pHatch->getPlane(hatchPlane, hatchPlanarity) == eOk) && (hatchPlanarity != OdDb::kNonPlanar) ) { OdGePoint3d ptDgHatch; if( getAnyPoint(e, ptDgHatch) == eOk ) { OdGePoint3d ptDbHatch = ptDgHatch.project(hatchPlane, hatchPlane.normal()); OdGeVector3d vrElevation = ptDgHatch - ptDbHatch; if( !vrElevation.isZeroLength() ) { if( vrElevation.isCodirectionalTo(hatchPlane.normal())) pHatch->setElevation(vrElevation.length()); else pHatch->setElevation(-vrElevation.length()); } } } } //-------------------------------------------------------------------------------------------------------------- double calculateCurveTolerance(OdDbCurve* pCurve) { OdGeExtents3d extCurve; pCurve->getGeomExtents(extCurve); double dTolerance = extCurve.diagonal().length() / 3000; if( pCurve->isKindOf(OdDbPolyline::desc()) ) { double dTolerance = 1e10; OdDbPolylinePtr pPolyline = pCurve; OdGePoint2d ptStart; OdGePoint2d ptEnd; double dBulge = 0; for( OdUInt32 i = 0; i < pPolyline->numVerts() - 1; i++ ) { pPolyline->getPointAt(i, ptStart); pPolyline->getPointAt(i+1, ptEnd); dBulge = pPolyline->getBulgeAt(i); if( !OdZero(dBulge) ) { OdGeCircArc3d arc; pPolyline->getArcSegAt(i, arc); double dArcTol = arc.length() / 20; if (dArcTol < dTolerance) dTolerance = dArcTol; } } } return dTolerance; } //-------------------------------------------------------------------------------------------------------------- OdGePoint3dArray getWipeoutBoundary(OdDbEntity* dbEll) { OdGePoint3dArray retVal; if( dbEll && dbEll->isKindOf(OdDbCurve::desc()) ) { OdDbCurvePtr pCurve = dbEll; double dTolerance = calculateCurveTolerance(pCurve); OdGeCurve3d* pGeCurve = NULL; pCurve->getOdGeCurve(pGeCurve, dTolerance); if( pGeCurve ) { OdGeInterval curveInterval; pGeCurve->getInterval(curveInterval); pGeCurve->getSamplePoints(&curveInterval, dTolerance, retVal); delete pGeCurve; } } return retVal; } //-------------------------------------------------------------------------------------------------------------- void importClosedElementFill( OdDgElement* e, OdDbEntity* dbEll, OdDbBlockTableRecord* owner ) { bool bUseFillColor = false; OdUInt32 uFillColorIndex = 0; if( e->isKindOf(OdDgGraphicsElement::desc()) ) { OdDgGraphicsElementPtr pGrElm = e; if( pGrElm->getFillType() == OdDg::kFillColor ) { bUseFillColor = true; uFillColorIndex = getDgnElementColorIndex(pGrElm->getFillColorIndex(), pGrElm->getLevelId()); } } if( !OdDgnImportContext::getActualViewFlags().getShowFillsFlag() ) bUseFillColor = false; OdDbObjectIdArray arrHatchItems; arrHatchItems.push_back( dbEll->id() ); if( bUseFillColor ) // Create solid hatch { OdDbWipeoutPtr pWipeout; if( uFillColorIndex == 255 ) { pWipeout = OdDbWipeout::createObject(); owner->appendOdDbEntity(pWipeout); OdGePoint3dArray arrBoundary = getWipeoutBoundary(dbEll); if (!arrBoundary.isEmpty() && !pWipeout.isNull()) { pWipeout->setBoundary(arrBoundary); if (e->isKindOf(OdDgGraphicsElement::desc())) { OdDgGraphicsElement* pGrElement = dynamic_cast(e); if (pGrElement) copyEntityProperties(pGrElement, pWipeout); } pWipeout->swapIdWith(dbEll->id(), true, true); arrHatchItems.clear(); arrHatchItems.push_back(dbEll->id()); dbEll->erase(true); } else pWipeout = NULL; } if( pWipeout.isNull() ) { OdDbHatchPtr pHatch = OdDbHatch::createObject(); owner->appendOdDbEntity(pHatch); try { OdGeVector3d vrNormal = OdGeVector3d::kZAxis; if (getLoopNormal(arrHatchItems, vrNormal, true, NULL)) { pHatch->setNormal(vrNormal); } pHatch->appendLoop(OdDbHatch::kExternal, arrHatchItems); pHatch->setPattern(OdDbHatch::kPreDefined, L"SOLID"); if (!pHatch.isNull()) { setHatchElevation(pHatch, e); if (e->isKindOf(OdDgGraphicsElement::desc())) { OdDgGraphicsElement* pGrElement = dynamic_cast(e); if (pGrElement) { copyEntityProperties(pGrElement, pHatch); } } setDwgColorByDgnIndex(e->database(), pHatch, uFillColorIndex); } pHatch->swapIdWith(dbEll->id(), true, true); arrHatchItems.clear(); arrHatchItems.push_back(dbEll->id()); pHatch->setAssociative(true); pHatch->setAssocObjIdsAt(0, arrHatchItems); } catch (...) { pHatch->erase(); } } } OdGePoint3dArray arrPoints; importPatterns( e, arrPoints, arrHatchItems, false, owner, true, dbEll->id() ); } }