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 pointInversion(circle, point):
    """Circle inversion of a point.

    pointInversion(Circle, Vector)

    Will calculate the inversed point an return it.
    If the given point is equal to the center of the circle "None" will be returned.

    See also:
    http://en.wikipedia.org/wiki/Inversive_geometry
    """
    if (geomType(circle) == "Circle") and isinstance(point, FreeCAD.Vector):
        cen = circle.Curve.Center
        rad = circle.Curve.Radius

        if DraftVecUtils.equals(cen, point):
            return None

        # Inverse the distance of the point
        # dist(cen -> P) = r^2 / dist(cen -> invP)

        dist = DraftVecUtils.dist(point, cen)
        invDist = rad**2 / d

        invPoint = Vector(0, 0, point.z)
        invPoint.x = cen.x + (point.x - cen.x) * invDist / dist
        invPoint.y = cen.y + (point.y - cen.y) * invDist / dist

        return invPoint

    else:
        FreeCAD.Console.PrintMessage("debug: pointInversion bad parameters!\n")
        return None
Exemplo n.º 8
0
def checkLimit(v: FreeCAD.Vector, PressureAngleOffset, minrad, maxrad):
    """ if x,y outside limit return x,y as at limit, else return x,y
        :type v: FreeCAD.Vector """
    r, a = toPolar(v.x, v.y)
    if (r > maxrad) or (r < minrad):
        r = r - PressureAngleOffset
        v.x, v.y = toRect(r, a)
    return v
Exemplo n.º 9
0
def check_limit(v: FreeCAD.Vector, pressure_angle_offset, minrad, maxrad):
    """ if x,y outside limit return x,y as at limit, else return x,y
        :type v: FreeCAD.Vector """
    r, a = to_polar(v.x, v.y)
    if (r > maxrad) or (r < minrad):
        r = r - pressure_angle_offset
        v.x, v.y = to_rect(r, a)
    return v
Exemplo n.º 10
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.º 11
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.º 12
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.º 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 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.º 15
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.º 16
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.º 17
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
Exemplo n.º 18
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.º 19
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.º 20
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.º 21
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)