framework/freecad_workbench/freecad/robossembler/project_validator.py

184 lines
7.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import FreeCAD as App
import unicodedata
import numpy as np
from .helper.is_solid import is_object_solid
## Программа, содержащая все проверки активного проекта FreeCAD в соответствии с issue#149
doc = App.ActiveDocument
Console = App.Console
#========== Проверка имен ===============
class FormalValidator:
def __init__(self, document):
self.document = document
def is_unicode_safe(self, name):
normalized_name = unicodedata.normalize('NFKD', name).encode('ASCII', 'ignore').decode()
return name == normalized_name
def fix_invalid_names(self):
for obj in self.document.Objects:
if not self.is_unicode_safe(obj.Label):
safe_name = unicodedata.normalize('NFKD', obj.Label).encode('ASCII', 'ignore').decode()
obj.Label = safe_name
self.document.recompute()
#запуск проверки и исправления имен файлов
def validate(self):
invalid_names = [obj.Label for obj in self.document.Objects if not self.is_unicode_safe(obj.Label)]
if invalid_names:
print("Некорректные имена:")
for name in invalid_names:
print(name)
self.fix_invalid_names()
else:
print("Все имена корректны.")
class ModelValidator:
def __init__(self, document):
self.document = document
self.partlist = [obj for obj in self.document.Objects if (is_object_solid(obj) and not obj.TypeId == 'App::Part') ]
self.material_objects = [obj for obj in document.Objects if obj.TypeId == "App::MaterialObjectPython"]
def get_parts(self):
pass
def validate_geometry(self):
for obj in self.document.Objects:
if hasattr(obj, "Shape") and not is_object_solid(obj):
Console.PrintError(f"Объект '{obj.Name}' не является твердым телом.\n")
def is_intersecting(self, obj1, obj2):
if obj1.Shape.common(obj2.Shape).Volume > 0.0:
return True
def has_allow_intersections(self, obj):
if hasattr(obj, 'Base_Allowed_Intersection') and getattr(obj, 'Base_Allowed_Intersection', True):
return True
def check_bodies_for_intersections(self):
bodies = self.partlist
num_bodies = len(bodies)
for i in range(num_bodies):
for j in range(i + 1, num_bodies):
body1 = bodies[i]
body2 = bodies[j]
if self.is_intersecting(body1, body2):
if self.has_allow_intersections(body1) or self.has_allow_intersections(body2):
Console.PrintWarning(
f"Тела '{body1.Label}' и '{body2.Label}' ""предусмотренно пересекаются.\n")
else:
Console.PrintError(
f"Тела '{body1.Label}' и '{body2.Label}' ""непредусмотренно пересекаются.\n")
print('V = ' + str(body1.Shape.common(body2.Shape).Volume))
def get_adjacency_matrix(self, padding = 1):
# print(int(padding))
bodies = self.partlist
num_bodies = len(bodies)
adjacency_matrix = np.zeros((num_bodies, num_bodies), dtype=bool)
for i in range(num_bodies):
shape1 = bodies[i].Shape
for j in range(i + 1, num_bodies):
shape2 = bodies[j].Shape
if shape1.common(shape2).Volume > 0:
continue
distance = shape1.distToShape(shape2)
if distance[0] < padding:
adjacency_matrix[i][j] = 1
adjacency_matrix[j][i] = 1
return adjacency_matrix
def check_bodies_without_contacts(self):
adjacency_matrix = self.get_adjacency_matrix()
bodies = self.partlist
isolated_bodies = []
num_bodies = len(bodies)
for i in range(num_bodies):
# Проверяем, есть ли у тела касания с другими телами
if not any(adjacency_matrix[i]):
isolated_bodies.append(bodies[i].Label)
if isolated_bodies:
App.Console.PrintWarning("Следующие тела не касаются других:\n")
for label in isolated_bodies:
App.Console.PrintWarning(f"- {label}\n")
else:
App.Console.PrintMessage("Все тела имеют контакты.\n")
def find_material_objects(document):
pass
def check_bodies_with_multiple_materials(self):
material_objects = self.material_objects
material_references = {}
for material in material_objects:
if hasattr(material, "References"):
for reference in material.References:
if reference in material_references:
material_references[reference].append(material.Label)
else:
material_references[reference] = [material.Label]
conflicts = {k: v for k, v in material_references.items() if len(v) > 1}
if conflicts:
App.Console.PrintWarning("Обнаружены конфликты между объектами материалов:\n")
for ref, materials in conflicts.items():
App.Console.PrintWarning(f"Деталь '{ref[0].Label}' используется в материалах: {', '.join(materials)}\n")
else:
App.Console.PrintMessage("Конфликтов в ссылках материалов не обнаружено.\n")
def check_bodies_without_material(self):
material_objects = self.material_objects
partlist = self.partlist
referenced_bodies = []
for material in material_objects:
if hasattr(material, "References"):
for reference in material.References:
referenced_bodies.append(reference[0].Label)
bodies_without_material = []
for part in partlist:
if part.Label not in referenced_bodies:
bodies_without_material.append(part.Label)
if bodies_without_material:
App.Console.PrintWarning("Следующие тела не имеют назначенного материала:\n")
for name in bodies_without_material:
App.Console.PrintWarning(f"- {name}\n")
else:
App.Console.PrintMessage("Все тела имеют назначенные материалы.\n")
def validate(self):
self.validate_geometry()
self.check_bodies_for_intersections()
self.check_bodies_without_contacts()
self.check_bodies_without_material()
self.check_bodies_with_multiple_materials()
def validate_project():
doc = App.ActiveDocument
FormalValidator(doc).validate()
ModelValidator(doc).validate()