def addObject(TypeId, name, rep="Shape", doc=None, cached=False, args={}):
    if doc is None:
        doc = FreeCAD.ActiveDocument

    if cached:
        for obj in doc.Objects:
            if fuzzyCompare(featurePropertiesOf(obj), featurePropertiesOf(TypeId, args=args)):
                obj.ViewObject.show()
                for ftr in ftrlist(obj.OutList):
                    ftr.ViewObject.hide()
                return obj

    if isinstance(TypeId, str):
        obj = doc.addObject(TypeId, name)
    else:
        if rep == "Shape":
            obj = doc.addObject("Part::FeaturePython", name)
        elif rep == "Mesh":
            obj = doc.addObject("Mesh::FeaturePython", name)
        else:
            raise TypeError
        obj.Proxy = TypeId()

    for k, v in args.items():
        if k in obj.PropertiesList:
            setattr(obj, k, v)
        else:
            getattr(obj.Proxy, "set"+k)(obj, v)

    return obj
def noCollision(ftrs):
    ftrs = ftrlist(ftrs)
    shps = []
    for ftr in ftrs:
        if isDerivedFrom(ftr, ("Part::Compound", Compound)):
            shps.append(Shapes.fuse(outftr.Shape for outftr in ftrlist(ftr.OutList)))
        else:
            shps.append(ftr.Shape)
    vol_sum = sum(shp.Volume for shp in shps)
    vol_fus = Shapes.fuse(shps).Volume
    return fuzzyCompare(vol_sum, vol_fus)
def makeConicalFrustum(radius1, radius2, height, pnt=FreeCAD.Vector()):
    if fuzzyCompare(radius1, radius2):
        return Part.makeCylinder(abs(radius1), abs(height), pnt)

    elif radius1*radius2 >= 0:
        return Part.makeCone(abs(radius1), abs(radius2), abs(height), pnt)

    else:
        height1 = abs(height)*abs(radius1/(radius1-radius2))
        height2 = abs(height)*abs(radius2/(radius1-radius2))
        pnt1 = pnt
        pnt2 = pnt + FreeCAD.Vector(0, 0, height1)
        shape1 = Part.makeCone(abs(radius1), 0, height1, pnt1)
        shape2 = Part.makeCone(0, abs(radius2), height2, pnt2)
        shape = shape1.fuse(shape2)
        return shape
def createConicalFrustum(radius1, radius2, height, pnt=FreeCAD.Vector(), fn=50):
    if fuzzyCompare(radius1, radius2):
        mesh = Mesh.createCylinder(abs(radius1), abs(height), 1, 0.5/fn, int(fn))
        mesh.transform(FreeCAD.Placement(pnt, FreeCAD.Rotation(0,-90,0)).toMatrix())
        return mesh

    elif radius1*radius2 >= 0:
        mesh = Mesh.createCone(abs(radius1), abs(radius2), abs(height), 1, 0.5/fn, int(fn))
        mesh.transform(FreeCAD.Placement(pnt, FreeCAD.Rotation(0,-90,0)).toMatrix())
        return mesh

    else:
        height1 = abs(height)*abs(radius1/(radius1-radius2))
        height2 = abs(height)*abs(radius2/(radius1-radius2))
        pnt1 = pnt
        pnt2 = pnt + FreeCAD.Vector(0, 0, height1)

        mesh1 = Mesh.createCone(abs(radius1), 0, height1, 1, 0.5/fn, int(fn))
        mesh1.transform(FreeCAD.Placement(pnt1, FreeCAD.Rotation(0,-90,0)).toMatrix())
        mesh2 = Mesh.createCone(0, abs(radius2), height2, 1, 0.5/fn, int(fn))
        mesh2.transform(FreeCAD.Placement(pnt2, FreeCAD.Rotation(0,-90,0)).toMatrix())
        mesh = mesh1.unite(mesh2)
        return mesh
def isInside(ftr1, ftr2):
    return fuzzyCompare(ftr1.Shape.cut(ftr2.Shape).Volume, 0)
def isOutside(ftr1, ftr2):
    return fuzzyCompare(ftr1.Shape.common(ftr2.Shape).Volume, 0)