Exemplo n.º 1
0
    def execute(self, fp):
        if not fp.Base or not fp.Tools:
            return

        fp.Proxy = None
        if fp.CutDirection == Vector(0.0, 0.0, 0.0):
            bbox = self.extractCompounds([fp.Base])[0].Shape.BoundBox
            v = Vector(1, 1, 1)
            if bbox.XLength < bbox.YLength and bbox.XLength < bbox.ZLength:
                v.x = 0
            elif bbox.YLength <= bbox.XLength and bbox.YLength < bbox.ZLength:
                v.y = 0
            else:
                v.z = 0

            bbox = self.extractCompounds(fp.Tools)[0].Shape.BoundBox
            if bbox.XLength < bbox.YLength and bbox.XLength < bbox.ZLength:
                v.x = 0
            elif bbox.YLength <= bbox.XLength and bbox.YLength < bbox.ZLength:
                v.y = 0
            else:
                v.z = 0

            fp.CutDirection = v * fp.CutDepth / 50

        fp.Proxy = self
        self.cutNotches(fp)
Exemplo n.º 2
0
    def cutNotches(self, fp):
        shapes = []
        halfsize = fp.CutDirection / 2
        for obj in self.extractCompounds([fp.Base]):
            useSubPart = obj.TypeId == 'Part::Extrusion' and len(
                obj.Base.Shape.Faces) > 0
            if useSubPart:
                bShapes = obj.Base
            else:
                bShapes = obj

            for bShape in self.extractShapes([bShapes]):
                cutcubes = []
                for tool in self.extractShapes(fp.Tools):
                    tbox = tool.optimalBoundingBox()
                    common = tool.common(bShape)
                    cbox = common.BoundBox
                    if cbox.XLength + cbox.YLength + cbox.ZLength > epsilon:
                        cbox = common.optimalBoundingBox()
                        vSize = Vector(cbox.XLength, cbox.YLength,
                                       cbox.ZLength)
                        vPlace = Vector(cbox.XMin, cbox.YMin, cbox.ZMin)
                        if vSize.x < epsilon or vSize.x > tbox.XLength:
                            vSize.x = tbox.XLength
                            vPlace.x = tbox.XMin
                        if vSize.y < epsilon or vSize.y > tbox.YLength:
                            vSize.y = tbox.YLength
                            vPlace.y = tbox.YMin
                        if vSize.z < epsilon or vSize.z > tbox.ZLength:
                            vSize.z = tbox.ZLength
                            vPlace.z = tbox.ZMin

                        cutcube = Part.makeBox(vSize.x, vSize.y, vSize.z)
                        cutcube.Placement.Base = vPlace
                        cutcube.Placement.Base.x += cbox.XLength * halfsize.x
                        cutcube.Placement.Base.y += cbox.YLength * halfsize.y
                        cutcube.Placement.Base.z += cbox.ZLength * halfsize.z
                        cutcubes.append(cutcube)

                if len(cutcubes) > 0:
                    try:
                        cutted = bShape.cut(cutcubes)
                    except:
                        cutted = bShape
                else:
                    cutted = bShape

                if useSubPart:
                    cutted.Placement.Base -= obj.Dir * float(obj.LengthRev)
                    ext = cutted.extrude(obj.Dir *
                                         float(obj.LengthFwd + obj.LengthRev))
                    shapes.append(ext)
                else:
                    shapes.append(cutted)

        fp.Shape = Part.makeCompound(shapes)
Exemplo n.º 3
0
    def cutNotches(self, fp):
        shapes = []
        halfsize = fp.CutDirection / 2
        for obj in self.extractCompounds([fp.Base]):
            isExtrude = hasattr(obj, "LengthFwd") and hasattr(obj, "Base")
            if isExtrude:
                bShapes = obj.Base
            else:
                bShapes = obj

            for bShape in self.extractShapes([bShapes]):
                cutcubes = []
                for tool in self.extractShapes(fp.Tools):
                    tbox = tool.BoundBox
                    common = tool.common(bShape)
                    cbox = common.BoundBox
                    if cbox.XLength + cbox.YLength + cbox.ZLength > epsilon:
                        vSize = Vector(cbox.XLength, cbox.YLength,
                                       cbox.ZLength)
                        vPlace = Vector(cbox.XMin, cbox.YMin, cbox.ZMin)
                        if vSize.x < epsilon or vSize.x > tbox.XLength:
                            vSize.x = tbox.XLength
                            vPlace.x = tbox.XMin
                        if vSize.y < epsilon or vSize.y > tbox.YLength:
                            vSize.y = tbox.YLength
                            vPlace.y = tbox.YMin
                        if vSize.z < epsilon or vSize.z > tbox.ZLength:
                            vSize.z = tbox.ZLength
                            vPlace.z = tbox.ZMin

                        cutcube = Part.makeBox(vSize.x, vSize.y, vSize.z)
                        cutcube.Placement.Base = vPlace
                        cutcube.Placement.Base.x += cbox.XLength * halfsize.x
                        cutcube.Placement.Base.y += cbox.YLength * halfsize.y
                        cutcube.Placement.Base.z += cbox.ZLength * halfsize.z
                        cutcubes.append(cutcube)

                if len(cutcubes) > 0:
                    cutted = bShape.cut(cutcubes)
                else:
                    cutted = bShape

                if isExtrude:
                    cutted.Placement.Base -= obj.Dir * float(obj.LengthRev)
                    ext = cutted.extrude(obj.Dir *
                                         float(obj.LengthFwd + obj.LengthRev))
                    shapes.append(ext)
                else:
                    shapes.append(cutted)

        if len(shapes) == 1:
            fp.Shape = shapes[0]
        elif len(shapes) > 1:
            fp.Shape = Part.makeCompound(shapes)
Exemplo n.º 4
0
def __vol_cog(shape):
    vol = 0.0
    cog = Vector()
    for solid in shape.Solids:
        vol += solid.Volume
        sCoG = solid.CenterOfMass
        cog.x = cog.x + sCoG.x * solid.Volume
        cog.y = cog.y + sCoG.y * solid.Volume
        cog.z = cog.z + sCoG.z * solid.Volume
    cog.x = cog.x / vol
    cog.y = cog.y / vol
    cog.z = cog.z / vol
    return cog, vol
Exemplo n.º 5
0
def scaleByBoundbox(shape, boundbox, doScaleXYZ, copy=True):
    basebbox = shape.BoundBox
    #basebbox=[1.0,1.0,1.0]
    scalevec = Vector(1, 1, 1)
    if doScaleXYZ[0] and basebbox.XLength > epsilon:
        scalevec.x = boundbox.XLength / basebbox.XLength
    if doScaleXYZ[1] and basebbox.YLength > epsilon:
        scalevec.y = boundbox.YLength / basebbox.YLength
    if doScaleXYZ[2] and basebbox.ZLength > epsilon:
        scalevec.z = boundbox.ZLength / basebbox.ZLength

    scalevec.x = boundbox.XLength
    scalevec.y = boundbox.YLength
    scalevec.z = boundbox.ZLength

    if scalevec.x < epsilon:
        if doScaleXYZ[0]:
            scalevec.x = epsilon
        else:
            scalevec.x = 1
    if scalevec.y < epsilon:
        if doScaleXYZ[1]:
            scalevec.y = epsilon
        else:
            scalevec.y = 1
    if scalevec.z < epsilon:
        if doScaleXYZ[2]:
            scalevec.z = epsilon
        else:
            scalevec.z = 1

    _rib = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Rib00")
    print("Scale in scaleByBoundbox")
    print(scalevec)
    WingRib(
        _rib,
        "/Users/fredericnivoix/Library/Preferences/FreeCAD/Mod/AirPlaneDesign/wingribprofil/naca/naca2412.dat",
        False, 0, scalevec.x, 0, 0, 0, 0, 0, 0)
    ViewProviderWingRib(_rib.ViewObject)
    _rib.Placement = shape.Placement
    #dolly = scale(shape, scalevec, basebbox.Center, copy)
    #dolly.Placement = shape.Placement

    if doScaleXYZ[0]:
        _rib.Placement.Base.x += boundbox.XMin - basebbox.XMin * scalevec.x
    if doScaleXYZ[1]:
        _rib.Placement.Base.y += boundbox.YMin - basebbox.YMin * scalevec.y
    if doScaleXYZ[2]:
        _rib.Placement.Base.z += boundbox.ZMin - basebbox.ZMin * scalevec.z

    return _rib  #dolly
Exemplo n.º 6
0
    def getCoG(self, fp, vol, roll=Units.parseQuantity("0 deg"),
                              trim=Units.parseQuantity("0 deg")):
        """Return the fluid volume center of gravity, provided the volume of
        fluid inside the tank.

        The returned center of gravity is referred to the untransformed ship.

        Keyword arguments:
        fp -- Part::FeaturePython object affected.
        vol -- Volume of fluid.
        roll -- Ship roll angle.
        trim -- Ship trim angle.

        If the fluid volume is bigger than the total tank one, it will be
        conveniently clamped.
        """
        if vol <= 0.0:
            return Vector()
        if vol >= fp.Shape.Volume:
            vol = 0.0
            cog = Vector()
            for solid in fp.Shape.Solids:
                vol += solid.Volume
                sCoG = solid.CenterOfMass
                cog.x = cog.x + sCoG.x * solid.Volume
                cog.y = cog.y + sCoG.y * solid.Volume
                cog.z = cog.z + sCoG.z * solid.Volume
            cog.x = cog.x / vol
            cog.y = cog.y / vol
            cog.z = cog.z / vol
            return cog

        shape = self.getFluidShape(fp, vol, roll, trim)

        # Get the center of gravity
        vol = 0.0
        cog = Vector()
        if len(shape.Solids) > 0:
            for solid in shape.Solids:
                vol += solid.Volume
                sCoG = solid.CenterOfMass
                cog.x = cog.x + sCoG.x * solid.Volume
                cog.y = cog.y + sCoG.y * solid.Volume
                cog.z = cog.z + sCoG.z * solid.Volume
            cog.x = cog.x / vol
            cog.y = cog.y / vol
            cog.z = cog.z / vol

        return cog
Exemplo n.º 7
0
def _zoom_camera(self, use_bound_box=True):
    """
        Fancy routine to smooth zoom the camera
        """

    _camera = Gui.ActiveDocument.ActiveView.getCameraNode()

    _start_pos = Vector(_camera.position.getValue().getValue())
    _start_ht = _camera.height.getValue()

    _center = Vector(self.camera_state['position'])
    _height = self.camera_state['height']

    if use_bound_box:
        _bound_box = self.camera_state['bound box']
        #get the center of the camera, setting the z coordinate positive
        _center = Vector(_bound_box.Center)
        _center.z = 1.0
        #calculate the camera height = bounding box larger dim + 15%
        _height = _bound_box.XMax - _bound_box.XMin
        _dy = _bound_box.YMax - _bound_box.YMin
        if _dy > _height:
            _height = _dy

        _height += 0.15 * _height

    _frames = 60.0
    #calculate a total change value
    _pct_chg = abs(_height - _start_ht) / (_height + _start_ht)
    #at 50% change or more, use 60 frames,
    #otherwise scale frames to a minimum of 10 frames
    if _pct_chg < 0.5:
        _frames *= _pct_chg * 2.0
        if _frames < 10.0:
            _frames = 10.0

    #build cosine-based animation curve and reverse
    _steps = [
        math.cos((_i/_frames) * (math.pi/2.0)) * _frames\
            for _i in range(0, int(_frames))
    ]

    _steps = _steps[::-1]

    #calculate position and height deltas for transition loop
    _d_pos = _center - _start_pos
    _d_pos.multiply(1.0 / _frames)

    _d_ht = (_height - _start_ht) / _frames

    for _v in _steps:
        #set the camera
        Gui.ActiveDocument.ActiveView.getCameraNode().position.setValue(
            tuple(_start_pos + (_d_pos * _v)))
        Gui.ActiveDocument.ActiveView.getCameraNode().height.setValue(
            _start_ht + (_d_ht * _v))
        Gui.updateGui()
Exemplo n.º 8
0
def scaleByBoundbox2(shape, boundbox, doScaleXYZ):
    basebbox = shape.BoundBox
    scalevec = Vector(1, 1, 1)
    x = shape.Placement.Base.x
    y = shape.Placement.Base.y
    z = shape.Placement.Base.z
    if doScaleXYZ[0] and basebbox.XLength > epsilon:
        scalevec.x = boundbox.XLength / basebbox.XLength
    if doScaleXYZ[1] and basebbox.YLength > epsilon:
        scalevec.y = boundbox.YLength / basebbox.YLength
    if doScaleXYZ[2] and basebbox.ZLength > epsilon:
        scalevec.z = boundbox.ZLength / basebbox.ZLength

    scalevec.x = boundbox.XLength
    scalevec.y = boundbox.YLength
    scalevec.z = boundbox.ZLength

    if scalevec.x < epsilon:
        if doScaleXYZ[0]:
            scalevec.x = epsilon
        else:
            scalevec.x = 1
    if scalevec.y < epsilon:
        if doScaleXYZ[1]:
            scalevec.y = epsilon
        else:
            scalevec.y = 1
    if scalevec.z < epsilon:
        if doScaleXYZ[2]:
            scalevec.z = epsilon
        else:
            scalevec.z = 1

    if doScaleXYZ[0]:
        x += boundbox.XMin - basebbox.XMin * scalevec.x
    if doScaleXYZ[1]:
        y += boundbox.YMin - basebbox.YMin * scalevec.y
    if doScaleXYZ[2]:
        z += boundbox.ZMin - basebbox.ZMin * scalevec.z

    return x, y, z, scalevec.x, scalevec.y, scalevec.z
Exemplo n.º 9
0
def scaleByBoundbox(shape, boundbox, doScaleXYZ, copy=True):
    basebbox = shape.BoundBox

    scalevec = Vector(1, 1, 1)
    if basebbox.XLength > epsilon:
        scalevec.x = boundbox.XLength / basebbox.XLength
    if basebbox.YLength > epsilon:
        scalevec.y = boundbox.YLength / basebbox.YLength
    if basebbox.ZLength > epsilon:
        scalevec.z = boundbox.ZLength / basebbox.ZLength
    if scalevec.x < epsilon:
        if doScaleXYZ[0]:
            scalevec.x = epsilon
        else:
            scalevec.x = 1
    if scalevec.y < epsilon:
        if doScaleXYZ[1]:
            scalevec.y = epsilon
        else:
            scalevec.y = 1
    if scalevec.z < epsilon:
        if doScaleXYZ[2]:
            scalevec.z = epsilon
        else:
            scalevec.z = 1

    dolly = scale(shape, scalevec, basebbox.Center, copy)
    dolly.Placement = shape.Placement

    if doScaleXYZ[0]:
        dolly.Placement.Base.x += boundbox.XMin - basebbox.XMin * scalevec.x
    if doScaleXYZ[1]:
        dolly.Placement.Base.y += boundbox.YMin - basebbox.YMin * scalevec.y
    if doScaleXYZ[2]:
        dolly.Placement.Base.z += boundbox.ZMin - basebbox.ZMin * scalevec.z

    return dolly
Exemplo n.º 10
0
def findContactVoxelSurfaces(face,
                             condIndex,
                             gbbox,
                             delta,
                             voxelSpace=None,
                             createShell=False):
    ''' Find the voxel surface sides corresponding to the given contact surface
        (face) of an object. The object must have already been voxelized.
        
        'face' is the object face
        'condIndex' (integer) is the index of the object to which the face belongs.
                It defines the object conductivity.
        'gbbox' (FreeCAD.BoundBox) is the overall bounding box
        'delta' is the voxels size length
        'voxelSpace' (Numpy 3D array) is the voxel tensor of the overall space
        'createShell' (bool) creates a shell out of the contact faces
        
        Returns a list of surfaces in the format [x,y,z,voxside] where
        x, y, z are the voxel position indexes, while voxside is '+x', '-x',
        '+y', '-y', '+z', '-z' according the the impacted surface of the voxel
'''
    if voxelSpace == None:
        return
    surfList = []
    contactList = []
    # get the face's bbox
    bbox = face.BoundBox
    # now must find the voxel set that contains the face bounding box
    # with a certain slack - it could be the next voxel,
    # if the surface is at the boundary between voxels.
    # Find the voxel that contains the bbox min point
    min_x = int((bbox.XMin - gbbox.XMin) / delta) - 1
    min_y = int((bbox.YMin - gbbox.YMin) / delta) - 1
    min_z = int((bbox.ZMin - gbbox.ZMin) / delta) - 1
    # find the voxel that contains the bbox max point
    max_x = int((bbox.XMax - gbbox.XMin) / delta) + 1
    max_y = int((bbox.YMax - gbbox.YMin) / delta) + 1
    max_z = int((bbox.ZMax - gbbox.ZMin) / delta) + 1
    # debug
    #print(str(min_x)+" "+str(min_y)+" "+str(min_z)+" "+str(max_x)+" "+str(max_y)+" "+str(max_z))
    # create a Part.Vertex that we can use to test the distance
    # to the face (as it is a TopoShape)
    vec = FreeCAD.Vector(0, 0, 0)
    testVertex = Part.Vertex(vec)
    # this is half the side of the voxel
    halfdelta = delta / 2.0
    # small displacement w.r.t. delta
    epsdelta = delta / 100.0
    # array to find the six neighbour
    sides = [(1, 0, 0), (-1, 0, 0), (0, 1, 0), (0, -1, 0), (0, 0, 1),
             (0, 0, -1)]
    # string describing the side
    sideStrs = ['+x', '-x', '+y', '-y', '+z', '-z']
    # centers of the sides, with respect to the lower corner (with the smallest coordinates)
    sideCenters = [
        Vector(delta, halfdelta, halfdelta),
        Vector(0.0, halfdelta, halfdelta),
        Vector(halfdelta, delta, halfdelta),
        Vector(halfdelta, 0.0, halfdelta),
        Vector(halfdelta, halfdelta, delta),
        Vector(halfdelta, halfdelta, 0.0)
    ]
    # vertexes of the six faces (with a slight offset)
    vertexes = [[
        Vector(delta + epsdelta, 0, 0),
        Vector(delta + epsdelta, delta, 0),
        Vector(delta + epsdelta, delta, delta),
        Vector(delta + epsdelta, 0, delta)
    ],
                [
                    Vector(-epsdelta, 0, 0),
                    Vector(-epsdelta, 0, delta),
                    Vector(-epsdelta, delta, delta),
                    Vector(-epsdelta, delta, 0)
                ],
                [
                    Vector(0, delta + epsdelta, 0),
                    Vector(0, delta + epsdelta, delta),
                    Vector(delta, delta + epsdelta, delta),
                    Vector(delta, delta + epsdelta, 0)
                ],
                [
                    Vector(0, -epsdelta, 0),
                    Vector(delta, -epsdelta, 0),
                    Vector(delta, -epsdelta, delta),
                    Vector(0, -epsdelta, delta)
                ],
                [
                    Vector(0, 0, delta + epsdelta),
                    Vector(delta, 0, delta + epsdelta),
                    Vector(delta, delta, delta + epsdelta),
                    Vector(0, delta, delta + epsdelta)
                ],
                [
                    Vector(0, 0, -epsdelta),
                    Vector(0, delta, -epsdelta),
                    Vector(delta, delta, -epsdelta),
                    Vector(delta, 0, -epsdelta)
                ]]

    # and now iterate to find which voxel is inside the bounding box of the 'face',
    vbase = Vector(gbbox.XMin + min_x * delta, gbbox.YMin + min_y * delta,
                   gbbox.ZMin + min_z * delta)
    for step_x in range(min_x, max_x + 1):
        vbase.y = gbbox.YMin + min_y * delta
        for step_y in range(min_y, max_y + 1):
            vbase.z = gbbox.ZMin + min_z * delta
            for step_z in range(min_z, max_z + 1):
                # check if voxel is belonging to the given object
                if voxelSpace[step_x, step_y, step_z] == condIndex:
                    # scan the six neighbour voxels, to see if they are belonging to the same conductor or not.
                    # If they are not belonging to the same conductor, or if the voxel space is finished, the current voxel
                    # side in the direction of the empty voxel is an external surface
                    for side, sideStr, sideCenter, vertex in zip(
                            sides, sideStrs, sideCenters, vertexes):
                        is_surface = False
                        nextVoxelIndexes = [
                            step_x + side[0], step_y + side[1],
                            step_z + side[2]
                        ]
                        if (nextVoxelIndexes[0] > max_x
                                or nextVoxelIndexes[0] < 0
                                or nextVoxelIndexes[1] > max_y
                                or nextVoxelIndexes[1] < 0
                                or nextVoxelIndexes[2] > max_z
                                or nextVoxelIndexes[2] < 0):
                            is_surface = True
                        else:
                            if voxelSpace[nextVoxelIndexes[0],
                                          nextVoxelIndexes[1],
                                          nextVoxelIndexes[2]] != condIndex:
                                is_surface = True
                        if is_surface == True:
                            # debug
                            #print("pos_x="+str(vbase.x)+" pos_y="+str(vbase.y)+" pos_z="+str(vbase.z))
                            testVertex.Placement.Base = vbase + sideCenter
                            # if the point is close enough to the face, we consider
                            # the voxel surface as belonging to the voxelized face
                            dist = testVertex.distToShape(face)
                            # debug
                            #print(str(dist))
                            if abs(dist[0]) < halfdelta:
                                contactList.append(
                                    [step_x, step_y, step_z, sideStr])
                                if createShell:
                                    # create the face
                                    # calculate the vertexes
                                    v11 = vbase + vertex[0]
                                    v12 = vbase + vertex[1]
                                    v13 = vbase + vertex[2]
                                    v14 = vbase + vertex[3]
                                    # now make the face
                                    poly = Part.makePolygon(
                                        [v11, v12, v13, v14, v11])
                                    contFace = Part.Face(poly)
                                    surfList.append(contFace)
                vbase.z += delta
            vbase.y += delta
        vbase.x += delta
    contactShell = None
    if createShell:
        if surfList != []:
            # create a shell. Does not need to be solid.
            contactShell = Part.makeShell(surfList)
    return [contactList, contactShell]
Exemplo n.º 11
0
def createVoxelShell(obj, condIndex, gbbox, delta, voxelSpace=None):
    ''' Creates a shell composed by the external faces of a voxelized object.
    
        'obj' is the object whose shell must be created
        'condIndex' (integer) is the index of the object. It defines the object conductivity.
        'gbbox' (FreeCAD.BoundBox) is the overall bounding box
        'delta' is the voxels size length
        'voxelSpace' (Numpy 3D array) is the voxel tensor of the overall space 
'''
    if voxelSpace == None:
        return
    if not hasattr(obj, "Shape"):
        return
    surfList = []
    # get the object's bbox
    bbox = obj.Shape.BoundBox
    # now must find the voxel set that contains the object bounding box
    # find the voxel that contains the bbox min point
    min_x = int((bbox.XMin - gbbox.XMin) / delta)
    min_y = int((bbox.YMin - gbbox.YMin) / delta)
    min_z = int((bbox.ZMin - gbbox.ZMin) / delta)
    # find the voxel that contains the bbox max point
    max_x = int((bbox.XMax - gbbox.XMin) / delta)
    max_y = int((bbox.YMax - gbbox.YMin) / delta)
    max_z = int((bbox.ZMax - gbbox.ZMin) / delta)
    # this is half the side of the voxel
    halfdelta = delta / 2.0
    # array to find the six neighbour
    sides = [(1, 0, 0), (-1, 0, 0), (0, 1, 0), (0, -1, 0), (0, 0, 1),
             (0, 0, -1)]
    # vertexes of the six faces
    vertexes = [[
        Vector(delta, 0, 0),
        Vector(delta, delta, 0),
        Vector(delta, delta, delta),
        Vector(delta, 0, delta)
    ],
                [
                    Vector(0, 0, 0),
                    Vector(0, 0, delta),
                    Vector(0, delta, delta),
                    Vector(0, delta, 0)
                ],
                [
                    Vector(0, delta, 0),
                    Vector(0, delta, delta),
                    Vector(delta, delta, delta),
                    Vector(delta, delta, 0)
                ],
                [
                    Vector(0, 0, 0),
                    Vector(delta, 0, 0),
                    Vector(delta, 0, delta),
                    Vector(0, 0, delta)
                ],
                [
                    Vector(0, 0, delta),
                    Vector(delta, 0, delta),
                    Vector(delta, delta, delta),
                    Vector(0, delta, delta)
                ],
                [
                    Vector(0, 0, 0),
                    Vector(0, delta, 0),
                    Vector(delta, delta, 0),
                    Vector(delta, 0, 0)
                ]]
    # and now iterate to find which voxel is inside the object 'obj',
    # sampling based on the voxel centers
    vbase = Vector(gbbox.XMin + min_x * delta, gbbox.YMin + min_y * delta,
                   gbbox.ZMin + min_z * delta)
    for step_x in range(min_x, max_x + 1):
        vbase.y = gbbox.YMin + min_y * delta
        for step_y in range(min_y, max_y + 1):
            vbase.z = gbbox.ZMin + min_z * delta
            for step_z in range(min_z, max_z + 1):
                # check if voxel is belonging to the given object
                if voxelSpace[step_x, step_y, step_z] == condIndex:
                    # scan the six neighbour voxels, to see if they are belonging to the same conductor or not.
                    # If they are not belonging to the same conductor, or if the voxel space is finished, the current voxel
                    # side in the direction of the empty voxel is an external surface
                    for side, vertex in zip(sides, vertexes):
                        is_surface = False
                        nextVoxelIndexes = [
                            step_x + side[0], step_y + side[1],
                            step_z + side[2]
                        ]
                        if (nextVoxelIndexes[0] > max_x
                                or nextVoxelIndexes[0] < 0
                                or nextVoxelIndexes[1] > max_y
                                or nextVoxelIndexes[1] < 0
                                or nextVoxelIndexes[2] > max_z
                                or nextVoxelIndexes[2] < 0):
                            is_surface = True
                        else:
                            if voxelSpace[nextVoxelIndexes[0],
                                          nextVoxelIndexes[1],
                                          nextVoxelIndexes[2]] != condIndex:
                                is_surface = True
                        if is_surface == True:
                            # debug
                            #print("pos_x="+str(vbase.x)+" pos_y="+str(vbase.y)+" pos_z="+str(vbase.z))
                            # create the face
                            # calculate the vertexes
                            v11 = vbase + vertex[0]
                            v12 = vbase + vertex[1]
                            v13 = vbase + vertex[2]
                            v14 = vbase + vertex[3]
                            # now make the face
                            poly = Part.makePolygon([v11, v12, v13, v14, v11])
                            face = Part.Face(poly)
                            surfList.append(face)
                vbase.z += delta
            vbase.y += delta
        vbase.x += delta
    # create a shell. Does not need to be solid.
    objShell = Part.makeShell(surfList)
    return objShell
Exemplo n.º 12
0
    def getCoG(self,
               fp,
               vol,
               roll=Units.parseQuantity("0 deg"),
               trim=Units.parseQuantity("0 deg")):
        """Return the fluid volume center of gravity, provided the volume of
        fluid inside the tank.

        The returned center of gravity is refered to the untransformed ship.

        Keyword arguments:
        fp -- Part::FeaturePython object affected.
        vol -- Volume of fluid.
        roll -- Ship roll angle.
        trim -- Ship trim angle.

        If the fluid volume is bigger than the total tank one, it will be
        conveniently clamped.
        """
        # Change the units of the volume, and clamp the value
        if vol <= 0.0:
            return Vector()
        if vol >= fp.Shape.Volume:
            vol = 0.0
            for solid in fp.Shape.Solids:
                vol += solid.Volume
                sCoG = solid.CenterOfMass
                cog.x = cog.x + sCoG.x * solid.Volume
                cog.y = cog.y + sCoG.y * solid.Volume
                cog.z = cog.z + sCoG.z * solid.Volume
            cog.x = cog.x / vol
            cog.y = cog.y / vol
            cog.z = cog.z / vol
            return cog

        # Get a first estimation of the level
        level = vol.Value / fp.Shape.Volume

        # Transform the tank shape
        current_placement = fp.Placement
        m = current_placement.toMatrix()
        m.rotateX(roll.getValueAs("rad"))
        m.rotateY(-trim.getValueAs("rad"))
        fp.Placement = Placement(m)

        # Iterate to find the fluid shape
        for i in range(COMMON_BOOLEAN_ITERATIONS):
            shape = self.getVolume(fp, level, return_shape=True)
            error = (vol.Value - shape.Volume) / fp.Shape.Volume
            if abs(error) < 0.01:
                break
            level += error

        # Get the center of gravity
        vol = 0.0
        cog = Vector()
        if len(shape.Solids) > 0:
            for solid in shape.Solids:
                vol += solid.Volume
                sCoG = solid.CenterOfMass
                cog.x = cog.x + sCoG.x * solid.Volume
                cog.y = cog.y + sCoG.y * solid.Volume
                cog.z = cog.z + sCoG.z * solid.Volume
            cog.x = cog.x / vol
            cog.y = cog.y / vol
            cog.z = cog.z / vol

        # Untransform the object to retrieve the original position
        fp.Placement = current_placement
        p = Part.Point(cog)
        m = Matrix()
        m.rotateY(trim.getValueAs("rad"))
        m.rotateX(-roll.getValueAs("rad"))
        p.rotate(Placement(m))

        return Vector(p.X, p.Y, p.Z)
Exemplo n.º 13
0
def displacement(ship, draft, roll=0.0, trim=0.0, yaw=0.0):
    """ Compute the ship displacement.
    @param ship Ship instance.
    @param draft Ship draft.
    @param roll Ship roll angle.
    @param trim Ship trim angle.
    @param yaw Ship yaw angle. Ussually you don't want to use this
     value.
    @return [disp, B, Cb], \n
      - disp = Ship displacement [ton].
      - B = Bouyance center [m].
      - Cb = Block coefficient.
    @note Bouyance center will returned as a FreeCAD.Vector instance.
    @note Returned Bouyance center is in the non modified ship coordinates
    """
    # We will take a duplicate of ship shape in order to conviniently
    # manipulate it
    shape = ship.Shape.copy()

    shape.translate(Vector(0.0, 0.0, -draft * Units.Metre.Value))
    shape.rotate(Vector(0.0, 0.0, 0.0), Vector(1.0, 0.0, 0.0), roll)
    shape.rotate(Vector(0.0, 0.0, 0.0), Vector(0.0, -1.0, 0.0), trim)
    shape.rotate(Vector(0.0, 0.0, 0.0), Vector(0.0, 0.0, 1.0), yaw)

    bbox = shape.BoundBox
    xmin = bbox.XMin
    xmax = bbox.XMax
    # Create the "sea" box to intersect the ship
    L = xmax - xmin
    B = bbox.YMax - bbox.YMin
    p = Vector(-1.5 * L, -1.5 * B, bbox.ZMin - 1.0)
    try:
        box = Part.makeBox(3.0 * L, 3.0 * B, -bbox.ZMin + 1.0, p)
    except:
        return [0.0, Vector(), 0.0]

    vol = 0.0
    cog = Vector()
    for solid in shape.Solids:
        # Compute the common part of the "sea" with the ship
        try:
            common = box.common(solid)
        except:
            continue
        # Get the data
        vol = vol + common.Volume / Units.Metre.Value**3
        for s in common.Solids:
            sCoG = s.CenterOfMass
            cog.x = cog.x + sCoG.x * s.Volume / Units.Metre.Value**4
            cog.y = cog.y + sCoG.y * s.Volume / Units.Metre.Value**4
            cog.z = cog.z + sCoG.z * s.Volume / Units.Metre.Value**4
    cog.x = cog.x / vol
    cog.y = cog.y / vol
    cog.z = cog.z / vol
    Vol = L * B * abs(bbox.ZMin) / Units.Metre.Value**3
    # Undo the transformations
    B = Vector()
    B.x = cog.x * math.cos(math.radians(-yaw)) - \
        cog.y * math.sin(math.radians(-yaw))
    B.y = cog.x * math.sin(math.radians(-yaw)) + \
        cog.y * math.cos(math.radians(-yaw))
    B.z = cog.z
    cog.x = B.x * math.cos(math.radians(-trim)) - \
        B.z * math.sin(math.radians(-trim))
    cog.y = B.y
    cog.z = B.x * math.sin(math.radians(-trim)) + \
        B.z * math.cos(math.radians(-trim))
    B.x = cog.x
    B.y = cog.y * math.cos(math.radians(-roll)) - \
        cog.z * math.sin(math.radians(-roll))
    B.z = cog.y * math.sin(math.radians(-roll)) + \
        cog.z * math.cos(math.radians(-roll))
    B.z = B.z + draft
    # Return the computed data
    dens = 1.025  # [tons/m3], salt water
    return [dens * vol, B, vol / Vol]
Exemplo n.º 14
0
def displacement(ship, draft, roll=0.0, trim=0.0, yaw=0.0):
    """ Compute ship displacement.
    @param ship Ship instance.
    @param draft Ship draft.
    @param roll Ship roll angle.
    @param trim Ship trim angle.
    @param yaw Ship yaw angle. Ussually you don't want to use this 
    value.
    @return [disp, B, Cb], \n
    disp = Ship displacement [ton].
    B    = Bouyance center [m].
    Cb   = Block coefficient.
    @note Bouyance center will returned as FreeCAD.Vector class.
    @note Returned Bouyance center is in non modified ship coordinates
    """
    # We will take a duplicate of ship shape in order to place it
    shape = ship.Shape.copy()
    shape.translate(Vector(0.0,0.0,-draft))
    # Rotations composition is Roll->Trim->Yaw
    shape.rotate(Vector(0.0,0.0,0.0), Vector(1.0,0.0,0.0), roll)
    shape.rotate(Vector(0.0,0.0,0.0), Vector(0.0,-1.0,0.0), trim)
    shape.rotate(Vector(0.0,0.0,0.0), Vector(0.0,0.0,1.0), yaw)
    # Now we need to know box dimensions
    bbox = shape.BoundBox
    xmin = bbox.XMin
    xmax = bbox.XMax
    # Create the box
    L = xmax - xmin
    B = bbox.YMax - bbox.YMin
    p = Vector(-1.5*L, -1.5*B, bbox.ZMin - 1.0)
    box = Part.makeBox(3.0*L, 3.0*B, -bbox.ZMin + 1.0, p)
    vol = 0.0
    cog = Vector()
    for solid in shape.Solids:
        # Compute common part with ship
        try:
            common = box.common(solid)
        except:
            continue
        # Get data
        vol = vol + common.Volume
        for s in common.Solids:
            sCoG  = s.CenterOfMass
            cog.x = cog.x + sCoG.x*s.Volume
            cog.y = cog.y + sCoG.y*s.Volume
            cog.z = cog.z + sCoG.z*s.Volume
    cog.x = cog.x / vol
    cog.y = cog.y / vol
    cog.z = cog.z / vol
    Vol = L*B*abs(bbox.ZMin)
    # Undo transformations
    B   = Vector()
    B.x = cog.x*math.cos(math.radians(-yaw)) - cog.y*math.sin(math.radians(-yaw))
    B.y = cog.x*math.sin(math.radians(-yaw)) + cog.y*math.cos(math.radians(-yaw))
    B.z = cog.z
    cog.x = B.x*math.cos(math.radians(-trim)) - B.z*math.sin(math.radians(-trim))
    cog.y = B.y
    cog.z = B.x*math.sin(math.radians(-trim)) + B.z*math.cos(math.radians(-trim))
    B.x = cog.x
    B.y = cog.y*math.cos(math.radians(-roll)) - cog.z*math.sin(math.radians(-roll))
    B.z = cog.y*math.sin(math.radians(-roll)) + cog.z*math.cos(math.radians(-roll))
    B.z = B.z + draft
    # Return data
    dens = 1.025 # [tons/m3], salt water
    return [dens*vol, B, vol/Vol]
Exemplo n.º 15
0
    def getCoG(self, fp, vol, roll=Units.parseQuantity("0 deg"),
                              trim=Units.parseQuantity("0 deg")):
        """Return the fluid volume center of gravity, provided the volume of
        fluid inside the tank.

        The returned center of gravity is referred to the untransformed ship.

        Keyword arguments:
        fp -- Part::FeaturePython object affected.
        vol -- Volume of fluid.
        roll -- Ship roll angle.
        trim -- Ship trim angle.

        If the fluid volume is bigger than the total tank one, it will be
        conveniently clamped.
        """
        # Change the units of the volume, and clamp the value
        if vol <= 0.0:
            return Vector()
        if vol >= fp.Shape.Volume:
            vol = 0.0
            for solid in fp.Shape.Solids:
                vol += solid.Volume
                sCoG = solid.CenterOfMass
                cog.x = cog.x + sCoG.x * solid.Volume
                cog.y = cog.y + sCoG.y * solid.Volume
                cog.z = cog.z + sCoG.z * solid.Volume
            cog.x = cog.x / vol
            cog.y = cog.y / vol
            cog.z = cog.z / vol
            return cog

        # Get a first estimation of the level
        level = vol.Value / fp.Shape.Volume

        # Transform the tank shape
        current_placement = fp.Placement
        m = current_placement.toMatrix()
        m.rotateX(roll.getValueAs("rad"))
        m.rotateY(-trim.getValueAs("rad"))
        fp.Placement = Placement(m)

        # Iterate to find the fluid shape
        for i in range(COMMON_BOOLEAN_ITERATIONS):
            shape = self.getVolume(fp, level, return_shape=True)
            error = (vol.Value - shape.Volume) / fp.Shape.Volume
            if abs(error) < 0.01:
                break
            level += error

        # Get the center of gravity
        vol = 0.0
        cog = Vector()
        if len(shape.Solids) > 0:
            for solid in shape.Solids:
                vol += solid.Volume
                sCoG = solid.CenterOfMass
                cog.x = cog.x + sCoG.x * solid.Volume
                cog.y = cog.y + sCoG.y * solid.Volume
                cog.z = cog.z + sCoG.z * solid.Volume
            cog.x = cog.x / vol
            cog.y = cog.y / vol
            cog.z = cog.z / vol

        # Untransform the object to retrieve the original position
        fp.Placement = current_placement
        p = Part.Point(cog)
        m = Matrix()
        m.rotateY(trim.getValueAs("rad"))
        m.rotateX(-roll.getValueAs("rad"))
        p.rotate(Placement(m))

        return Vector(p.X, p.Y, p.Z)
Exemplo n.º 16
0
    def makeRibs(self, obj):
        pl = obj.Placement
        ribs = []
        curvebox = FreeCAD.BoundBox(float("-inf"), float("-inf"),
                                    float("-inf"), float("inf"), float("inf"),
                                    float("inf"))

        for n in range(0, len(obj.Hullcurves)):
            cbbx = obj.Hullcurves[n].Shape.BoundBox
            if self.doScaleXYZ[n][0]:
                if cbbx.XMin > curvebox.XMin: curvebox.XMin = cbbx.XMin
                if cbbx.XMax < curvebox.XMax: curvebox.XMax = cbbx.XMax
            if self.doScaleXYZ[n][1]:
                if cbbx.YMin > curvebox.YMin: curvebox.YMin = cbbx.YMin
                if cbbx.YMax < curvebox.YMax: curvebox.YMax = cbbx.YMax
            if self.doScaleXYZ[n][2]:
                if cbbx.ZMin > curvebox.ZMin: curvebox.ZMin = cbbx.ZMin
                if cbbx.ZMax < curvebox.ZMax: curvebox.ZMax = cbbx.ZMax

        if curvebox.XMin == float("-inf"):
            curvebox.XMin = obj.Hullcurves[0].Shape.BoundBox.XMin
        if curvebox.XMax == float("inf"):
            curvebox.XMax = obj.Hullcurves[0].Shape.BoundBox.XMax
        if curvebox.YMin == float("-inf"):
            curvebox.YMin = obj.Hullcurves[0].Shape.BoundBox.YMin
        if curvebox.YMax == float("inf"):
            curvebox.YMax = obj.Hullcurves[0].Shape.BoundBox.YMax
        if curvebox.ZMin == float("-inf"):
            curvebox.ZMin = obj.Hullcurves[0].Shape.BoundBox.ZMin
        if curvebox.ZMax == float("inf"):
            curvebox.ZMax = obj.Hullcurves[0].Shape.BoundBox.ZMax

        areavec = Vector(curvebox.XLength, curvebox.YLength, curvebox.ZLength)
        deltavec = areavec.scale(
            obj.Axis.x, obj.Axis.y,
            obj.Axis.z) - (obj.OffsetStart + obj.OffsetEnd) * obj.Axis
        sections = int(obj.Items)
        startvec = Vector(curvebox.XMin, curvebox.YMin, curvebox.ZMin)
        if obj.Axis.x < 0: startvec.x = curvebox.XMax
        if obj.Axis.y < 0: startvec.y = curvebox.YMax
        if obj.Axis.z < 0: startvec.z = curvebox.ZMax
        pos0 = startvec + (obj.OffsetStart * obj.Axis)

        if (not hasattr(obj, "Positions") or len(obj.Positions) == 0):
            for x in range(0, sections):
                if sections > 1:
                    d = CurvedShapes.distribute(x / (sections - 1),
                                                obj.Distribution,
                                                obj.DistributionReverse)

                    posvec = pos0 + (deltavec * d)
                else:
                    posvec = pos0

                dolly = self.makeRib(obj, posvec)
                if dolly:
                    if not obj.Twist == 0:
                        dolly.rotate(
                            dolly.BoundBox.Center, obj.Axis,
                            obj.Twist * posvec.Length / areavec.Length)
                    ribs.append(dolly)
        else:
            for p in obj.Positions:
                posvec = pos0 + (deltavec * p)

                dolly = self.makeRib(obj, posvec)
                if dolly:
                    if not obj.Twist == 0:
                        dolly.rotate(
                            dolly.BoundBox.Center, obj.Axis,
                            obj.Twist * posvec.Length / areavec.Length)
                    ribs.append(dolly)

        if (obj.Surface or obj.Solid) and obj.Items > 1:
            obj.Shape = CurvedShapes.makeSurfaceSolid(ribs, obj.Solid)
        else:
            obj.Shape = Part.makeCompound(ribs)

        obj.Placement = pl

        if self.extract:
            CompoundTools.Explode.explodeCompound(obj)
            obj.ViewObject.hide()
Exemplo n.º 17
0
def displacement(ship,
                 draft=None,
                 roll=Units.parseQuantity("0 deg"),
                 trim=Units.parseQuantity("0 deg")):
    """Compute the ship displacement

    Position arguments:
    ship -- Ship object (see createShip)

    Keyword arguments:
    draft -- Ship draft (Design ship draft by default)
    roll -- Roll angle (0 degrees by default)
    trim -- Trim angle (0 degrees by default)

    Returned values:
    disp -- The ship displacement (a density of the water of 1025 kg/m^3 is
    assumed)
    B -- Bouyance application point, i.e. Center of mass of the underwater side
    Cb -- Block coefficient

    The Bouyance center is referred to the original ship position.
    """
    if draft is None:
        draft = ship.Draft

    shape, base_z = placeShipShape(ship.Shape.copy(), draft, roll, trim)
    shape = getUnderwaterSide(shape)

    vol = 0.0
    cog = Vector()
    if len(shape.Solids) > 0:
        for solid in shape.Solids:
            vol += solid.Volume
            sCoG = solid.CenterOfMass
            cog.x = cog.x + sCoG.x * solid.Volume
            cog.y = cog.y + sCoG.y * solid.Volume
            cog.z = cog.z + sCoG.z * solid.Volume
        cog.x = cog.x / vol
        cog.y = cog.y / vol
        cog.z = cog.z / vol

    bbox = shape.BoundBox
    Vol = (bbox.XMax - bbox.XMin) * (bbox.YMax - bbox.YMin) * abs(bbox.ZMin)

    # Undo the transformations on the bouyance point
    B = Part.Point(Vector(cog.x, cog.y, cog.z))
    m = Matrix()
    m.move(Vector(0.0, 0.0, draft))
    m.move(Vector(-draft * math.sin(trim.getValueAs("rad")), 0.0, 0.0))
    m.rotateY(trim.getValueAs("rad"))
    m.move(Vector(0.0, -draft * math.sin(roll.getValueAs("rad")), base_z))
    m.rotateX(-roll.getValueAs("rad"))
    B.transform(m)

    try:
        cb = vol / Vol
    except ZeroDivisionError:
        msg = QtGui.QApplication.translate(
            "ship_console",
            "ZeroDivisionError: Null volume found during the displacement"
            " computation!", None)
        App.Console.PrintError(msg + '\n')
        cb = 0.0

    # Return the computed data
    return (DENS * Units.Quantity(vol, Units.Volume), Vector(B.X, B.Y,
                                                             B.Z), cb)
Exemplo n.º 18
0
def displacement(ship, draft, roll=0.0, trim=0.0, yaw=0.0):
    """ Compute ship displacement.
	@param ship Ship instance.
	@param draft Ship draft.
	@param roll Ship roll angle.
	@param trim Ship trim angle.
	@param yaw Ship yaw angle. Ussually you don't want to use this 
	value.
	@return [disp, B, Cb], \n
	disp = Ship displacement [ton].
	B	= Bouyance center [m].
	Cb   = Block coefficient.
	@note Bouyance center will returned as FreeCAD.Vector class.
	@note Returned Bouyance center is in non modified ship coordinates
	"""
    # We will take a duplicate of ship shape in order to place it
    shape = ship.Shape.copy()
    shape.translate(Vector(0.0, 0.0, -draft))
    # Rotations composition is Roll->Trim->Yaw
    shape.rotate(Vector(0.0, 0.0, 0.0), Vector(1.0, 0.0, 0.0), roll)
    shape.rotate(Vector(0.0, 0.0, 0.0), Vector(0.0, -1.0, 0.0), trim)
    shape.rotate(Vector(0.0, 0.0, 0.0), Vector(0.0, 0.0, 1.0), yaw)
    # Now we need to know box dimensions
    bbox = shape.BoundBox
    xmin = bbox.XMin
    xmax = bbox.XMax
    # Create the box
    L = xmax - xmin
    B = bbox.YMax - bbox.YMin
    p = Vector(-1.5 * L, -1.5 * B, bbox.ZMin - 1.0)
    box = Part.makeBox(3.0 * L, 3.0 * B, -bbox.ZMin + 1.0, p)
    vol = 0.0
    cog = Vector()
    for solid in shape.Solids:
        # Compute common part with ship
        try:
            common = box.common(solid)
        except:
            continue
        # Get data
        vol = vol + common.Volume
        for s in common.Solids:
            sCoG = s.CenterOfMass
            cog.x = cog.x + sCoG.x * s.Volume
            cog.y = cog.y + sCoG.y * s.Volume
            cog.z = cog.z + sCoG.z * s.Volume
    cog.x = cog.x / vol
    cog.y = cog.y / vol
    cog.z = cog.z / vol
    Vol = L * B * abs(bbox.ZMin)
    # Undo transformations
    B = Vector()
    B.x = cog.x * math.cos(math.radians(-yaw)) - cog.y * math.sin(
        math.radians(-yaw))
    B.y = cog.x * math.sin(math.radians(-yaw)) + cog.y * math.cos(
        math.radians(-yaw))
    B.z = cog.z
    cog.x = B.x * math.cos(math.radians(-trim)) - B.z * math.sin(
        math.radians(-trim))
    cog.y = B.y
    cog.z = B.x * math.sin(math.radians(-trim)) + B.z * math.cos(
        math.radians(-trim))
    B.x = cog.x
    B.y = cog.y * math.cos(math.radians(-roll)) - cog.z * math.sin(
        math.radians(-roll))
    B.z = cog.y * math.sin(math.radians(-roll)) + cog.z * math.cos(
        math.radians(-roll))
    B.z = B.z + draft
    # Return data
    dens = 1.025  # [tons/m3], salt water
    return [dens * vol, B, vol / Vol]
Exemplo n.º 19
0
def displacement(ship, draft, roll=0.0, trim=0.0, yaw=0.0):
    """ Compute the ship displacement.
    @param ship Ship instance.
    @param draft Ship draft.
    @param roll Ship roll angle.
    @param trim Ship trim angle.
    @param yaw Ship yaw angle. Ussually you don't want to use this
     value.
    @return [disp, B, Cb], \n
      - disp = Ship displacement [ton].
      - B = Bouyance center [m].
      - Cb = Block coefficient.
    @note Bouyance center will returned as a FreeCAD.Vector instance.
    @note Returned Bouyance center is in the non modified ship coordinates
    """
    # We will take a duplicate of ship shape in order to conviniently
    # manipulate it
    shape = ship.Shape.copy()

    shape.translate(Vector(0.0, 0.0, -draft * Units.Metre.Value))
    shape.rotate(Vector(0.0, 0.0, 0.0), Vector(1.0, 0.0, 0.0), roll)
    shape.rotate(Vector(0.0, 0.0, 0.0), Vector(0.0, -1.0, 0.0), trim)
    shape.rotate(Vector(0.0, 0.0, 0.0), Vector(0.0, 0.0, 1.0), yaw)

    bbox = shape.BoundBox
    xmin = bbox.XMin
    xmax = bbox.XMax
    # Create the "sea" box to intersect the ship
    L = xmax - xmin
    B = bbox.YMax - bbox.YMin
    p = Vector(-1.5*L, -1.5*B, bbox.ZMin - 1.0)
    try:
        box = Part.makeBox(3.0*L, 3.0*B, - bbox.ZMin + 1.0, p)
    except:
        return [0.0, Vector(), 0.0]

    vol = 0.0
    cog = Vector()
    for solid in shape.Solids:
        # Compute the common part of the "sea" with the ship
        try:
            common = box.common(solid)
        except:
            continue
        # Get the data
        vol = vol + common.Volume / Units.Metre.Value**3
        for s in common.Solids:
            sCoG = s.CenterOfMass
            cog.x = cog.x + sCoG.x * s.Volume / Units.Metre.Value**4
            cog.y = cog.y + sCoG.y * s.Volume / Units.Metre.Value**4
            cog.z = cog.z + sCoG.z * s.Volume / Units.Metre.Value**4
    cog.x = cog.x / vol
    cog.y = cog.y / vol
    cog.z = cog.z / vol
    Vol = L * B * abs(bbox.ZMin) / Units.Metre.Value**3
    # Undo the transformations
    B = Vector()
    B.x = cog.x * math.cos(math.radians(-yaw)) - \
        cog.y * math.sin(math.radians(-yaw))
    B.y = cog.x * math.sin(math.radians(-yaw)) + \
        cog.y * math.cos(math.radians(-yaw))
    B.z = cog.z
    cog.x = B.x * math.cos(math.radians(-trim)) - \
        B.z * math.sin(math.radians(-trim))
    cog.y = B.y
    cog.z = B.x * math.sin(math.radians(-trim)) + \
        B.z * math.cos(math.radians(-trim))
    B.x = cog.x
    B.y = cog.y * math.cos(math.radians(-roll)) - \
        cog.z * math.sin(math.radians(-roll))
    B.z = cog.y * math.sin(math.radians(-roll)) + \
        cog.z * math.cos(math.radians(-roll))
    B.z = B.z + draft
    # Return the computed data
    dens = 1.025  # [tons/m3], salt water
    return [dens*vol, B, vol/Vol]
Exemplo n.º 20
0
def displacement(ship, draft=None,
                       roll=Units.parseQuantity("0 deg"), 
                       trim=Units.parseQuantity("0 deg")):
    """Compute the ship displacement

    Position arguments:
    ship -- Ship object (see createShip)

    Keyword arguments:
    draft -- Ship draft (Design ship draft by default)
    roll -- Roll angle (0 degrees by default)
    trim -- Trim angle (0 degrees by default)

    Returned values:
    disp -- The ship displacement (a density of the water of 1025 kg/m^3 is
    assumed)
    B -- Bouyance application point, i.e. Center of mass of the underwater side
    Cb -- Block coefficient

    The Bouyance center is refered to the original ship position.
    """
    if draft is None:
        draft = ship.Draft

    shape, base_z = placeShipShape(ship.Shape.copy(), draft, roll, trim)
    shape = getUnderwaterSide(shape)

    vol = 0.0
    cog = Vector()
    if len(shape.Solids) > 0:
        for solid in shape.Solids:
            vol += solid.Volume
            sCoG = solid.CenterOfMass
            cog.x = cog.x + sCoG.x * solid.Volume
            cog.y = cog.y + sCoG.y * solid.Volume
            cog.z = cog.z + sCoG.z * solid.Volume
        cog.x = cog.x / vol
        cog.y = cog.y / vol
        cog.z = cog.z / vol

    bbox = shape.BoundBox
    Vol = (bbox.XMax - bbox.XMin) * (bbox.YMax - bbox.YMin) * abs(bbox.ZMin)

    # Undo the transformations on the bouyance point
    B = Part.Point(Vector(cog.x, cog.y, cog.z))
    m = Matrix()
    m.move(Vector(0.0, 0.0, draft))
    m.move(Vector(-draft * math.sin(trim.getValueAs("rad")), 0.0, 0.0))
    m.rotateY(trim.getValueAs("rad"))
    m.move(Vector(0.0,
                  -draft * math.sin(roll.getValueAs("rad")),
                  base_z))
    m.rotateX(-roll.getValueAs("rad"))
    B.transform(m)

    try:
        cb = vol / Vol
    except ZeroDivisionError:
        msg = QtGui.QApplication.translate(
            "ship_console",
            "ZeroDivisionError: Null volume found during the displacement"
            " computation!",
            None,
            QtGui.QApplication.UnicodeUTF8)
        App.Console.PrintError(msg + '\n')
        cb = 0.0


    # Return the computed data
    return (DENS * Units.Quantity(vol, Units.Volume),
            Vector(B.X, B.Y, B.Z),
            cb)
Exemplo n.º 21
0
def create_compartment(box, 
                       direction, 
                       offset, 
                       materialWidth, 
                       notchWidth, 
                       drawSides=[True, True, True, True, True, True],
                       doc = app.activeDocument()):
    
    cpos = direction * offset
    mybox = None
    if len(box) == 1 and hasattr(box[0], 'Links'):
        parts = box[0].Links
        mybox = box[0]
    elif isinstance(box, list):
        parts = box
    else:
        parts = [box]
        
    boxsize = Vector(0, 0, 0)
    for side in parts:
        if hasattr(side, 'Shape'):
            bbox = side.Shape.BoundBox
            if bbox.XLength > boxsize.x: boxsize.x = bbox.XLength
            if bbox.YLength > boxsize.y: boxsize.y = bbox.YLength
            if bbox.ZLength > boxsize.z: boxsize.z = bbox.ZLength
            
    holes = []
    if direction == Vector(1, 0, 0):
        if boxsize.z == 0 or boxsize.y == 0:
            app.Console.PrintError("select a box first !\n")
            return
        compartment = draw_left(doc, 'compartmentX' + str(offset), materialWidth, boxsize.z, boxsize.y, notchWidth, drawSides)
        if drawSides[4] or drawSides[5]:
            holes += draw_holes(boxsize.y, notchWidth, materialWidth, Vector(0, 0, 90))
        if drawSides[2] or drawSides[3]:
            holes += draw_holes(boxsize.z, notchWidth, materialWidth, Vector(90, 0, 90))
        
        for h in holes:
            h.Placement.Base.x += offset + materialWidth
            
    elif direction == Vector(0, 1, 0):
        if boxsize.z == 0 or boxsize.x == 0:
            app.Console.PrintError("select a box first !\n")
            return
        
        sides = [drawSides[0], drawSides[1], drawSides[4], drawSides[5], drawSides[2], drawSides[3]]
        compartment = draw_left(doc, 'compartmentY' + str(offset), materialWidth, boxsize.z, boxsize.x, notchWidth, sides)
        doc.recompute()
        Draft.rotate([compartment], 270.0, Vector(0, 0, 0), axis=Vector(0.0, 0.0, 1.0), copy=False)
        doc.recompute()
        Draft.move([compartment], Vector(0, materialWidth, 0), copy=False)    
        doc.recompute()
        if drawSides[0] or drawSides[1]:
            holes += draw_holes(boxsize.x, notchWidth, materialWidth, Vector(0, 0, 0))
        if drawSides[2] or drawSides[3]:
            holes += draw_holes(boxsize.z, notchWidth, materialWidth, Vector(0, 270, 0))
        
        for h in holes:
            h.Placement.Base.y += offset
            
    elif direction == Vector(0, 0, 1):
        if boxsize.x == 0 or boxsize.y == 0:
            app.Console.PrintError("select a box first !\n")
            return
        
        sides = [drawSides[2], drawSides[3], drawSides[0], drawSides[1], drawSides[4], drawSides[5]]
        compartment = draw_left(doc, 'compartmentZ' + str(offset), materialWidth, boxsize.x, boxsize.y, notchWidth, sides)
        doc.recompute()
        Draft.rotate([compartment], 270.0, Vector(boxsize.x, 0, 0), axis=Vector(0.0, 1.0, 0.0), copy=False)
        doc.recompute()
        Draft.move([compartment], Vector(0, 0, boxsize.x), copy=False)   
        doc.recompute() 
        if drawSides[0] or drawSides[1]:
            holes += draw_holes(boxsize.x, notchWidth, materialWidth, Vector(270, 0, 0))
        if drawSides[4] or drawSides[5]:
            holes += draw_holes(boxsize.y, notchWidth, materialWidth, Vector(0, 270, 90))
        
        for h in holes:
            h.Placement.Base.z += offset + materialWidth
    else:
        return None
    
    Draft.move([compartment], cpos, copy=False)    
    
    doc.recompute()
    addLinesToBoxSide(parts, holes)            
            
    if mybox:
        compartment.adjustRelativeLinks(mybox)
        mybox.ViewObject.dropObject(compartment, None, '', [])
        doc.recompute()
        return mybox
    
    doc.recompute()
    return compartment