# Path: lasercut/helper.py
# def transform(part, referentiel_face, transform_matrix=None, y_invert = False):
#     normal_face = referentiel_face.normalAt(0, 0)
#     # original center is (0,0,0)
#     transformed_center = referentiel_face.CenterOfMass #+ normal_face.normalize() * x_origin
#     if transform_matrix is None:
#         transform_matrix = get_matrix_transform(referentiel_face)
#     part.Placement = FreeCAD.Placement(transform_matrix).multiply(part.Placement)
#     part.translate(transformed_center)
#     if y_invert:
#         part.rotate(transformed_center, normal_face, 180.)
#     return part
# 
# def compare_freecad_vector(vector1, vector2, epsilon=10e-6):
#     vector = vector1.sub(vector2)
#     if math.fabs(vector.x) < epsilon and math.fabs(vector.y) < epsilon and math.fabs(vector.z) < epsilon:
#         return True
#     return False
# 
# def compare_value(value1, value2, epsilon=10e-6):
#     value = value1 - value2
#     if math.fabs(value) < epsilon:
#         return True
#     return False
# 
# class Segment:
#     def __init__(self, first=FreeCAD.Vector(0, 0, 0), second=FreeCAD.Vector(0, 0, 0)):
#         self.A = first
#         self.B = second
# 
#     def a(self):
#         return self.A
# 
#     def b(self):
#         return self.B * 1
# 
#     def clone_a(self):
#         return self.A * 1
# 
#     def clone_b(self):
#         return self.B * 1
# 
#     def vector(self):
#         return self.B.sub(self.A)
# 
#     def length(self):
#         return self.vector().Length
# 
#     def mid_point(self):
#         mid_point_b = self.A.add(self.B)
#         mid_point_b.scale(0.5, 0.5, 0.5)
#         return mid_point_b
# 
#     def get_angle(self, segment):
#         return self.vector().getAngle(segment.vector())
# 
#     def add(self, vector):
#         return Segment(self.A.add(vector), self.B.add(vector))
# 
#     def rotate_z(self, angle):
#         return Segment(rotate_vector_z(self.A, angle), rotate_vector_z(self.B, angle))
# 
#     def __repr__(self):
#         return "Segment A: " + str(self.A) + ", B: " + str(self.B)
# 
# def assemble_list_element(el_list):
#     if len(el_list) == 0:
#         return None
# 
#     part = el_list[0]
#     for el in el_list[1:]:
#         part = part.fuse(el)
# 
#     return part


import Part
import FreeCAD
import math
from lasercut.helper import transform, compare_freecad_vector, compare_value, Segment, assemble_list_element
    for index, hinge in enumerate(hinges_list):
        if hinge.nb_link < hinge.min_links_nb:
            FreeCAD.Console.PrintError("Min. link is not respected for living hinges named " + str(hinge.name))

        flat_connection = create_flat_connection(hinge, last_face)
        parts_to_fuse.append(flat_connection)
        hinges_to_removes.append(make_hinges(hinge, material_properties, last_face))
        last_face = find_same_normal_face(flat_connection, last_face)

        sum_angle += hinge.deg_angle
        if rotation_vector is None:
            rotation_vector = hinge.rotation_vector

        second_shape_transformed = assemble_shape(last_face, hinge.freecad_object_2.Shape, hinge.freecad_face_2,
                                                  rotation_vector, -sum_angle)
        parts_to_fuse.append(second_shape_transformed)
        if index < (len(hinges_list) - 1):
            last_face = find_same_normal_face(second_shape_transformed, last_face)

    flat_part = assemble_list_element(parts_to_fuse)
    for hinge_to_remove in hinges_to_removes:
        flat_part = flat_part.cut(hinge_to_remove)

    solid = hinges_list[0].solid.copy()
    for hinge in hinges_list[1:]:
        solid = solid.fuse(hinge.solid)

    return flat_part, solid



# Path: lasercut/helper.py
# def transform(part, referentiel_face, transform_matrix=None, y_invert = False):
#     normal_face = referentiel_face.normalAt(0, 0)
#     # original center is (0,0,0)
#     transformed_center = referentiel_face.CenterOfMass #+ normal_face.normalize() * x_origin
#     if transform_matrix is None:
#         transform_matrix = get_matrix_transform(referentiel_face)
#     part.Placement = FreeCAD.Placement(transform_matrix).multiply(part.Placement)
#     part.translate(transformed_center)
#     if y_invert:
#         part.rotate(transformed_center, normal_face, 180.)
#     return part
# 
# def compare_freecad_vector(vector1, vector2, epsilon=10e-6):
#     vector = vector1.sub(vector2)
#     if math.fabs(vector.x) < epsilon and math.fabs(vector.y) < epsilon and math.fabs(vector.z) < epsilon:
#         return True
#     return False
# 
# def compare_value(value1, value2, epsilon=10e-6):
#     value = value1 - value2
#     if math.fabs(value) < epsilon:
#         return True
#     return False
# 
# class Segment:
#     def __init__(self, first=FreeCAD.Vector(0, 0, 0), second=FreeCAD.Vector(0, 0, 0)):
#         self.A = first
#         self.B = second
# 
#     def a(self):
#         return self.A
# 
#     def b(self):
#         return self.B * 1
# 
#     def clone_a(self):
#         return self.A * 1
# 
#     def clone_b(self):
#         return self.B * 1
# 
#     def vector(self):
#         return self.B.sub(self.A)
# 
#     def length(self):
#         return self.vector().Length
# 
#     def mid_point(self):
#         mid_point_b = self.A.add(self.B)
#         mid_point_b.scale(0.5, 0.5, 0.5)
#         return mid_point_b
# 
#     def get_angle(self, segment):
#         return self.vector().getAngle(segment.vector())
# 
#     def add(self, vector):
#         return Segment(self.A.add(vector), self.B.add(vector))
# 
#     def rotate_z(self, angle):
#         return Segment(rotate_vector_z(self.A, angle), rotate_vector_z(self.B, angle))
# 
#     def __repr__(self):
#         return "Segment A: " + str(self.A) + ", B: " + str(self.B)
# 
# def assemble_list_element(el_list):
#     if len(el_list) == 0:
#         return None
# 
#     part = el_list[0]
#     for el in el_list[1:]:
#         part = part.fuse(el)
# 
#     return part


# Path: lasercut/makehinges.py
import Part
import FreeCAD
import math
from lasercut.helper import transform, compare_freecad_vector, compare_value, Segment, assemble_list_element

    for index, hinge in enumerate(hinges_list):
        if hinge.nb_link < hinge.min_links_nb:
            FreeCAD.Console.PrintError("Min. link is not respected for living hinges named " + str(hinge.name))

        flat_connection = create_flat_connection(hinge, last_face)
        parts_to_fuse.append(flat_connection)
        hinges_to_removes.append(make_hinges(hinge, material_properties, last_face))
        last_face = find_same_normal_face(flat_connection, last_face)

        sum_angle += hinge.deg_angle
        if rotation_vector is None:
            rotation_vector = hinge.rotation_vector

        second_shape_transformed = assemble_shape(last_face, hinge.freecad_object_2.Shape, hinge.freecad_face_2,
                                                  rotation_vector, -sum_angle)
        parts_to_fuse.append(second_shape_transformed)
        if index < (len(hinges_list) - 1):
            last_face = find_same_normal_face(second_shape_transformed, last_face)

    flat_part = assemble_list_element(parts_to_fuse)
    for hinge_to_remove in hinges_to_removes:
        flat_part = flat_part.cut(hinge_to_remove)

    solid = hinges_list[0].solid.copy()
    for hinge in hinges_list[1:]:
        solid = solid.fuse(hinge.solid)

    return flat_part, solid



def create_flat_connection(hinge_properties, referentiel_face):