# -*- coding: utf-8 -*- # Copyright (C) 2014-2022 EDF R&D, OPEN CASCADE # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # # Author : Alexey SOZINOV, Open CASCADE S.A.S. ## @defgroup check_conformity CheckConformity - Wrapper to find imperfections in the shape # @{ # @details # This tool provides the user with a simple python API # to analyze, available shape for Boolean Operations or not. # Also tool provide advanced output to indicate imperfections in the input shape. # @n Example: # @code # import GEOM # from salome.geom import geomBuilder # from salome.geom.CheckConformity import CheckConformity # # geompy = geomBuilder.New() # # O = geompy.MakeVertex(0, 0, 0) # OX = geompy.MakeVectorDXDYDZ(1, 0, 0) # OY = geompy.MakeVectorDXDYDZ(0, 1, 0) # OZ = geompy.MakeVectorDXDYDZ(0, 0, 1) # Vertex_1 = geompy.MakeVertex(-30, -70, 0) # Vertex_2 = geompy.MakeVertex(-30, 50, 0) # Line_1 = geompy.MakeLineTwoPnt(Vertex_2, Vertex_1) # Vertex_3 = geompy.MakeVertex(0, -50, 0) # Vertex_4 = geompy.MakeVertex(-40, -10, 0) # Vertex_5 = geompy.MakeVertex(0, 40, 0) # Arc_1 = geompy.MakeArc(Vertex_5, Vertex_4, Vertex_3) # Vertex_6 = geompy.MakeVertex(10, -50, 4) # Vertex_7 = geompy.MakeVertex(10, -50, 10) # Vertex_8 = geompy.MakeVertex(10, 40, 10) # Arc_1_vertex_3 = geompy.GetSubShape(Arc_1, [3]) # Line_2 = geompy.MakeLineTwoPnt(Arc_1_vertex_3, Vertex_6) # Line_3 = geompy.MakeLineTwoPnt(Vertex_6, Vertex_7) # Line_4 = geompy.MakeLineTwoPnt(Vertex_7, Vertex_8) # Vertex_9 = geompy.MakeVertex(15, 40, 10) # Vertex_10 = geompy.MakeVertex(17, 0, 6) # Vertex_11 = geompy.MakeVertex(17, 0, 3) # Line_5 = geompy.MakeLineTwoPnt(Vertex_8, Vertex_9) # Line_6 = geompy.MakeLineTwoPnt(Vertex_9, Vertex_10) # Line_7 = geompy.MakeLineTwoPnt(Vertex_10, Vertex_11) # Arc_1_vertex_2 = geompy.GetSubShape(Arc_1, [2]) # Line_8 = geompy.MakeLineTwoPnt(Vertex_11, Arc_1_vertex_2) # Wire_1 = geompy.MakeWire([Arc_1, Line_2, Line_3, Line_4, Line_5, Line_6, Line_7, Line_8], 1e-07) # Wire_2 = geompy.MakeWire([Line_1], 1e-07) # Compound_1 = geompy.MakeCompound([Wire_1, Wire_2]) # # # Create class CheckConformity for check shape # cc = CheckConformity(Compound_1, geompy) # valid = cc.isValid() # dist = cc.distantShapes() # small = cc.smallEdges() # interfer = cc.interferingSubshapes() # intersect = cc.selfIntersected2D() # # geompy.addToStudy( O, 'O' ) # geompy.addToStudy( OX, 'OX' ) # geompy.addToStudy( OY, 'OY' ) # geompy.addToStudy( OZ, 'OZ' ) # geompy.addToStudy( Vertex_1, 'Vertex_1' ) # geompy.addToStudy( Vertex_2, 'Vertex_2' ) # geompy.addToStudy( Line_1, 'Line_1' ) # geompy.addToStudy( Vertex_3, 'Vertex_3' ) # geompy.addToStudy( Vertex_4, 'Vertex_4' ) # geompy.addToStudy( Vertex_5, 'Vertex_5' ) # geompy.addToStudy( Arc_1, 'Arc_1' ) # geompy.addToStudy( Vertex_6, 'Vertex_6' ) # geompy.addToStudy( Vertex_7, 'Vertex_7' ) # geompy.addToStudy( Vertex_8, 'Vertex_8' ) # geompy.addToStudyInFather( Arc_1, Arc_1_vertex_3, 'Arc_1:vertex_3' ) # geompy.addToStudy( Line_2, 'Line_2' ) # geompy.addToStudy( Line_3, 'Line_3' ) # geompy.addToStudy( Line_4, 'Line_4' ) # geompy.addToStudy( Vertex_9, 'Vertex_9' ) # geompy.addToStudy( Vertex_10, 'Vertex_10' ) # geompy.addToStudy( Vertex_11, 'Vertex_11' ) # geompy.addToStudy( Line_5, 'Line_5' ) # geompy.addToStudy( Line_6, 'Line_6' ) # geompy.addToStudy( Line_7, 'Line_7' ) # geompy.addToStudyInFather( Arc_1, Arc_1_vertex_2, 'Arc_1:vertex_2' ) # geompy.addToStudy( Line_8, 'Line_8' ) # geompy.addToStudy( Wire_1, 'Wire_1' ) # geompy.addToStudy( Wire_2, 'Wire_2' ) # geompy.addToStudy( Compound_1, 'Compound_1' ) # # salome.sg.updateObjBrowser() # # @endcode # @n Additional examples can be found as unit tests in the source code. # @} ## An interface to find imperfections in the shape. # Use geompy.CheckConformity(shape) method to obtain an instance of this class # # @ref tui_check_conformity_page "Example" # @ingroup check_conformity class CheckConformity: AUTO = -1 """ Check Conformity interface Example of usage: cc = CheckConformity(Lot4_twistedFace_brep_1, geompy) valid = cc.isValid() dist = cc.distantShapes(geompy.ShapeType["EDGE"], geompy.ShapeType["VERTEX"]) small = cc.smallEdges() interfer = cc.interferingSubshapes() interferEV = cc.interferingSubshapes(geompy.ShapeType["EDGE"], geompy.ShapeType["VERTEX"]) interferVV = cc.interferingSubshapes(geompy.ShapeType["VERTEX], geompy.ShapeType["VERTEX"]) intersect = cc.selfIntersected2D() """ def __init__(self, shape, geompyD): self.geompyD = geompyD self.myShape = shape self.myIsChecked = False; self.myResults = [] ## Perform analyse of shape. # # @return New List, which contains pair: type of check and single of pair failed sub-shapes. def __checkShape(self): """ Perform analyse of shape. Returns: New List, which contains pair: type of check and single of pair failed sub-shapes. """ anOp = self.geompyD.GetIMeasureOperations() self.myResults = anOp.CheckConformityShape(self.myShape) self.myIsChecked = True ## Check whether the shape is applicable for Boolean Operations. # # @return Boolean value True if shape is applicable for Boolean Operations, otherwise - False def isValid(self): """ check whether the shape is applicable for Boolean Operations. Returns: Boolean value True if shape is applicable for Boolean Operations, otherwise - False. Example of usage: Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200) cc = CheckConformity(Box_1, geompy) isValid = cc.isValid() """ if not self.myIsChecked: self.__checkShape() return len(self.myResults) == 0 ## Find all self-intersected 2D curves. # # @return New List, of pair sub-shape, which has self-intersected in 2D def selfIntersected2D(self): """ Find all self-intersected 2D curves. Returns: New List, of pair sub-shape, which has self-intersected in 2D/ Example of usage: Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200) cc = CheckConformity(Box_1, geompy) selfIntersected2D = cc.selfIntersected2D() """ if not self.myIsChecked: self.__checkShape() anOp = self.geompyD.GetIMeasureOperations() return anOp.SelfIntersected2D(self.myResults) ## Find pairs of interfering sub-shapes: # - vertices touched by tolerance; # - vertex touching an edge in the inner point; # - vertex lying on the inner point of a face; # - edges intersecting by inner points; # - edge touching/intersecting face in the inner point; # - faces intersection by inner point # # Types of interfering shapes could be specified, # by default all pairs of interfering shapes are returned. # # @param shapeType1 first type of shape # @param shapeType2 second type of shape # # @return New List, of pairs of interfering shapes with given types (if they was specified) def interferingSubshapes(self, shapeType1 = AUTO, shapeType2 = AUTO): """ Find pairs of interfering sub-shapes: - vertices touched by tolerance - vertex touching an edge in the inner point - vertex lying on the inner point of a face - edges intersecting by inner points - edge touching/intersecting face in the inner point - faces intersection by inner point Types of interfering shapes could be specified, by default all pairs of interfering shapes are returned. Parameters: shapeType1 first type of shape shapeType2 second type of shape Returns: New List, of pairs of interfering shapes with given types (if they was specified) Example of usage: Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200) cc = CheckConformity(Box_1, geompy) interferingSubshapes = cc.interferingSubshapes() interferingSubshapesVV = cc.interferingSubshapes(geompy.ShapeType["VERTEX"], geompy.ShapeType["VERTEX"]) """ if not self.myIsChecked: self.__checkShape() anOp = self.geompyD.GetIMeasureOperations() return anOp.InterferingSubshapes(self.myResults, shapeType1, shapeType2) ## Find edges, which are fully covered by tolerances of vertices. # # @return New List of edges, which are fully covered by tolerances of vertices def smallEdges(self): """ Find edges, which are fully covered by tolerances of vertices. Returns: New List of edges, which are fully covered by tolerances of vertices. Example of usage: Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200) cc = CheckConformity(Box_1, geompy) smallEdges = cc.smallEdges() """ if not self.myIsChecked: self.__checkShape() anOp = self.geompyD.GetIMeasureOperations() return anOp.SmallEdges(self.myResults) ## Find remote objects (sub-shape on a shape): # - vertex far from edge; # - vertex far from face; # - edge far from face # # Sub-shape which are lying far from its parent shape more than the given tolerance. # # @param shapeType type of shape # @param subShapeType type of sub-shape # @param tolerance available tolerance, by default used tolerance of sub-shape. # # @return New List, of pair of sub-shape with given types, # that lying far from its parent shape more than the given tolerance. def distantShapes(self, shapeType = AUTO, subShapeType = AUTO, tolerance = -1.0): """ Find remote objects (sub-shape on a shape): - vertex far from edge; - vertex far from face; - edge far from face Sub-shape which are lying far from its parent shape more than the given tolerance. Parameters: shapeType type of shape subShapeType type of sub-shape tolerance available tolerance, by default used tolerance of sub-shape. Returns: New List, of pair of sub-shape with given types, that lying far from its parent shape more than the given tolerance Example of usage: Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200) cc = CheckConformity(Box_1, geompy) distantShapes = cc.distantShapes(geompy.ShapeType["EDGE"], geompy.ShapeType["VERTEX"]) """ if not self.myIsChecked: self.__checkShape() anOp = self.geompyD.GetIMeasureOperations() return anOp.DistantShapes(self.myResults, shapeType, subShapeType, tolerance) ## Compute possible tolerance for the shape, # minimize tolerance of shape as well as tolerance of sub-shapes as much as possible . # # @return New value of tolerance. def updateTolerance(self): """ Compute possible tolerance for the shape, minimize tolerance of shape as well as tolerance of sub-shapes as much as possible. Returns: New value of tolerance. Example of usage: Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200) cc = CheckConformity(Box_1, geompy) toler = cc.updateTolerance() """ anOp = self.geompyD.GetIMeasureOperations() return anOp.UpdateTolerance(self.myShape)