Ejemplo n.º 1
0
def rotate(u,angle,axis=Vector(0,0,1)):
    '''rotate(Vector,Float,axis=Vector): rotates the first Vector
    around the given axis, at the given angle.
    If axis is omitted, the rotation is made on the xy plane.'''
    typecheck ([(u,Vector), (angle,(int,float)), (axis,Vector)], "rotate")

    if angle == 0: 
        return u

    l=axis.Length
    x=axis.x/l
    y=axis.y/l
    z=axis.z/l
    c = math.cos(angle)
    s = math.sin(angle)
    t = 1 - c

    xyt = x*y*t
    xzt = x*z*t
    yzt = y*z*t
    xs = x*s
    ys = y*s
    zs = z*s

    m = Matrix(c + x*x*t,   xyt - zs,   xzt + ys,   0,
               xyt + zs,    c + y*y*t,  yzt - xs,   0,
               xzt - ys,    yzt + xs,   c + z*z*t,  0)

    return m.multiply(u)
Ejemplo n.º 2
0
def rotate(u, angle, axis=Vector(0, 0, 1)):
    '''rotate(Vector,Float,axis=Vector): rotates the first Vector
    around the given axis, at the given angle.
    If axis is omitted, the rotation is made on the xy plane.'''
    typecheck([(u, Vector), (angle, (int, long, float)), (axis, Vector)],
              "rotate")

    if angle == 0:
        return u

    l = axis.Length
    x = axis.x / l
    y = axis.y / l
    z = axis.z / l
    c = math.cos(angle)
    s = math.sin(angle)
    t = 1 - c

    xyt = x * y * t
    xzt = x * z * t
    yzt = y * z * t
    xs = x * s
    ys = y * s
    zs = z * s

    m = Matrix(c + x * x * t, xyt - zs, xzt + ys, 0, xyt + zs, c + y * y * t,
               yzt - xs, 0, xzt - ys, yzt + xs, c + z * z * t, 0)

    return m.multiply(u)
Ejemplo n.º 3
0
    def test_from_matrix(self):
        from FreeCAD import Matrix

        # identity
        self.assertEqual(CoordSystem.from_transform(Matrix()), CoordSystem())

        # random #1
        m = Matrix(-0.146655, -0.271161, -0.951296, 0.0376659, -0.676234,
                   0.729359, -0.103649, 0.615421, 0.721942, 0.628098,
                   -0.290333, -0.451955, 0, 0, 0, 1)
        cs = CoordSystem.from_transform(m)
        self.assertEqual(
            cs,
            CoordSystem(
                origin=(0.0376659, 0.615421, -0.451955),
                xDir=(-0.14665525299526946, -0.6762339076811328,
                      0.7219417835748246),
                normal=(-0.9512957880009034, -0.10364897690151711,
                        -0.2903329352984416),
            ))

        # random #2
        m = Matrix(0.423408, -0.892837, -0.153517, -0.163654, -0.617391,
                   -0.408388, 0.672345, 0.835824, -0.662989, -0.189896,
                   -0.724144, 0.632804, 0, 0, 0, 1)
        cs = CoordSystem.from_transform(m)
        self.assertEqual(
            cs,
            CoordSystem(
                origin=(-0.163654, 0.835824, 0.632804),
                xDir=(0.4234078285564432, -0.6173904937335437,
                      -0.6629892826920875),
                normal=(-0.15351701527110584, 0.672345066881529,
                        -0.7241440720342351),
            ))
Ejemplo n.º 4
0
Archivo: meca.py Proyecto: nnayo/egere
    def __init__(self, doc, name='cone'):
        self.data = {
            'len lo': 70., # mm
            'len up': 120., # mm
            'int diameter': 36., # mm
            'thick': 1., # mm
        }

        int_diam = self.data['int diameter']
        len_up = self.data['len up']
        len_lo = self.data['len lo']
        ext_diam = int_diam + 2 * self.data['thick']

        int_cone = Part.makeSphere(int_diam / 2)
        ext_cone = Part.makeSphere(ext_diam / 2)

        box = Part.makeBox(ext_diam, ext_diam, ext_diam)
        box.translate(Vector(-ext_diam / 2, -ext_diam / 2, 0))

        cone_up = ext_cone.cut(int_cone)
        cone_up = cone_up.common(box)

        matrix = Matrix()
        matrix.scale(1., 1., len_up / (ext_diam / 2))
        cone_up = cone_up.transformGeometry(matrix)
        cone_up.translate(Vector(0, 0, len_lo))
        cone_up = cone_up.fuse(cone_up)

        # blocking thread (pas de vis de blocage)
#        radius = self.data['int diameter'] / 2
#
#        helix = Part.makeHelix(4., 20., radius)
#
#        p0 = (radius, 0, 0)
#        p1 = (radius, 0, 3)
#        p2 = (radius - 1, 0, 2)
#        p3 = (radius - 1, 0, 1)
#
#        e0 = Part.makeLine(p0, p1)
#        e1 = Part.makeLine(p1, p2)
#        e2 = Part.makeLine(p2, p3)
#        e3 = Part.makeLine(p3, p0)
#        section = Part.Wire([e0, e1, e2, e3])
#        helix = Part.Wire(helix).makePipeShell([section], 1, 1)
#        helix.translate(Vector(0, 0, len_lo - 20))

        int_tube = Part.makeCylinder(int_diam / 2, len_lo)
        ext_tube = Part.makeCylinder(ext_diam / 2, len_lo)

        cone_lo = ext_tube.cut(int_tube)
#        cone_lo = cone_lo.fuse(helix)

        #comp = cone_up.fuse(cone_lo) # BUG: this fusion fails!!!
        comp = cone_lo

        MecaComponent.__init__(self, doc, comp, name, (1., 1., 0.))
Ejemplo n.º 5
0
 def getMatrix(self):
     m = self.m
     return Matrix(                              \
      m[0][0], m[0][1], m[0][2], m[0][3], \
      m[1][0], m[1][1], m[1][2], m[1][3], \
      m[2][0], m[2][1], m[2][2], m[2][3], \
      m[3][0], m[3][1], m[3][2], m[3][3]  \
      )
Ejemplo n.º 6
0
def __valueAtEllipse__(ra, rb, center, axis, u):
	x = VEC(cos(u) * ra, sin(u) * rb, 0)
	theta = axis.getAngle(DIR_Z)
	if (abs(theta) < 1e-06):
		n = DIR_X
	elif (abs(theta - pi) < 1e-06):
		n = -DIR_X
	else:
		n = DIR_Z.cross(axis)
	if (n.Length == 0):
		return x
	n = n.normalize()
	a = cos(theta/2)
	b = n.x*sin(theta/2)
	c = n.y*sin(theta/2)
	d = n.z*sin(theta/2)
	aa, bb, cc, dd = a*a, b*b, c*c, d*d
	bc, ad, ac, ab, bd, cd = b*c, a*d, a*c, a*b, b*d, c*d
	m = MAT(aa+bb-cc-dd, 2*(bc+ad), 2*(bd-ac), 0,
			2*(bc-ad), aa+cc-bb-dd, 2*(cd+ab), 0,
			2*(bd+ac), 2*(cd-ab), aa+dd-bb-cc, 0,
			0, 0, 0, 1)
	return center + m.multiply(x)
Ejemplo n.º 7
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)
Ejemplo n.º 8
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)
Ejemplo n.º 9
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)
Ejemplo n.º 10
0
def rotate(u, angle, axis=Vector(0, 0, 1)):
    """Rotate the vector by the specified angle, around the given axis.

    If the axis is omitted, the rotation is made around the Z axis
    (on the XY plane).

    It uses a 3x3 rotation matrix.
    ::
        u_rot = R u

                (c + x*x*t    xyt - zs     xzt + ys )
        u_rot = (xyt + zs     c + y*y*t    yzt - xs ) * u
                (xzt - ys     yzt + xs     c + z*z*t)

    Where `x`, `y`, `z` indicate unit components of the axis;
    `c` denotes a cosine of the angle; `t` indicates a complement
    of that cosine; `xs`, `ys`, `zs` indicate products of the unit
    components and the sine of the angle; and `xyt`, `xzt`, `yzt`
    indicate products of two unit components and the complement
    of the cosine.

    Parameters
    ----------
    u : Base::Vector3
        The vector.
    angle : float
        The angle of rotation given in radians.
    axis : Base::Vector3, optional
        The vector specifying the axis of rotation.
        It defaults to `(0, 0, 1)`, the +Z axis.

    Returns
    -------
    Base::Vector3
        The new rotated vector.
        If the `angle` is zero, return the original vector `u`.
    """
    typecheck([(u, Vector), (angle, (int, float)), (axis, Vector)], "rotate")

    if angle == 0:
        return u

    # Unit components, so that x**2 + y**2 + z**2 = 1
    L = axis.Length
    x = axis.x / L
    y = axis.y / L
    z = axis.z / L

    c = math.cos(angle)
    s = math.sin(angle)
    t = 1 - c

    # Various products
    xyt = x * y * t
    xzt = x * z * t
    yzt = y * z * t
    xs = x * s
    ys = y * s
    zs = z * s

    m = Matrix(c + x * x * t, xyt - zs, xzt + ys, 0, xyt + zs, c + y * y * t,
               yzt - xs, 0, xzt - ys, yzt + xs, c + z * z * t, 0)

    return m.multiply(u)
Ejemplo n.º 11
0
def cone_setup(doc, profil, data):
    """create all the shapes needed for the cone parts"""

    # if the final shapes already existed (true if one shape exists)
    # return them immediatly
    cone_top_obj = doc.getObject('_cone_top_base')
    cone_side_obj = doc.getObject('_cone_side_base')
    cone_struct_obj = doc.getObject('_cone_struct_base')
    cone_top_thread_obj = doc.getObject('_cone_top_thread')
    cone_struct_thread_obj = doc.getObject('_cone_struct_thread')

    if cone_top_obj:
        cone_top = cone_top_obj.Shape.copy()
        cone_side0 = cone_side_obj.Shape.copy()
        cone_side1 = cone_side_obj.Shape.copy()
        cone_side2 = cone_side_obj.Shape.copy()
        cone_struct = cone_struct_obj.Shape.copy()
        cone_top_thread = cone_top_thread_obj.Shape.copy()
        cone_struct_thread = cone_struct_thread_obj.Shape.copy()

        return cone_top, cone_side0, cone_side1, cone_side2, cone_struct, \
                cone_top_thread, cone_struct_thread

    side = profil['side']
    radius = profil['radius']
    diam_int = data['diameter']
    diam_ext = data['diameter'] + data['thick']
    length = data['len_lo'] + data['len_hi']
    struct_thick = data['struct_thick']

    # to modify the sphere to make it a ellipsoid
    matrix = Matrix()
    matrix.scale(1., 1., length / (diam_ext / 2))

    # to suppress the lower half of the sphere/ellipsoid
    lower = Part.makeBox(diam_ext, diam_ext, length)
    lower.translate(Vector(-diam_ext / 2, -diam_ext / 2, 0))

    gui_doc = FreeCADGui.ActiveDocument

    # make the external shape base of the cone
    sphere = Part.makeSphere(diam_ext / 2)
    sphere = sphere.transformGeometry(matrix)
    cone_base_ext = sphere.common(lower)
    cone_base_ext_obj = doc.addObject("Part::Feature", '_cone_base_ext')
    cone_base_ext_obj.Shape = cone_base_ext
    gui_doc.getObject('_cone_base_ext').Visibility = False

    # make the internal shape base of the cone
    sphere = Part.makeSphere(diam_int / 2)
    sphere = sphere.transformGeometry(matrix)
    cone_base_int = sphere.common(lower)
    cone_base_int_obj = doc.addObject("Part::Feature", '_cone_base_int')
    cone_base_int_obj.Shape = cone_base_int
    gui_doc.getObject('_cone_base_int').Visibility = False

    # make the skin
    skin = cone_base_ext.cut(cone_base_int)
    skin_obj = doc.addObject("Part::Feature", '_skin')
    skin_obj.Shape = skin
    gui_doc.getObject('_skin').Visibility = False

    # use profile shapes to make suppressed parts of the skin

    # full profil part
    shape = []
    shape.append(Vector(radius - 10, side / 2, 0))
    shape.append(Vector(radius + diam_ext, side / 2, 0))
    shape.append(Vector(radius + diam_ext, -side / 2, 0))
    shape.append(Vector(radius - 10, -side / 2, 0))
    shape.append(Vector(radius - 10, side / 2, 0))

    wire = Part.makePolygon(shape)
    face = Part.Face(wire)

    # make the volume
    long_cut_base = face.extrude(Vector(0, 0, length))
    long_cut_obj = doc.addObject("Part::Feature", '_long_cut_base')
    long_cut_obj.Shape = long_cut_base
    gui_doc.getObject('_long_cut_base').Visibility = False

    # full profil part
    shape = []
    shape.append(Vector(radius, side / 2, 0))
    shape.append(Vector(radius + diam_ext, side / 2, 0))
    shape.append(Vector(radius + diam_ext, -side / 2, 0))
    shape.append(Vector(radius, -side / 2, 0))
    shape.append(Vector(radius, side / 2, 0))

    wire = Part.makePolygon(shape)
    face = Part.Face(wire)

    # make the volume
    short_cut_base = face.extrude(Vector(0, 0, data['len_lo']))
    short_cut_obj = doc.addObject("Part::Feature", '_short_cut_base')
    short_cut_obj.Shape = short_cut_base
    gui_doc.getObject('_short_cut_base').Visibility = False

    # create 1/3 cylinder
    cylinder = Part.makeCylinder(diam_ext / 2, length, Vector(0, 0, 0), Vector(0, 0, 1), 120)
    cylinder_obj = doc.addObject("Part::Feature", '_cylinder_1_3')
    cylinder_obj.Shape = cylinder
    gui_doc.getObject('_cylinder_1_3').Visibility = False

    # thread bases
    radius_ext = diam_ext / 2 - struct_thick - 5
    thread_ext = Part.makeHelix(8, struct_thick - 8, radius_ext)
    radius_int = diam_ext / 2 - struct_thick - 9
    thread_int = Part.makeHelix(8, struct_thick, radius_int)

    # tube to make the space for threads
    tube_thread_ext = Part.makeCylinder(radius_ext, struct_thick)
    tube_thread_int = Part.makeCylinder(radius_int, struct_thick)
    tube_thread = tube_thread_ext.cut(tube_thread_int)
    tube_thread_obj = doc.addObject("Part::Feature", '_tube_thread')
    tube_thread_obj.Shape = tube_thread
    gui_doc.getObject('_tube_thread').Visibility = False

    # tube to cut the top of the structure
    tube_cut_ext = Part.makeCylinder(diam_ext / 2 - struct_thick / 2, struct_thick)
    tube_cut_int = tube_thread_int
    tube_cut = tube_cut_ext.cut(tube_cut_int)
    tube_cut_obj = doc.addObject("Part::Feature", '_tube_cut')
    tube_cut_obj.Shape = tube_cut
    gui_doc.getObject('_tube_cut').Visibility = False

    # tube to make the locking of the cone
    tube_lock_0 = Part.makeCylinder(diam_ext / 2 - struct_thick - 2, struct_thick / 2)
    tube_lock_1 = Part.makeCylinder(diam_ext / 2 - struct_thick + 2, struct_thick / 2)
    tube_lock_2 = Part.makeCylinder(diam_ext / 2, struct_thick / 4)

    tube_lock_int = tube_lock_1.cut(tube_lock_0)
    tube_lock_int.translate(Vector(0, 0, data['len_lo'] - 0.25 * data['struct_thick']))
    tube_lock_obj = doc.addObject("Part::Feature", '_tube_lock_int')
    tube_lock_obj.Shape = tube_lock_int
    gui_doc.getObject('_tube_lock_int').Visibility = False

    tube_lock_ext = tube_lock_2.cut(tube_lock_0)
    tube_lock_ext.translate(Vector(0, 0, data['len_lo'] - 0.25 * data['struct_thick']))
    tube_lock_obj = doc.addObject("Part::Feature", '_tube_lock_ext')
    tube_lock_obj.Shape = tube_lock_ext
    gui_doc.getObject('_tube_lock_ext').Visibility = False

    # make cone top part
    cone_top = cone_top_make(doc, gui_doc, data, skin, lower, cone_base_int, tube_cut, tube_thread, tube_lock_int)
    cone_top = cone_top.copy()

    cone_side = cone_side_make(doc, gui_doc, skin, lower, data, cone_base_int, long_cut_base, cylinder, tube_lock_int, tube_lock_ext)

    cone_side0 = cone_side.copy()
    cone_side0.rotate(Vector(0, 0, 0), Vector(0, 0, 1), 0)
    cone_side1 = cone_side.copy()
    cone_side1.rotate(Vector(0, 0, 0), Vector(0, 0, 1), 120)
    cone_side2 = cone_side.copy()
    cone_side2.rotate(Vector(0, 0, 0), Vector(0, 0, 1), 240)

    cone_struct = cone_struct_make(doc, gui_doc, cone_base_ext, short_cut_base, data, cone_top, cone_side, tube_thread)

    # internal thread profile
    p0 = (radius_int, 0, 0)
    p1 = (radius_int + 4, 0, 4)
    p2 = (radius_int, 0, 8)

    e0 = Part.makeLine(p0, p1)
    e1 = Part.makeLine(p1, p2)
    e2 = Part.makeLine(p2, p0)
 
    section = Part.Wire([e0, e1, e2])
    cone_struct_thread = Part.Wire(thread_int).makePipeShell([section], 1, 1)

    cone_struct_thread_obj = doc.addObject("Part::Feature", '_cone_struct_thread')
    cone_struct_thread_obj.Shape = cone_struct_thread.copy()
    gui_doc.getObject('_cone_struct_thread').Visibility = False

    # external thread profile
    p0 = (radius_ext, 0, 0)
    p1 = (radius_ext - 4, 0, 4)
    p2 = (radius_ext, 0, 8)

    e0 = Part.makeLine(p0, p1)
    e1 = Part.makeLine(p1, p2)
    e2 = Part.makeLine(p2, p0)
 
    section = Part.Wire([e0, e1, e2])
    cone_top_thread = Part.Wire(thread_ext).makePipeShell([section], 1, 1)

    cone_top_thread_obj = doc.addObject("Part::Feature", '_cone_top_thread')
    cone_top_thread_obj.Shape = cone_top_thread.copy()
    gui_doc.getObject('_cone_top_thread').Visibility = False

    return cone_top, cone_side0, cone_side1, cone_side2, cone_struct, \
            cone_top_thread, cone_struct_thread
Ejemplo 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 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)