Skip to content

Interlocking: AttributeError: 'NoneType' object has no attribute 'Length' #53

Open

Description

@sdesalve

Hi,
I wasn't able to make interlocking pieces between a boolean and a solid from a sketch. I've tried also to make simple copies of objects. Is my object (LABEL: "Cut") too complex for making interlocking?

I'm getting this error:

16:37:03  Traceback (most recent call last):
16:37:03    File "C:\Users\x\AppData\Roaming\FreeCAD\Mod\LCInterlocking\panel\treepanel.py", line 255, in add_tabs
16:37:03      item = self.tabsList.append(face, self.tab_type_box.currentText())
16:37:03    File "C:\Users\x\AppData\Roaming\FreeCAD\Mod\LCInterlocking\panel\tab.py", line 165, in append
16:37:03      tab_properties = TabProperties(freecad_face=face['face'],
16:37:03    File "C:\Users\x\AppData\Roaming\FreeCAD\Mod\LCInterlocking\lasercut\tabproperties.py", line 71, in __init__
16:37:03      self.thickness = thickness.Length
16:37:03  AttributeError: 'NoneType' object has no attribute 'Length'

I've attached my file:
v4.zip

OS: Windows 10 (10.0)
Word size of FreeCAD: 64-bit
Version: 0.20.25429 (Git)
Build type: Release
Branch: master
Hash: acce57a25d82b0408fa07b9452ed31c8a06c7a1b
Python version: 3.8.10
Qt version: 5.12.9
Coin version: 4.0.0
OCC version: 7.5.2
Locale: Italian/Italy (it_IT)

Thanks
SDeSalve

Activity

  1. randomdude commented on Mar 28, 2022

    @randomdude

    I had the same problem. I think it's due to a face having more than four points (even a rectangular face may have more than four points, as some may be redundant or used for connecting shapes).

    I was able to bodge it in to working by replacing the get_local_axis function in helper.py:

    
    def getExtends(edge):
        extends_X = (edge.Vertexes[0].X != edge.Vertexes[1].X)
        extends_Y = (edge.Vertexes[0].Y != edge.Vertexes[1].Y)
        extends_Z = (edge.Vertexes[0].Z != edge.Vertexes[1].Z)
        
        return extends_X, extends_Y, extends_Z
    
    def get_local_axis(face):
        list_edges = Part.__sortEdges__(face.Edges)
        
        coalescedEdges = []
        previousEdge = None
        for edge in list_edges:
            extends_X, extends_Y, extends_Z = getExtends(edge)
    
            if previousEdge is not None:
                # If we extend in only one direction, and that is the same direction as the previous edge,
                # then we can merge the two edges together.
                dirsExtended = 0
                if extends_X:
                    dirsExtended = dirsExtended + 1
                if extends_Y:
                    dirsExtended = dirsExtended + 1
                if extends_Z:
                    dirsExtended = dirsExtended + 1
    
                if dirsExtended == 1 and extends_X == prev_extends_X and extends_Y == prev_extends_Y and extends_Z == prev_extends_Z:
                    if extends_X:
                        coalescedEdges[-1].Vertexes[1] = Part.Vertex(  edge.Vertexes[1].X, coalescedEdges[-1].Vertexes[1].Y, coalescedEdges[-1].Vertexes[1].Z)
    
                    if extends_Y:
                        ls = Part.LineSegment( coalescedEdges[-1].Vertexes[0].Point, FreeCAD.Vector(coalescedEdges[-1].Vertexes[1].X, edge.Vertexes[1].Y, coalescedEdges[-1].Vertexes[1].Z) )
                        coalescedEdges[-1] = Part.Edge(ls)
    
                    if extends_Z:
                        coalescedEdges[-1].Vertexes[1] = Part.Vertex( coalescedEdges[-1].Vertexes[1].X, coalescedEdges[-1].Vertexes[1].Y, edge.Vertexes[1].Z)
                else:
                    coalescedEdges.append(edge)
            else:
                coalescedEdges.append(edge)
    
            prev_extends_X = extends_X
            prev_extends_Y = extends_Y
            prev_extends_Z = extends_Z
            previousEdge = edge
    
        # And check in case the last edge is an extension of the first.
        extends_X, extends_Y, extends_Z = getExtends(coalescedEdges[-1])
        prev_extends_X, prev_extends_Y, prev_extends_Z = getExtends(coalescedEdges[0])
    
        dirsExtended = 0
        if extends_X:
            dirsExtended = dirsExtended + 1
    
        if extends_Y:
            dirsExtended = dirsExtended + 1
    
        if extends_Z:
            dirsExtended = dirsExtended + 1
    
        if dirsExtended == 1 and extends_X == prev_extends_X and extends_Y == prev_extends_Y and extends_Z == prev_extends_Z:
            if extends_X:
                coalescedEdges[-1].Vertexes[1] = Part.Vertex( coalescedEdges[0].Vertexes[1].X, coalescedEdges[-1].Vertexes[1].Y, coalescedEdges[-1].Vertexes[1].Z)
    
            if extends_Y:
                ls = Part.LineSegment( coalescedEdges[-1].Vertexes[0].Point, FreeCAD.Vector(coalescedEdges[-1].Vertexes[1].X, edge.Vertexes[1].Y, coalescedEdges[-1].Vertexes[1].Z) )
                coalescedEdges[-1] = Part.Edge(ls)
    
            if extends_Z:
                coalescedEdges[-1].Vertexes[1] = Part.Vertex( coalescedEdges[-1].Vertexes[1].X, coalescedEdges[-1].Vertexes[1].Y, coalescedEdges[0].Vertexes[1].Z)
    
            coalescedEdges.remove(coalescedEdges[0])
    
        list_edges = coalescedEdges
    
        #get_local_axis(elt)
        
        list_points = sort_quad_vertex(list_edges, False)
        if list_points is None:
            list_points = sort_quad_vertex(list_edges, True)
        if list_points is None:
            raise ValueError("Error sorting vertex")
    
        normal_face = face.normalAt(0, 0)
        y_local = None
        z_local = None
        #x_local = normal_face.negative()
        x_local = normal_face.normalize()
        z_local_not_normalized = None
        y_local_not_normalized = None
        for x in range(0, len(list_edges)):
            vector1 = list_points[(x + 1) % len(list_edges)] - list_points[x]
            vector2 = list_points[(x - 1) % len(list_edges)] - list_points[x]
            y_local = None
            z_local = None
            if vector1.Length >= vector2.Length:
                z_local_not_normalized = vector2 * 1
                y_local_not_normalized = vector1 * 1
                y_local = vector1.normalize()
                z_local = vector2.normalize()
            else:
                z_local_not_normalized = vector1 * 1
                y_local_not_normalized = vector2 * 1
                y_local = vector2.normalize()
                z_local = vector1.normalize()
    
            computed_x_local = y_local.cross(z_local)
    
            if compare_freecad_vector(computed_x_local, x_local):
                return x_local, y_local_not_normalized, z_local_not_normalized
    
        return None, None, None
    
    

    Please note that I haven't got a clue about geometry, and so I don't know if this will help at all! It might make things worse! Hopefully someone with deeper knowlege can help out later, but in the meantime, I hope this helps. It's horribly written, I know. But it works [for me.]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions