// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause /** * @class vtkTrimmedExtrusionFilter * @brief extrude polygonal data trimmed by a second input surface * * vtkTrimmedExtrusionFilter is a modeling filter. It takes polygonal data as * input and generates polygonal data on output. The input dataset is swept * along a specified direction forming a "skirt" from the boundary edges 2D * primitives (i.e., edges used by only one polygon); and/or from vertices * and lines. The extent of the sweeping is limited by a second input: * defined where the sweep intersects a user-specified surface. * * Capping of the extrusion can be enabled. In this case the input, * generating primitive is copied inplace as well as to the end of the * extrusion skirt. (See warnings below on what happens if the intersecting * sweep does not intersect, or partially intersects the trim surface.) * * Note that this filter operates in two fundamentally different modes based * on the extrusion strategy. If the strategy is BOUNDARY_EDGES, then only the * boundary edges of the input's 2D primitives are extruded (verts and lines * are extruded to generate lines and quads). However, if the extrusions * strategy is ALL_EDGES, then every edge of the 2D primitives is used to * sweep out a quadrilateral polygon (again verts and lines are swept to * produce lines and quads). * * @warning * The extrusion direction is assumed to define an infinite line. The * intersection with the trim surface is along a ray from the - to + * direction, however only the first intersection is taken. * * @warning * Some polygonal objects have no free edges (e.g., sphere). When swept, this * will result in two separate surfaces if capping is on and BOUNDARY_EDGES * enabled, or no surface if capping is off and BOUNDARY_EDGES is enabled. * * @warning * If all the extrusion lines emanating from an extruding primitive do not * intersect the trim surface, then no output for that primitive will be * generated. In extreme cases, it is possible that no output whatsoever will * be generated by the filter. * * @warning * This class has been threaded with vtkSMPTools. Using TBB or other * non-sequential type (set in the CMake variable * VTK_SMP_IMPLEMENTATION_TYPE) may improve performance significantly. * * @sa * vtkLinearExtrusionFilter vtkRotationalExtrusionFilter */ #ifndef vtkTrimmedExtrusionFilter_h #define vtkTrimmedExtrusionFilter_h #include "vtkFiltersModelingModule.h" // For export macro #include "vtkPolyDataAlgorithm.h" VTK_ABI_NAMESPACE_BEGIN class vtkAbstractCellLocator; class VTKFILTERSMODELING_EXPORT vtkTrimmedExtrusionFilter : public vtkPolyDataAlgorithm { public: vtkTypeMacro(vtkTrimmedExtrusionFilter, vtkPolyDataAlgorithm); void PrintSelf(ostream& os, vtkIndent indent) override; /** * Create object with extrusion direction (0,0,1) and capping on. */ static vtkTrimmedExtrusionFilter* New(); ///@{ /** * Set/Get the extrusion direction. */ vtkSetVector3Macro(ExtrusionDirection, double); vtkGetVectorMacro(ExtrusionDirection, double, 3); ///@} ///@{ /** * Specify the surface which trims the surface. Note that the method * SetTrimSurfaceData does not connect the pipeline. The algorithm will * work on the input data as it is without updating the producer of the * data. The method SetTrimSurfaceConnection connects the pipeline. */ void SetTrimSurfaceData(vtkPolyData* pd); void SetTrimSurfaceConnection(vtkAlgorithmOutput* algOutput); ///@} ///@{ /** * Return a pointer to the enclosing surface. */ vtkPolyData* GetTrimSurface(); vtkPolyData* GetTrimSurface(vtkInformationVector* sourceInfo); ///@} ///@{ /** * Turn on/off the capping of the extruded skirt. */ vtkSetMacro(Capping, int); vtkGetMacro(Capping, int); vtkBooleanMacro(Capping, int); ///@} // How to extrude data. Either determine boundary edges and sweep them; or // sweep all edges. enum ExtrusionStrategy { BOUNDARY_EDGES = 0, ALL_EDGES = 1 }; ///@{ /** * Specify a strategy for extrusion. If the strategy is set to * "BOUNDARY_EDGES" then the boundary edges of the input polygons and * triangle strips are swept. (A boundary edge is an edge used by only one * 2D primitive, e.g., polygon or triangle.) Alternatively, all edges can * be swept. (This is particularly useful when only sinple disconnected * polygons exist in the input and so boundary calculation can be avoided.) * By default boundary edges are extruded. */ vtkSetMacro(ExtrusionStrategy, int); vtkGetMacro(ExtrusionStrategy, int); void SetExtrusionStrategyToBoundaryEdges() { this->SetExtrusionStrategy(BOUNDARY_EDGES); } void SetExtrusionStrategyToAllEdges() { this->SetExtrusionStrategy(ALL_EDGES); } ///@} // How to cap data. enum CappingStrategy { INTERSECTION = 0, MINIMUM_DISTANCE = 1, MAXIMUM_DISTANCE = 2, AVERAGE_DISTANCE = 3, }; ///@{ /** * Specify a strategy for capping. By default the points of the cap * polygons are located where the extrusion intersects the capping surface. * However, to preserve planarity, or to place the capping surface at the * average/minimum/maximum distance of extrusion, different strategies can * be used. By default the average distance is used. * * Note if none of the extrusion rays intersect the trim surface, then * capping is not performed, nor is an extrusion skirt sent to the * output. Also note that if the capping strategy is set to INTERSECTION, * and one of the extrusion rays of the generating primitive does not * intersect the trim surface, then no output will be generated for that * primitive. However if any other capping strategy is used, capping will * succeed if at least one extrusion ray strikes the trim surface (although * missed extrusion ray intersections will not factor into the * determination of final cap location). * * Finally, note that any capping strategy other than INTERSECTION may * produce more points than expected because the output primitives may * have to be "split apart" to satisfy the capping constraint. */ vtkSetMacro(CappingStrategy, int); vtkGetMacro(CappingStrategy, int); void SetCappingStrategyToIntersection() { this->SetCappingStrategy(INTERSECTION); } void SetCappingStrategyToMinimumDistance() { this->SetCappingStrategy(MINIMUM_DISTANCE); } void SetCappingStrategyToMaximumDistance() { this->SetCappingStrategy(MAXIMUM_DISTANCE); } void SetCappingStrategyToAverageDistance() { this->SetCappingStrategy(AVERAGE_DISTANCE); } ///@} ///@{ /** * Specify a cell locator. By default a vtkStaticCellLocator is * used. The locator performs efficient searches to intersect cells. */ void SetLocator(vtkAbstractCellLocator* locator); vtkGetObjectMacro(Locator, vtkAbstractCellLocator); ///@} protected: vtkTrimmedExtrusionFilter(); ~vtkTrimmedExtrusionFilter() override; int Capping; double ExtrusionDirection[3]; int ExtrusionStrategy; int CappingStrategy; vtkAbstractCellLocator* Locator; void AdjustPoints(vtkPolyData* mesh, vtkIdType numPts, vtkIdType numCells, unsigned char* hots, vtkPoints* newPts); void ExtrudeEdges(vtkPolyData* input, vtkPolyData* output, vtkIdType numPts, vtkIdType numCells); vtkIdType GetNeighborCount( vtkPolyData* mesh, vtkIdType inCellId, vtkIdType p1, vtkIdType p2, vtkIdList* cellIds); int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override; int FillInputPortInformation(int, vtkInformation*) override; private: vtkTrimmedExtrusionFilter(const vtkTrimmedExtrusionFilter&) = delete; void operator=(const vtkTrimmedExtrusionFilter&) = delete; }; VTK_ABI_NAMESPACE_END #endif