Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
sdesalve opened this issue Aug 29, 2021 · 1 comment · May be fixed by #58
Open

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

sdesalve opened this issue Aug 29, 2021 · 1 comment · May be fixed by #58

Comments

@sdesalve
Copy link

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

@randomdude
Copy link

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.]

@randomdude randomdude linked a pull request Apr 6, 2022 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants