/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2019, 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-2019 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #ifndef __ODGISECTIONGEOMETRYOUTPUT_H__ #define __ODGISECTIONGEOMETRYOUTPUT_H__ #include "Gi/GiConveyorPassingImpl.h" #include "Gi/GiDummyGeometry.h" #include "TD_PackPush.h" // Forward declarations class OdGiClippedGeometryOutput; /** \details This class provides default callback functionality for OdGiClippedGeometryOutput interface. */ class ODGI_EXPORT OdGiClippedGeometryOutputCallback : public OdRxObject { public: OdGiClippedGeometryOutputCallback() { } /** details This callback method will be called for each sectionable object. \param pGeomOutput [in] Current geometry output for reconfiguration. \param pVp [in] Current vectorization context state. \remarks Return true to process upcoming geometry or false to disable geometry processing output. */ virtual bool clippedGeometryOutputCallbackProc(OdGiClippedGeometryOutput &pGeomOutput, const OdGiConveyorContext &pDrawContext) = 0; }; /** \details This template class is a specialization of the OdSmartPtr class for OdGiClippedGeometryOutputCallback object pointers. */ typedef OdSmartPtr OdGiClippedGeometryOutputCallbackPtr; /** \details This class is an default implementation of OdGiConveyorGeometry that provides generic output of clipped geometry. */ class ODGI_EXPORT OdGiClippedGeometryOutput : public OdRxObject, public OdGiConveyorPassingImpl { public: /** \details This class provides data for OdGiClippedGeometryOutput and inherited classes. */ struct ODGI_EXPORT ClippedGeometryOutputInterface { /** \details Returns destination geometry interface. */ virtual OdGiConveyorGeometry &destinationGeometry() = 0; /** \details Returns conveyor context interface. */ virtual OdGiConveyorContext &conveyorContext() = 0; }; protected: enum Flags { kProcessingEnabled = 1, kNonSectionableGeometryClip = 2, kLastGenericFlag = kNonSectionableGeometryClip }; protected: ClippedGeometryOutputInterface *m_pIface; // Conveyor geometry output interface. OdGiClippedGeometryOutputCallbackPtr m_pDrawCallback; // Optional drawable callback. OdUInt32 m_flags; // Generic flags storage. OdUInt32 m_overrideFlags; // Traits override flags storage. OdGiSubEntityTraitsData m_overrides; // Traits override values. OdGiSubEntityTraitsData m_traits; // Actual traits storage. public: OdGiConveyorGeometry& destGeometry() { if (!m_pIface) throw OdError(eInvalidContext); return m_pIface->destinationGeometry(); } OdGiConveyorContext& drawContext() { if (!m_pIface) throw OdError(eInvalidContext); return m_pIface->conveyorContext(); } protected: class WrapTraitsProc { OdGiClippedGeometryOutput &m_this; OdGiConveyorContext &m_drawContext; public: WrapTraitsProc(OdGiClippedGeometryOutput *pThis) : m_this(*pThis), m_drawContext(pThis->drawContext()) { m_this.setupTraits(m_drawContext); } ~WrapTraitsProc() { m_this.releaseTraits(m_drawContext); } }; public: OdGiClippedGeometryOutput() : m_pIface(NULL), m_flags(kProcessingEnabled | kNonSectionableGeometryClip), m_overrideFlags(0) {} /** details Copies the contents of the specified object into this object. /remarks If you create nested class, based onto OdGiClippedGeometryOutput, you should implement this method override, elsewhere it will not support multithreaded regeneration. */ virtual void copyFrom(const OdRxObject* pSource) { const OdGiClippedGeometryOutput *pFrom = static_cast(pSource); if (!pFrom) throw OdError(eInvalidInput); m_pDrawCallback = pFrom->m_pDrawCallback; m_flags = pFrom->m_flags; m_overrideFlags = pFrom->m_overrideFlags; m_overrides = pFrom->m_overrides; } /** \details Returns conveyor geometry output interface. */ ClippedGeometryOutputInterface *getInterface() { return m_pIface; } /** \details Sets conveyor geometry output interface. \param pInterface [in] Pointer onto conveyor geometry output interface. \remarks Called internally by OdGiOrthoClipperEx conveyor node. */ void setInterface(ClippedGeometryOutputInterface *pInterface) { m_pIface = pInterface; } /** \details Returns geometry output callback interface. \remarks Called internally by OdGiOrthoClipperEx conveyor node. */ OdGiClippedGeometryOutputCallback *geometryProcessingCallback() { return m_pDrawCallback; } /** \details Setup geometry output callback interface. \param pCallback [in] Geometry output callback interface pointer. */ void setGeometryProcessingCallback(OdGiClippedGeometryOutputCallback *pCallback) { m_pDrawCallback = pCallback; } /** \details Returns true if processing of this geometry output is enabled. */ bool isProcessingEnabled() const { return GETBIT(m_flags, kProcessingEnabled); } /** \details Enables or disables processing of this geometry output. \param bSet [in] New processing state for this geometry output. */ void setProcessingEnabled(bool bSet) { SETBIT(m_flags, kProcessingEnabled, bSet); } /** \details Returns true if clipping of non-sectionable geometry enabled. */ bool isNonSectionableGeometryClipping() const { return GETBIT(m_flags, kNonSectionableGeometryClip); } /** \details Enables or disables clipping of non-sectionable geometry. \param bSet [in] New state of non-sectionable geometry clipping. */ void setNonSectionableGeometryClipping(bool bSet) { SETBIT(m_flags, kNonSectionableGeometryClip, bSet); } /** \details Setup traits override flags. \param nFlags [in] Traits override flags. */ void setTraitsOverrideFlags(OdUInt32 nFlags) { m_overrideFlags = nFlags; } /** \details Returns traits override flags. */ OdUInt32 traitsOverrideFlags() const { return m_overrideFlags; } /** \details Setup traits overrides. \param pData [in] Traits overrides. */ void setTraitsOverrides(const OdGiSubEntityTraitsData &pData) { m_overrides = pData; } /** \details Returns traits overrides (for changing). */ OdGiSubEntityTraitsData &traitsOverrides() { return m_overrides; } /** \details Returns traits overrides. */ const OdGiSubEntityTraitsData &traitsOverrides() const { return m_overrides; } /** \details Called by vectorizer to setup geometry output configuration for current conveyor drawable and state. \remarks Override to implement own settings processing. */ virtual void setupDrawableProcessing() { if (!m_pDrawCallback.isNull()) setProcessingEnabled(m_pDrawCallback->clippedGeometryOutputCallbackProc(*this, drawContext())); } /** \details Called to setup output geometry traits. \param context [in] Geometry conveyor context. \remarks Override to implement own traits processing. */ virtual void setupTraits(OdGiConveyorContext &context) { if (m_overrideFlags) { // Copy traits settings from current state OdGiSubEntityTraitsToData dataAdaptor(m_traits); OdGiSubEntityTraitsToData::copyTraits(context.subEntityTraits(), dataAdaptor, m_overrideFlags); // Setup traits overrides dataAdaptor.setTraits(m_overrides); OdGiSubEntityTraitsToData::copyTraits(dataAdaptor, context.subEntityTraits(), m_overrideFlags); context.onTraitsModified(); } } /** \details Called to release output geometry traits. \param context [in] Geometry conveyor context. \remarks Override to implement own traits processing. */ virtual void releaseTraits(OdGiConveyorContext &context) { if (m_overrideFlags) { // Copy modified traits back to current state OdGiSubEntityTraitsToData dataAdaptor(m_traits); OdGiSubEntityTraitsToData::copyTraits(dataAdaptor, context.subEntityTraits(), m_overrideFlags); //context.onTraitsModified(); // Don't need since we completed with section geometry } } // Conveyor geometry primitives implementation void plineProc(const OdGiPolyline& polyline, const OdGeMatrix3d* pXfm = 0, OdUInt32 fromIndex = 0, OdUInt32 numSegs = 0) { WrapTraitsProc _wtp(this); destGeometry().plineProc(polyline, pXfm, fromIndex, numSegs); } void polylineProc(OdInt32 numPoints, const OdGePoint3d* vertexList, const OdGeVector3d* pNormal = 0, const OdGeVector3d* pExtrusion = 0, OdGsMarker baseSubEntMarker = -1) { WrapTraitsProc _wtp(this); destGeometry().polylineProc(numPoints, vertexList, pNormal, pExtrusion, baseSubEntMarker); } void polygonProc(OdInt32 numPoints, const OdGePoint3d* vertexList, const OdGeVector3d* pNormal = 0, const OdGeVector3d* pExtrusion = 0) { WrapTraitsProc _wtp(this); destGeometry().polygonProc(numPoints, vertexList, pNormal, pExtrusion); } void xlineProc(const OdGePoint3d& firstPoint, const OdGePoint3d& secondPoint) { WrapTraitsProc _wtp(this); destGeometry().xlineProc(firstPoint, secondPoint); } void rayProc(const OdGePoint3d& basePoint, const OdGePoint3d& throughPoint) { WrapTraitsProc _wtp(this); destGeometry().rayProc(basePoint, throughPoint); } void meshProc(OdInt32 numRows, OdInt32 numColumns, const OdGePoint3d* vertexList, const OdGiEdgeData* pEdgeData = 0, const OdGiFaceData* pFaceData = 0, const OdGiVertexData* pVertexData = 0) { WrapTraitsProc _wtp(this); destGeometry().meshProc(numRows, numColumns, vertexList, pEdgeData, pFaceData, pVertexData); } void shellProc(OdInt32 numVertices, const OdGePoint3d* vertexList, OdInt32 faceListSize, const OdInt32* faceList, const OdGiEdgeData* pEdgeData = 0, const OdGiFaceData* pFaceData = 0, const OdGiVertexData* pVertexData = 0) { WrapTraitsProc _wtp(this); destGeometry().shellProc(numVertices, vertexList, faceListSize, faceList, pEdgeData, pFaceData, pVertexData); } void circleProc(const OdGePoint3d& center, double radius, const OdGeVector3d& normal, const OdGeVector3d* pExtrusion = 0) { WrapTraitsProc _wtp(this); destGeometry().circleProc(center, radius, normal, pExtrusion); } void circleProc2(const OdGePoint3d& center, double radius, const OdGeVector3d& normal, const OdGeVector3d& startVector, const OdGeVector3d* pExtrusion = 0) { WrapTraitsProc _wtp(this); destGeometry().circleProc2(center, radius, normal, startVector, pExtrusion); } void circleProc(const OdGePoint3d& firstPoint, const OdGePoint3d& secondPoint, const OdGePoint3d& thirdPoint, const OdGeVector3d* pExtrusion = 0) { WrapTraitsProc _wtp(this); destGeometry().circleProc(firstPoint, secondPoint, thirdPoint, pExtrusion); } void circularArcProc(const OdGePoint3d& center, double radius, const OdGeVector3d& normal, const OdGeVector3d& startVector, double sweepAngle, OdGiArcType arcType = kOdGiArcSimple, const OdGeVector3d* pExtrusion = 0) { WrapTraitsProc _wtp(this); destGeometry().circularArcProc(center, radius, normal, startVector, sweepAngle, arcType, pExtrusion); } void circularArcProc(const OdGePoint3d& firstPoint, const OdGePoint3d& secondPoint, const OdGePoint3d& thirdPoint, OdGiArcType arcType = kOdGiArcSimple, const OdGeVector3d* pExtrusion = 0) { WrapTraitsProc _wtp(this); destGeometry().circularArcProc(firstPoint, secondPoint, thirdPoint, arcType, pExtrusion); } void ellipArcProc(const OdGeEllipArc3d& ellipArc, const OdGePoint3d* endPointOverrides = 0, OdGiArcType arcType = kOdGiArcSimple, const OdGeVector3d* pExtrusion = 0) { WrapTraitsProc _wtp(this); destGeometry().ellipArcProc(ellipArc, endPointOverrides, arcType, pExtrusion); } void nurbsProc(const OdGeNurbCurve3d& nurbsCurve) { WrapTraitsProc _wtp(this); destGeometry().nurbsProc(nurbsCurve); } void textProc(const OdGePoint3d& position, const OdGeVector3d& direction, const OdGeVector3d& upVector, const OdChar* msg, OdInt32 numBytes, bool raw, const OdGiTextStyle* pTextStyle, const OdGeVector3d* pExtrusion = 0) { WrapTraitsProc _wtp(this); destGeometry().textProc(position, direction, upVector, msg, numBytes, raw, pTextStyle, pExtrusion); } void textProc2(const OdGePoint3d& position, const OdGeVector3d& direction, const OdGeVector3d& upVector, const OdChar* msg, OdInt32 numBytes, bool raw, const OdGiTextStyle* pTextStyle, const OdGeVector3d* pExtrusion = 0, const OdGeExtents3d* extentsBox = 0) { WrapTraitsProc _wtp(this); destGeometry().textProc2(position, direction, upVector, msg, numBytes, raw, pTextStyle, pExtrusion, extentsBox); } void shapeProc(const OdGePoint3d& position, const OdGeVector3d& direction, const OdGeVector3d& upVector, int shapeNumber, const OdGiTextStyle* pTextStyle, const OdGeVector3d* pExtrusion = 0) { WrapTraitsProc _wtp(this); destGeometry().shapeProc(position, direction, upVector, shapeNumber, pTextStyle, pExtrusion); } void rasterImageProc(const OdGePoint3d& origin, const OdGeVector3d& u, const OdGeVector3d& v, const OdGiRasterImage* pImage, const OdGePoint2d* uvBoundary, OdUInt32 numBoundPts, bool transparency = false, double brightness = 50.0, double contrast = 50.0, double fade = 0.0) { WrapTraitsProc _wtp(this); destGeometry().rasterImageProc(origin, u, v, pImage, uvBoundary, numBoundPts, transparency, brightness, contrast, fade); } void metafileProc(const OdGePoint3d& origin, const OdGeVector3d& u, const OdGeVector3d& v, const OdGiMetafile* pMetafile, bool dcAligned = true, bool allowClipping = false) { WrapTraitsProc _wtp(this); destGeometry().metafileProc(origin, u, v, pMetafile, dcAligned, allowClipping); } void xlineProc2(const OdGePoint3d& basePoint, const OdGeVector3d& direction) { WrapTraitsProc _wtp(this); destGeometry().xlineProc2(basePoint, direction); } void rayProc2(const OdGePoint3d& basePoint, const OdGeVector3d& direction) { WrapTraitsProc _wtp(this); destGeometry().rayProc2(basePoint, direction); } void ttfPolyDrawProc(OdInt32 numVertices, const OdGePoint3d* vertexList, OdInt32 faceListSize, const OdInt32* faceList, const OdUInt8* pBezierTypes, const OdGiFaceData* pFaceData = 0) { WrapTraitsProc _wtp(this); destGeometry().ttfPolyDrawProc(numVertices, vertexList, faceListSize, faceList, pBezierTypes, pFaceData); } void polypointProc(OdInt32 numPoints, const OdGePoint3d* vertexList, const OdCmEntityColor* pColors, const OdCmTransparency* pTransparency = 0, const OdGeVector3d* pNormals = 0, const OdGeVector3d* pExtrusions = 0, const OdGsMarker* pSubEntMarkers = 0, OdInt32 nPointSize = 0) { WrapTraitsProc _wtp(this); destGeometry().polypointProc(numPoints, vertexList, pColors, pTransparency, pNormals, pExtrusions, pSubEntMarkers, nPointSize); } void rowOfDotsProc(OdInt32 numPoints, const OdGePoint3d& startPoint, const OdGeVector3d& dirToNextPoint) { WrapTraitsProc _wtp(this); destGeometry().rowOfDotsProc(numPoints, startPoint, dirToNextPoint); } void edgeProc(const OdGiEdge2dArray& edges, const OdGeMatrix3d* pXform = 0) { WrapTraitsProc _wtp(this); destGeometry().edgeProc(edges, pXform); } }; /** \details This template class is a specialization of the OdSmartPtr class for OdGiClippedGeometryOutput object pointers. */ typedef OdSmartPtr OdGiClippedGeometryOutputPtr; /** \details This class is an default implementation of OdGiConveyorGeometry that provides output of section geometry. */ class ODGI_EXPORT OdGiSectionGeometryOutput : public OdGiClippedGeometryOutput { protected: enum Flags { kOutputClosedPrimitives = kLastGenericFlag << 1, kOutputOpenedPrimitives = kLastGenericFlag << 2, kClosedPrimitivesAsPolylines = kLastGenericFlag << 3, kToleranceOverrideEnabled = kLastGenericFlag << 4 }; protected: double m_tolOverride; // Section tolerance override. OdGePoint3dArray m_tmpPoints; // Temporary vertexes array public: OdGiSectionGeometryOutput() : m_tolOverride(1.e-10) { SETBIT_1(m_flags, kOutputClosedPrimitives); } ODRX_DECLARE_MEMBERS(OdGiSectionGeometryOutput); /** details Copies the contents of the specified object into this object. /remarks If you create nested class, based onto OdGiSectionGeometryOutput, you should implement this method override, elsewhere it will not support multithreaded regeneration. */ virtual void copyFrom(const OdRxObject* pSource) { const OdGiSectionGeometryOutput *pFrom = OdGiSectionGeometryOutput::cast(pSource); if (!pFrom) throw OdError(eInvalidInput); OdGiClippedGeometryOutput::copyFrom(pSource); m_tolOverride = pFrom->m_tolOverride; } /** \details Returns true if closed sections output enabled. */ bool isClosedSectionsOutputEnabled() const { return GETBIT(m_flags, kOutputClosedPrimitives); } /** \details Enables or disables closed sections output. \param bSet [in] New state of closed sections output. */ void enableClosedSectionsOutput(bool bSet) { SETBIT(m_flags, kOutputClosedPrimitives, bSet); } /** \details Returns true if opened sections output enabled. */ bool isOpenedSectionsOutputEnabled() const { return GETBIT(m_flags, kOutputOpenedPrimitives); } /** \details Enables or disables opened sections output. \param bSet [in] New state of opened sections output. */ void enableOpenedSectionsOutput(bool bSet) { SETBIT(m_flags, kOutputOpenedPrimitives, bSet); } /** \details Returns true if enabled output of closed sections as polyline primitives. */ bool isOutputOfClosedSectionsAsPolylinesEnabled() const { return GETBIT(m_flags, kClosedPrimitivesAsPolylines); } /** \details Enables or disables output of closed sections as polyline primitives. \param bSet [in] New state of closed sections output mode. */ void enableOutputOfClosedSectionsAsPolylines(bool bSet) { SETBIT(m_flags, kClosedPrimitivesAsPolylines, bSet); } /** \details Returns true if sections generation tolerance override enabled. */ bool isSectionToleranceOverrideEnabled() const { return GETBIT(m_flags, kToleranceOverrideEnabled); } /** \details Returns sections generation tolerance override value. */ double sectionToleranceOverride() const { return m_tolOverride; } /** \details Enables sections generation tolerance override and sets it's value. */ void setSectionToleranceOverride(double tolOverride) { SETBIT_1(m_flags, kToleranceOverrideEnabled); m_tolOverride = tolOverride; } /** \details Disables sections generation tolerance override. */ void resetSectionToleranceOverride() { SETBIT_0(m_flags, kToleranceOverrideEnabled); } /** \details Called for opened sections. \remarks Redirects to destination geometry in default implementation. */ void polylineProc(OdInt32 numPoints, const OdGePoint3d* vertexList, const OdGeVector3d* pNormal = 0, const OdGeVector3d* pExtrusion = 0, OdGsMarker baseSubEntMarker = -1) { OdGiClippedGeometryOutput::polylineProc(numPoints, vertexList, pNormal, pExtrusion, baseSubEntMarker); } /** \details Called for closed sections. \remarks Redirects to destination geometry in default implementation. */ void shellProc(OdInt32 numVertices, const OdGePoint3d* vertexList, OdInt32 faceListSize, const OdInt32* faceList, const OdGiEdgeData* pEdgeData = 0, const OdGiFaceData* pFaceData = 0, const OdGiVertexData* pVertexData = 0) { WrapTraitsProc _wtp(this); if (!isOutputOfClosedSectionsAsPolylinesEnabled()) destGeometry().shellProc(numVertices, vertexList, faceListSize, faceList, pEdgeData, pFaceData, pVertexData); else shellProcAsPolylineProc(numVertices, vertexList, faceListSize, faceList, pEdgeData, pFaceData, pVertexData); } protected: void shellProcAsPolylineProc(OdInt32 /*numVertices*/, const OdGePoint3d* vertexList, OdInt32 faceListSize, const OdInt32* faceList, const OdGiEdgeData* /*pEdgeData*/, const OdGiFaceData* pFaceData, const OdGiVertexData* /*pVertexData*/) { OdInt32 nFace = 0, nFaceList = 0; OdGeVector3d extrusion; const bool bExtrusion = OdNonZero(drawContext().subEntityTraits().thickness()); while (nFaceList < faceListSize) { const OdInt32 numVerts = Od_abs(faceList[nFaceList++]); const OdGeVector3d *pNormal = (pFaceData && pFaceData->normals()) ? (pFaceData->normals() + nFace) : NULL; if (pNormal && bExtrusion) extrusion = *pNormal * drawContext().subEntityTraits().thickness(); m_tmpPoints.resize(numVerts + 1); OdGePoint3d *tmpPoints = m_tmpPoints.asArrayPtr(); for (OdInt32 nVert = 0; nVert < numVerts; nVert++) tmpPoints[nVert] = vertexList[faceList[nFaceList++]]; tmpPoints[numVerts] = tmpPoints[0]; destGeometry().polylineProc(numVerts + 1, tmpPoints, pNormal, (pNormal && bExtrusion) ? &extrusion : NULL); nFace++; } } }; /** \details This template class is a specialization of the OdSmartPtr class for OdGiSectionGeometryOutput object pointers. */ typedef OdSmartPtr OdGiSectionGeometryOutputPtr; /** \details This class is an default implementation of OdGiConveyorGeometry that provides output of section geometry. */ class ODGI_EXPORT OdGiCuttedGeometryOutput : public OdGiClippedGeometryOutput { public: OdGiCuttedGeometryOutput() { } ODRX_DECLARE_MEMBERS(OdGiCuttedGeometryOutput); /** details Copies the contents of the specified object into this object. /remarks If you create nested class, based onto OdGiSectionGeometryOutput, you should implement this method override, elsewhere it will not support multithreaded regeneration. */ virtual void copyFrom(const OdRxObject* pSource) { const OdGiCuttedGeometryOutput *pFrom = OdGiCuttedGeometryOutput::cast(pSource); if (!pFrom) throw OdError(eInvalidInput); OdGiClippedGeometryOutput::copyFrom(pSource); } }; /** \details This template class is a specialization of the OdSmartPtr class for OdGiCuttedGeometryOutput object pointers. */ typedef OdSmartPtr OdGiCuttedGeometryOutputPtr; #include "TD_PackPop.h" #endif //#ifndef __ODGISECTIONGEOMETRYOUTPUT_H__