mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-13 02:47:48 +00:00
Purge old experimental painter algorithm code for vector background elements
In preparation to migrate this to C++
This commit is contained in:
@@ -152,7 +152,6 @@ class IfcCutter:
|
||||
self.ifc_filenames = []
|
||||
self.ifc_files = {}
|
||||
self.resolved_pixels = set()
|
||||
self.should_get_background = False
|
||||
self.text_pickle_file = "text.pickle"
|
||||
self.metadata_pickle_file = "metadata.pickle"
|
||||
self.cut_pickle_file = "cut.pickle"
|
||||
@@ -192,15 +191,6 @@ class IfcCutter:
|
||||
self.get_cut_polygon_metadata()
|
||||
self.profile_code("Get cut polygon metadata")
|
||||
|
||||
# should_get_background is False in production as this is experimental
|
||||
if not self.should_get_background:
|
||||
return
|
||||
|
||||
self.get_background_elements()
|
||||
self.sort_background_elements(reverse=True)
|
||||
self.merge_background_elements()
|
||||
self.sort_background_elements()
|
||||
|
||||
def profile_code(self, message):
|
||||
if not self.time:
|
||||
self.time = time.time()
|
||||
@@ -329,76 +319,6 @@ class IfcCutter:
|
||||
return True
|
||||
return False
|
||||
|
||||
def sort_background_elements(self, reverse=None):
|
||||
if reverse:
|
||||
new_list = sorted(self.background_elements, key=lambda k: -k["z"])
|
||||
else:
|
||||
new_list = sorted(self.background_elements, key=lambda k: k["z"])
|
||||
self.background_elements = new_list
|
||||
|
||||
def process_grid(self, face, resolution):
|
||||
try:
|
||||
bbox = self.get_bbox(face)
|
||||
xmin, ymin, zmin, xmax, ymax, zmax = bbox.Get()
|
||||
except:
|
||||
return
|
||||
current_x = 0
|
||||
current_y = 0
|
||||
is_visible = False
|
||||
while current_x < self.section_box["x"]:
|
||||
current_y = 0
|
||||
while current_y > -self.section_box["y"]:
|
||||
if current_x < xmin or current_x > xmax or current_y < ymin or current_y > ymax:
|
||||
current_y -= resolution
|
||||
continue
|
||||
if (current_x, current_y) in self.resolved_pixels:
|
||||
current_y -= resolution
|
||||
continue
|
||||
point = numpy.array((current_x, current_y, 0))
|
||||
hit = self.raycast(face, point)
|
||||
if hit:
|
||||
is_visible = True
|
||||
self.resolved_pixels.add((current_x, current_y))
|
||||
current_y -= resolution
|
||||
current_x += resolution
|
||||
return is_visible
|
||||
|
||||
def merge_background_elements(self):
|
||||
background_elements = []
|
||||
|
||||
resolution = 0.1 # 10cm
|
||||
|
||||
# DO CUT
|
||||
total_product_shapes = len(self.cut_polygons)
|
||||
n = 0
|
||||
for element in self.cut_polygons:
|
||||
# print('{}/{} background elements processed ...'.format(n, total_product_shapes), end='\r', flush=True)
|
||||
print("{}/{} cut polygons processed ...".format(n, total_product_shapes))
|
||||
print("{} resolved pixels".format(len(self.resolved_pixels)))
|
||||
n += 1
|
||||
self.process_grid(element["geometry_face"], resolution)
|
||||
|
||||
# DO BACKGROUND
|
||||
total_product_shapes = len(self.background_elements)
|
||||
n = 0
|
||||
for element in self.background_elements:
|
||||
# print('{}/{} background elements processed ...'.format(n, total_product_shapes), end='\r', flush=True)
|
||||
print("{}/{} background elements processed ...".format(n, total_product_shapes))
|
||||
print("{} resolved pixels".format(len(self.resolved_pixels)))
|
||||
n += 1
|
||||
if element["type"] != "polygon":
|
||||
background_elements.append(element)
|
||||
continue
|
||||
is_visible = self.process_grid(element["geometry_face"], resolution)
|
||||
if is_visible:
|
||||
background_elements.append(element)
|
||||
|
||||
print(
|
||||
"##### BEFORE it had {} and after it had {}".format(len(self.background_elements), len(background_elements))
|
||||
)
|
||||
self.background_elements = background_elements
|
||||
return
|
||||
|
||||
def create_section_box(self):
|
||||
top_left_corner = gp.gp_Pnt(
|
||||
self.section_box["top_left_corner"][0],
|
||||
@@ -429,86 +349,6 @@ class IfcCutter:
|
||||
self.transformation = gp.gp_Trsf()
|
||||
self.transformation.SetDisplacement(source, destination)
|
||||
|
||||
def get_background_elements(self):
|
||||
total_product_shapes = len(self.product_shapes)
|
||||
n = 0
|
||||
intersections = []
|
||||
compound = TopoDS.TopoDS_Compound()
|
||||
builder = BRep.BRep_Builder()
|
||||
builder.MakeCompound(compound)
|
||||
for product, shape in self.product_shapes:
|
||||
builder.Add(compound, shape)
|
||||
|
||||
print("{}/{} background elements processed ...".format(n, total_product_shapes), end="\r", flush=True)
|
||||
# print('Processing product {} '.format(product.Name))
|
||||
n += 1
|
||||
|
||||
intersection = BRepAlgoAPI.BRepAlgoAPI_Common(self.section_box["shape"], shape).Shape()
|
||||
intersection_edges = self.get_booleaned_edges(intersection)
|
||||
if len(intersection_edges) <= 0:
|
||||
continue
|
||||
intersections.append(intersection)
|
||||
|
||||
transformed_intersection = BRepBuilderAPI.BRepBuilderAPI_Transform(intersection, self.transformation)
|
||||
intersection = transformed_intersection.Shape()
|
||||
|
||||
edge_face_map = TopTools.TopTools_IndexedDataMapOfShapeListOfShape()
|
||||
TopExp.topexp.MapShapesAndAncestors(intersection, TopAbs.TopAbs_EDGE, TopAbs.TopAbs_FACE, edge_face_map)
|
||||
|
||||
exp = TopExp.TopExp_Explorer(intersection, TopAbs.TopAbs_FACE)
|
||||
while exp.More():
|
||||
face = topods.Face(exp.Current())
|
||||
normal = self.get_normal(face)
|
||||
# Cull back-faces
|
||||
if normal.Z() <= 0:
|
||||
exp.Next()
|
||||
continue
|
||||
zpos, zmax = self.calculate_face_zpos(face)
|
||||
self.build_new_face(face, zpos, product)
|
||||
self.get_split_edges(edge_face_map, face, zmax, product)
|
||||
exp.Next()
|
||||
|
||||
def get_raycast_hits(self, shape):
|
||||
resolution = 0.1 # 5cm
|
||||
hits = []
|
||||
current_x = 0
|
||||
current_y = 0
|
||||
while current_x < self.section_box["x"] / 2:
|
||||
current_y = 0
|
||||
while current_y < self.section_box["y"] / 4:
|
||||
point = numpy.array(self.section_box["top_left_corner"])
|
||||
point = numpy.add(point, current_x * numpy.array(self.section_box["x_axis"]))
|
||||
point = numpy.add(point, current_y * numpy.array(self.section_box["y_axis"]))
|
||||
hit = self.raycast(shape, point)
|
||||
if hit:
|
||||
hits.append(hit)
|
||||
current_y += resolution
|
||||
current_x += resolution
|
||||
print("row down")
|
||||
return hits
|
||||
|
||||
def raycast(self, shape, point):
|
||||
raycast = IntCurvesFace.IntCurvesFace_ShapeIntersector()
|
||||
raycast.Load(shape, 0.01)
|
||||
line = gp.gp_Lin(gp.gp_Pnt(float(point[0]), float(point[1]), float(point[2])), gp.gp_Dir(0, 0, -1))
|
||||
raycast.Perform(line, 0, self.section_box["z"])
|
||||
return raycast.NbPnt() != 0
|
||||
|
||||
def raycast_at_projection_dir(self, shape, point):
|
||||
raycast = IntCurvesFace.IntCurvesFace_ShapeIntersector()
|
||||
raycast.Load(shape, 0.01)
|
||||
line = gp.gp_Lin(
|
||||
gp.gp_Pnt(float(point[0]), float(point[1]), float(point[2])),
|
||||
gp.gp_Dir(
|
||||
self.section_box["projection"][0], self.section_box["projection"][1], self.section_box["projection"][2]
|
||||
),
|
||||
)
|
||||
raycast.Perform(line, 0, self.section_box["z"])
|
||||
if raycast.NbPnt() != 0:
|
||||
# The smaller WParameter is the closer z-index
|
||||
# Should be the first
|
||||
return {"face": raycast.Face(1), "z": raycast.WParameter(1)}
|
||||
|
||||
def get_bbox(self, shape):
|
||||
bbox = Bnd.Bnd_Box()
|
||||
BRepBndLib.brepbndlib_Add(shape, bbox)
|
||||
@@ -520,111 +360,6 @@ class IfcCutter:
|
||||
zpos = zmin + ((zmax - zmin) / 2)
|
||||
return zpos, zmax
|
||||
|
||||
def get_split_edges(self, edge_face_map, face, zmax, product):
|
||||
exp2 = TopExp.TopExp_Explorer(face, TopAbs.TopAbs_EDGE)
|
||||
while exp2.More():
|
||||
edge = topods.Edge(exp2.Current())
|
||||
adjface = TopoDS.TopoDS_Face()
|
||||
getadj = TopOpeBRepBuild.TopOpeBRepBuild_Tools.GetAdjacentFace(face, edge, edge_face_map, adjface)
|
||||
if getadj:
|
||||
try:
|
||||
edge_angle = math.degrees(self.get_angle_between_faces(face, adjface))
|
||||
except:
|
||||
# TODO: Figure out when a math domain error might occur,
|
||||
# because it does, sometimes.
|
||||
edge_angle = 0
|
||||
if edge_angle > 30 and edge_angle < 160:
|
||||
newedge = self.build_new_edge(edge, zmax + 0.01)
|
||||
if newedge:
|
||||
self.background_elements.append(
|
||||
{"raw": product, "geometry": newedge, "type": "line", "z": zmax + 0.01}
|
||||
)
|
||||
exp2.Next()
|
||||
|
||||
def get_angle_between_faces(self, f1, f2):
|
||||
return self.convert_dot_product_to_angle(
|
||||
self.get_dot_product_of_normals(self.get_normal(f1), self.get_normal(f2))
|
||||
)
|
||||
|
||||
def get_normal(self, face):
|
||||
surface = Geom.Handle_Geom_Surface(BRep.BRep_Tool.Surface(face))
|
||||
props = GeomLProp.GeomLProp_SLProps(surface, 0, 0, 1, 0.001)
|
||||
return props.Normal()
|
||||
|
||||
def get_dot_product_of_normals(self, n1, n2):
|
||||
return n1.X() * n2.X() + n1.Y() * n2.Y() + n1.Z() * n2.Z()
|
||||
|
||||
def convert_dot_product_to_angle(self, dp):
|
||||
return math.acos(dp)
|
||||
|
||||
def is_same_point(self, p1, p2):
|
||||
return p1.X() == p2.X() and p1.Y() == p2.Y() and p1.Z() == p2.Z()
|
||||
|
||||
def build_new_edge(self, edge, zpos):
|
||||
exp = TopExp.TopExp_Explorer(edge, TopAbs.TopAbs_VERTEX)
|
||||
new_vertices = []
|
||||
while exp.More():
|
||||
current_vertex = topods.Vertex(exp.Current())
|
||||
current_point = BRep.BRep_Tool.Pnt(current_vertex)
|
||||
current_point.SetZ(zpos)
|
||||
new_vertices.append(BRepBuilderAPI.BRepBuilderAPI_MakeVertex(current_point).Vertex())
|
||||
exp.Next()
|
||||
try:
|
||||
return BRepBuilderAPI.BRepBuilderAPI_MakeEdge(new_vertices[0], new_vertices[1]).Edge()
|
||||
except:
|
||||
return None
|
||||
|
||||
def build_new_face(self, face, zpos, product):
|
||||
exp = TopExp.TopExp_Explorer(face, TopAbs.TopAbs_WIRE)
|
||||
while exp.More():
|
||||
wireexp = BRepTools.BRepTools_WireExplorer(topods.Wire(exp.Current()))
|
||||
new_wire_builder = BRepBuilderAPI.BRepBuilderAPI_MakeWire()
|
||||
first_vertex = None
|
||||
previous_vertex = None
|
||||
while wireexp.More():
|
||||
current_vertex = wireexp.CurrentVertex()
|
||||
current_point = BRep.BRep_Tool.Pnt(current_vertex)
|
||||
# Dodgy technique to squash in Z axis
|
||||
current_point.SetZ(zpos)
|
||||
current_vertex = BRepBuilderAPI.BRepBuilderAPI_MakeVertex(current_point).Vertex()
|
||||
if not first_vertex:
|
||||
first_vertex = current_vertex
|
||||
if not previous_vertex:
|
||||
previous_vertex = current_vertex
|
||||
else:
|
||||
try:
|
||||
new_wire_builder.Add(
|
||||
topods.Edge(BRepBuilderAPI.BRepBuilderAPI_MakeEdge(previous_vertex, current_vertex).Edge())
|
||||
)
|
||||
previous_vertex = current_vertex
|
||||
except:
|
||||
pass
|
||||
wireexp.Next()
|
||||
|
||||
# make last edge
|
||||
if not wireexp.More():
|
||||
try:
|
||||
new_wire_builder.Add(
|
||||
topods.Edge(BRepBuilderAPI.BRepBuilderAPI_MakeEdge(current_vertex, first_vertex).Edge())
|
||||
)
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
new_wire = new_wire_builder.Wire()
|
||||
new_face = BRepBuilderAPI.BRepBuilderAPI_MakeFace(new_wire).Face()
|
||||
self.background_elements.append(
|
||||
{"raw": product, "geometry": new_wire, "geometry_face": new_face, "type": "polygon", "z": zpos}
|
||||
)
|
||||
except:
|
||||
# print('Could not build face')
|
||||
pass
|
||||
exp.Next()
|
||||
|
||||
def get_area(self, shape):
|
||||
gprops = GProp.GProp_GProps()
|
||||
BRepGProp.brepgprop.SurfaceProperties(shape, gprops)
|
||||
return gprops.Mass()
|
||||
|
||||
def get_booleaned_edges(self, shape):
|
||||
edges = []
|
||||
exp = TopExp.TopExp_Explorer(shape, TopAbs.TopAbs_EDGE)
|
||||
@@ -798,55 +533,3 @@ class IfcCutter:
|
||||
if os.path.isfile(self.cut_pickle_file):
|
||||
with open(self.cut_pickle_file, "rb") as pickle_file:
|
||||
self.cut_polygons = pickle.load(pickle_file)
|
||||
|
||||
|
||||
class IfcCutterDebug(IfcCutter):
|
||||
def cut(self):
|
||||
self.occ_display = ifcopenshell.geom.utils.initialize_display()
|
||||
super().cut()
|
||||
|
||||
def create_section_box(self):
|
||||
super().create_section_box()
|
||||
self.display_everything_with_section_plane()
|
||||
|
||||
def get_cut_polygons(self):
|
||||
super().get_cut_polygons()
|
||||
self.display_cut_polygons()
|
||||
|
||||
def get_background_elements(self):
|
||||
super().get_background_elements()
|
||||
self.display_background_elements()
|
||||
|
||||
def display_everything_with_section_plane(self):
|
||||
section_face_display = ifcopenshell.geom.utils.display_shape(self.section_box["face"])
|
||||
ifcopenshell.geom.utils.set_shape_transparency(section_face_display, 0.8)
|
||||
section_box_display = ifcopenshell.geom.utils.display_shape(self.section_box["shape"])
|
||||
ifcopenshell.geom.utils.set_shape_transparency(section_box_display, 0.5)
|
||||
|
||||
transformed_box = BRepBuilderAPI.BRepBuilderAPI_Transform(self.section_box["shape"], self.transformation)
|
||||
box_display = ifcopenshell.geom.utils.display_shape(transformed_box.Shape())
|
||||
ifcopenshell.geom.utils.set_shape_transparency(box_display, 0.2)
|
||||
|
||||
for shape in self.product_shapes:
|
||||
ifcopenshell.geom.utils.display_shape(shape[1])
|
||||
input("Debug: showing everything with section plane.")
|
||||
|
||||
def display_cut_polygons(self):
|
||||
self.occ_display.EraseAll()
|
||||
for polygon in self.cut_polygons:
|
||||
ifcopenshell.geom.utils.display_shape(polygon["geometry"], clr="BLACK")
|
||||
face = BRepBuilderAPI.BRepBuilderAPI_MakeFace(polygon["geometry"]).Face()
|
||||
face_display = ifcopenshell.geom.utils.display_shape(face)
|
||||
ifcopenshell.geom.utils.set_shape_transparency(face_display, 0.5)
|
||||
input("Debug: showing cut polygons.")
|
||||
|
||||
def display_background_elements(self):
|
||||
self.occ_display.EraseAll()
|
||||
for element in self.background_elements:
|
||||
if element["type"] == "line":
|
||||
ifcopenshell.geom.utils.display_shape(element["geometry"], clr="PURPLE")
|
||||
elif element["type"] == "polyline":
|
||||
ifcopenshell.geom.utils.display_shape(element["geometry_face"], clr="RED")
|
||||
elif element["type"] == "polygon":
|
||||
ifcopenshell.geom.utils.display_shape(element["geometry_face"])
|
||||
input("Debug: showing background elements.")
|
||||
|
||||
@@ -4139,9 +4139,6 @@ class ActivateDrawingStyle(bpy.types.Operator):
|
||||
self.exclude_global_ids.extend([e.GlobalId for e in results])
|
||||
if self.drawing_style.include_query:
|
||||
self.parse_filter_query("INCLUDE")
|
||||
else:
|
||||
for obj in bpy.context.scene.objects:
|
||||
obj.hide_viewport = False
|
||||
if self.drawing_style.exclude_query:
|
||||
self.parse_filter_query("EXCLUDE")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user