Esempio n. 1
0
def ungroup(obj):
    """Remove the object from any group to which it belongs.

    A "group" is any object returned by `get_group_names`.

    Parameters
    ----------
    obj: App::DocumentObject or str
        Any type of object.
        If it is a string, it must be the `Label` of that object.
        Since a label is not guaranteed to be unique in a document,
        it will use the first object found with this label.
    """
    if isinstance(obj, str):
        obj_str = obj

    found, obj = utils.find_object(obj, doc=App.activeDocument())
    if not found:
        _msg("obj: {}".format(obj_str))
        _err(_tr("Wrong input: object not in document."))
        return None

    doc = obj.Document

    for name in get_group_names():
        group = doc.getObject(name)
        if obj in group.Group:
            # The list of objects cannot be modified directly,
            # so a new list is created, this new list is modified,
            # and then it is assigned over the older list.
            objects = group.Group
            objects.remove(obj)
            group.Group = objects
Esempio n. 2
0
def get_group_names(doc=None):
    """Return a list of names of existing groups in the document.

    Parameters
    ----------
    doc: App::Document, optional
        It defaults to `None`.
        A document on which to search group names.
        It if is `None` it will search the current document.

    Returns
    -------
    list of str
        A list of names of objects that are "groups".
        These are objects derived from `App::DocumentObjectGroup`
        or which are of types `'Floor'`, `'Building'`, or `'Site'`
        from the Arch Workbench.

        Otherwise, return an empty list.
    """
    if not doc:
        found, doc = utils.find_doc(App.activeDocument())

    if not found:
        _err(_tr("No active document. Aborting."))
        return []

    glist = []

    for obj in doc.Objects:
        if (obj.isDerivedFrom("App::DocumentObjectGroup")
                or utils.get_type(obj) in ("Floor", "Building", "Site")):
            glist.append(obj.Name)

    return glist
Esempio n. 3
0
def _are_integers(n_x, n_y, n_z=None, name="Unknown"):
    """Check that the numbers are integers, with minimum value of 1."""
    _msg("n_x: {}".format(n_x))
    _msg("n_y: {}".format(n_y))
    if n_z:
        _msg("n_z: {}".format(n_z))

    try:
        if n_z:
            utils.type_check([(n_x, int), (n_y, int), (n_z, int)], name=name)
        else:
            utils.type_check([(n_x, int), (n_y, int)], name=name)
    except TypeError:
        _err(_tr("Wrong input: must be an integer number."))
        return False, n_x, n_y, n_z

    _text = ("Input: number of elements must be at least 1. "
             "It is set to 1.")
    if n_x < 1:
        _wrn(_tr(_text))
        n_x = 1
    if n_y < 1:
        _wrn(_tr(_text))
        n_y = 1
    if n_z and n_z < 1:
        _wrn(_tr(_text))
        n_z = 1

    return True, n_x, n_y, n_z
Esempio n. 4
0
def _are_vectors(v_x, v_y, v_z=None, name="Unknown"):
    """Check that the vectors are numbers."""
    _msg("v_x: {}".format(v_x))
    _msg("v_y: {}".format(v_y))
    if v_z:
        _msg("v_z: {}".format(v_z))

    try:
        if v_z:
            utils.type_check([(v_x, (int, float, App.Vector)),
                              (v_y, (int, float, App.Vector)),
                              (v_z, (int, float, App.Vector))],
                             name=name)
        else:
            utils.type_check([(v_x, (int, float, App.Vector)),
                              (v_y, (int, float, App.Vector))],
                             name=name)
    except TypeError:
        _err(_tr("Wrong input: must be a number or vector."))
        return False, v_x, v_y, v_z

    _text = "Input: single value expanded to vector."
    if not isinstance(v_x, App.Vector):
        v_x = App.Vector(v_x, 0, 0)
        _wrn(_tr(_text))
    if not isinstance(v_y, App.Vector):
        v_y = App.Vector(0, v_y, 0)
        _wrn(_tr(_text))
    if v_z and not isinstance(v_z, App.Vector):
        v_z = App.Vector(0, 0, v_z)
        _wrn(_tr(_text))

    return True, v_x, v_y, v_z
Esempio n. 5
0
def cut(object1, object2):
    """Return a cut object made from the difference of the 2 given objects.

    Parameters
    ----------
    object1: Part::Feature
        Any object with a `Part::TopoShape`.

    object2: Part::Feature
        Any object with a `Part::TopoShape`.

    Returns
    -------
    Part::Cut
        The resulting cut object.

    None
        If there is a problem and the new object can't be created.
    """
    if not App.activeDocument():
        _err(_tr("No active document. Aborting."))
        return

    obj = App.activeDocument().addObject("Part::Cut", "Cut")
    obj.Base = object1
    obj.Tool = object2

    if App.GuiUp:
        gui_utils.format_object(obj, object1)
        gui_utils.select(obj)
        object1.ViewObject.Visibility = False
        object2.ViewObject.Visibility = False

    return obj
Esempio n. 6
0
def get_group_names(doc=None):
    """Return a list of names of existing groups in the document.

    Parameters
    ----------
    doc: App::Document, optional
        It defaults to `None`.
        A document on which to search group names.
        It if is `None` it will search the current document.

    Returns
    -------
    list of str
        A list of names of objects that are considered groups.
        See the is_group function.

        Otherwise returns an empty list.
    """
    if not doc:
        found, doc = utils.find_doc(App.activeDocument())

    if not found:
        _err(_tr("No active document. Aborting."))
        return []

    glist = []

    for obj in doc.Objects:
        if is_group(obj):
            glist.append(obj.Name)

    return glist
Esempio n. 7
0
    def proceed(self):
        """Proceed with the command if one object was selected."""
        sel = Gui.Selection.getSelectionEx()
        if len(sel) != 2:
            _err(
                _tr("Please select exactly two objects, "
                    "the base object and the path object, "
                    "before calling this command."))
        else:
            base_object = sel[0].Object
            path_object = sel[1].Object

            count = 15
            rot_factor = 0.25
            use_link = self.use_link

            Gui.addModule("Draft")
            _cmd = "Draft.make_path_twisted_array"
            _cmd += "("
            _cmd += "App.ActiveDocument." + base_object.Name + ", "
            _cmd += "App.ActiveDocument." + path_object.Name + ", "
            _cmd += "count=" + str(count) + ", "
            _cmd += "rot_factor=" + str(rot_factor) + ", "
            _cmd += "use_link=" + str(use_link)
            _cmd += ")"

            _cmd_list = [
                "_obj_ = " + _cmd, "Draft.autogroup(_obj_)",
                "App.ActiveDocument.recompute()"
            ]
            self.commit(_tr(self.name), _cmd_list)

        # Commit the transaction and execute the commands
        # through the parent class
        self.finish()
Esempio n. 8
0
    def createObject(self):
        """Create the actual object in the current document."""
        # print("debug: D_T ShapeString.createObject type(self.SString):"
        #       + str(type(self.SString)))

        dquote = '"'
        String = dquote + self.SString + dquote

        # Size and tracking are numbers;
        # they are ASCII so this conversion should always work
        Size = str(self.SSSize)
        Tracking = str(self.SSTrack)
        FFile = dquote + self.FFile + dquote

        try:
            qr, sup, points, fil = self.getStrings()
            Gui.addModule("Draft")
            _cmd = 'Draft.make_shapestring'
            _cmd += '('
            _cmd += 'String=' + String + ', '
            _cmd += 'FontFile=' + FFile + ', '
            _cmd += 'Size=' + Size + ', '
            _cmd += 'Tracking=' + Tracking
            _cmd += ')'
            _cmd_list = [
                'ss = ' + _cmd, 'plm = FreeCAD.Placement()',
                'plm.Base = ' + DraftVecUtils.toString(self.ssBase),
                'plm.Rotation.Q = ' + qr, 'ss.Placement = plm',
                'ss.Support = ' + sup, 'Draft.autogroup(ss)',
                'FreeCAD.ActiveDocument.recompute()'
            ]
            self.commit(translate("draft", "Create ShapeString"), _cmd_list)
        except Exception:
            _err("Draft_ShapeString: error delaying commit")
        self.finish()
Esempio n. 9
0
def get_layer_container():
    """Return a group object to put layers in.

    Returns
    -------
    App::DocumentObjectGroupPython
        The existing group object named `'LayerContainer'`
        of type `LayerContainer`.
        If it doesn't exist it will create it with this default Name.
    """
    found, doc = utils.find_doc(App.activeDocument())
    if not found:
        _err(translate("draft", "No active document. Aborting."))
        return None

    for obj in doc.Objects:
        if obj.Name == "LayerContainer":
            return obj

    new_obj = doc.addObject("App::DocumentObjectGroupPython", "LayerContainer")
    new_obj.Label = translate("draft", "Layers")

    LayerContainer(new_obj)

    if App.GuiUp:
        ViewProviderLayerContainer(new_obj.ViewObject)

    return new_obj
Esempio n. 10
0
    def createObject(self):
        """Create object in the current document."""
        dquote = '"'
        if sys.version_info.major < 3:  # Python3: no more unicode
            String = 'u' + dquote + str(
                self.task.leString.text().encode('unicode_escape')) + dquote
        else:
            String = dquote + self.task.leString.text() + dquote
        FFile = dquote + str(self.fileSpec) + dquote

        Size = str(_Quantity(self.task.sbHeight.text()).Value)
        Tracking = str(0.0)
        x = _Quantity(self.task.sbX.text()).Value
        y = _Quantity(self.task.sbY.text()).Value
        z = _Quantity(self.task.sbZ.text()).Value
        ssBase = App.Vector(x, y, z)
        # this try block is almost identical to the one in DraftTools
        try:
            qr, sup, points, fil = self.sourceCmd.getStrings()
            Gui.addModule("Draft")
            self.sourceCmd.commit(translate("draft", "Create ShapeString"), [
                'ss=Draft.makeShapeString(String=' + String + ',FontFile=' +
                FFile + ',Size=' + Size + ',Tracking=' + Tracking + ')',
                'plm=FreeCAD.Placement()', 'plm.Base=' +
                DraftVecUtils.toString(ssBase), 'plm.Rotation.Q=' + qr,
                'ss.Placement=plm', 'ss.Support=' + sup, 'Draft.autogroup(ss)'
            ])
        except Exception:
            _err("Draft_ShapeString: error delaying commit\n")
Esempio n. 11
0
def build_copies(base_object, pt_list=None, placement=App.Placement()):
    """Build a compound of copies from the base object and list of points.

    Returns
    -------
    Part::TopoShape
        The compound shape created by `Part.makeCompound`.
    """

    if not pt_list:
        _err(
            translate(
                "Draft", "Point object doesn't have a discrete point, "
                "it cannot be used for an array."))
        shape = base_object.Shape.copy()
        return shape

    copies = list()

    for pla in build_copies(base_object, pt_list, placement):
        new_shape = base_object.Shape.copy()
        new_shape.Placement = pla

        copies.append(new_shape)

    shape = Part.makeCompound(copies)
    return shape
Esempio n. 12
0
    def execute(self, obj):
        """Execute when the object is created or recomputed."""
        if not obj.Base or not obj.PathObject:
            return

        # placement of entire PathArray object
        array_placement = obj.Placement

        w = self.get_wires(obj.PathObject, obj.PathSubelements)
        if not w:
            _err(obj.PathObject.Label +
                 translate("draft", ", path object doesn't have 'Edges'."))
            return

        base_rotation = obj.Base.Shape.Placement.Rotation
        final_rotation = base_rotation

        if (obj.Align and obj.AlignMode == "Tangent"
                and hasattr(obj, "TangentVector")):
            Xaxis = App.Vector(1.0, 0.0, 0.0)  # default TangentVector

            if not DraftVecUtils.equals(Xaxis, obj.TangentVector):
                # make rotation from TangentVector to X
                pre_rotation = App.Rotation(obj.TangentVector, Xaxis)
                final_rotation = base_rotation.multiply(pre_rotation)

        copy_placements = placements_on_path(final_rotation, w, obj.Count,
                                             obj.ExtraTranslation, obj.Align,
                                             obj.AlignMode, obj.ForceVertical,
                                             obj.VerticalVector)

        return super(PathArray, self).buildShape(obj, array_placement,
                                                 copy_placements)
Esempio n. 13
0
    def createObject(self):
        """Create object in the current document."""
        dquote = '"'
        String = dquote + self.form.leString.text() + dquote
        FFile = dquote + str(self.fileSpec) + dquote

        Size = str(App.Units.Quantity(self.form.sbHeight.text()).Value)
        Tracking = str(0.0)
        x = App.Units.Quantity(self.form.sbX.text()).Value
        y = App.Units.Quantity(self.form.sbY.text()).Value
        z = App.Units.Quantity(self.form.sbZ.text()).Value
        ssBase = App.Vector(x, y, z)
        # this try block is almost identical to the one in DraftTools
        try:
            qr, sup, points, fil = self.sourceCmd.getStrings()
            Gui.addModule("Draft")
            self.sourceCmd.commit(translate("draft", "Create ShapeString"), [
                'ss=Draft.make_shapestring(String=' + String + ', FontFile=' +
                FFile + ', Size=' + Size + ', Tracking=' + Tracking + ')',
                'plm=FreeCAD.Placement()', 'plm.Base=' + toString(ssBase),
                'plm.Rotation.Q=' + qr, 'ss.Placement=plm',
                'ss.Support=' + sup, 'Draft.autogroup(ss)'
            ])
        except Exception:
            _err("Draft_ShapeString: error delaying commit\n")
Esempio n. 14
0
    def proceed(self):
        """Proceed with the command if one object was selected."""
        if self.call:
            self.view.removeEventCallback("SoEvent", self.call)

        sel = Gui.Selection.getSelectionEx()
        if len(sel) != 2:
            _err(
                _tr("Please select exactly two objects, "
                    "the base object and the point object, "
                    "before calling this command."))
        else:
            base_object = sel[0].Object
            point_object = sel[1].Object
            extra = None

            Gui.addModule('Draft')
            _cmd = "Draft.make_point_array"
            _cmd += "("
            _cmd += "App.ActiveDocument." + base_object.Name + ", "
            _cmd += "App.ActiveDocument." + point_object.Name + ", "
            _cmd += "extra=" + str(extra) + ", "
            _cmd += 'use_link=' + str(self.use_link)
            _cmd += ")"

            _cmd_list = [
                "_obj_ = " + _cmd, "Draft.autogroup(_obj_)",
                "App.ActiveDocument.recompute()"
            ]
            self.commit(_tr(self.name), _cmd_list)

        # Commit the transaction and execute the commands
        # through the parent class
        self.finish()
Esempio n. 15
0
def build_placements(base_object, pt_list=None, placement=App.Placement()):
    """Build a placements from the base object and list of points.

    Returns
    -------
    list(App.Placement)
    """
    if not pt_list:
        _err(
            translate(
                "Draft", "Point object doesn't have a discrete point, "
                "it cannot be used for an array."))
        return []

    pls = list()

    for point in pt_list:
        new_pla = base_object.Placement.copy()
        original_rotation = new_pla.Rotation

        # Reset the position of the copy, and combine the original rotation
        # with the provided rotation. Two rotations (quaternions)
        # are combined by multiplying them.
        new_pla.Base = placement.Base
        new_pla.Rotation = original_rotation * placement.Rotation

        if point.TypeId == "Part::Vertex":
            # For this object the final position is the value of the Placement
            # plus the value of the X, Y, Z properties
            place = App.Vector(point.X, point.Y,
                               point.Z) + point.Placement.Base

        elif hasattr(point, 'Placement'):
            # If the point object has a placement (Draft Point), use it
            # to displace the copy of the shape
            place = point.Placement.Base

            # The following old code doesn't make much sense because it uses
            # the rotation value of the auxiliary point.
            # Even if the point does have a rotation property as part of its
            # placement, rotating a point by itself is a strange workflow.
            # We want to use the position of the point but not its rotation,
            # which will probably be zero anyway.

            # Old code:
            # place = point.Placement
            # new_shape.rotate(place.Base,
            #                  place.Rotation.Axis,
            #                  math.degrees(place.Rotation.Angle))
        else:
            # In other cases (Sketch with points)
            # translate by the X, Y, Z coordinates
            place = App.Vector(point.X, point.Y, point.Z)

        new_pla.translate(place)

        pls.append(new_pla)

    return pls
Esempio n. 16
0
 def createObject(self):
     """Create the actual object in the current document."""
     plane = App.DraftWorkingPlane
     p1 = self.node[0]
     p3 = self.node[-1]
     diagonal = p3.sub(p1)
     halfdiag = App.Vector(diagonal).multiply(0.5)
     center = p1.add(halfdiag)
     p2 = p1.add(DraftVecUtils.project(diagonal, plane.v))
     p4 = p1.add(DraftVecUtils.project(diagonal, plane.u))
     r1 = (p4.sub(p1).Length) / 2
     r2 = (p2.sub(p1).Length) / 2
     try:
         # The command to run is built as a series of text strings
         # to be committed through the `draftutils.todo.ToDo` class.
         rot, sup, pts, fil = self.getStrings()
         if r2 > r1:
             r1, r2 = r2, r1
             m = App.Matrix()
             m.rotateZ(math.pi / 2)
             rot1 = App.Rotation()
             rot1.Q = eval(rot)
             rot2 = App.Placement(m)
             rot2 = rot2.Rotation
             rot = str((rot1.multiply(rot2)).Q)
         if utils.getParam("UsePartPrimitives", False):
             # Insert a Part::Primitive object
             Gui.addModule("Part")
             _cmd = 'FreeCAD.ActiveDocument.'
             _cmd += 'addObject("Part::Ellipse", "Ellipse")'
             _cmd_list = [
                 'ellipse = ' + _cmd, 'ellipse.MajorRadius = ' + str(r1),
                 'ellipse.MinorRadius = ' + str(r2),
                 'pl = FreeCAD.Placement()', 'pl.Rotation.Q= ' + rot,
                 'pl.Base = ' + DraftVecUtils.toString(center),
                 'ellipse.Placement = pl', 'Draft.autogroup(ellipse)',
                 'FreeCAD.ActiveDocument.recompute()'
             ]
             self.commit(translate("draft", "Create Ellipse"), _cmd_list)
         else:
             # Insert a Draft ellipse
             Gui.addModule("Draft")
             _cmd = 'Draft.makeEllipse'
             _cmd += '('
             _cmd += str(r1) + ', ' + str(r2) + ', '
             _cmd += 'placement=pl, '
             _cmd += 'face=' + fil + ', '
             _cmd += 'support=' + sup
             _cmd += ')'
             _cmd_list = [
                 'pl = FreeCAD.Placement()', 'pl.Rotation.Q = ' + rot,
                 'pl.Base = ' + DraftVecUtils.toString(center),
                 'ellipse = ' + _cmd, 'Draft.autogroup(ellipse)',
                 'FreeCAD.ActiveDocument.recompute()'
             ]
             self.commit(translate("draft", "Create Ellipse"), _cmd_list)
     except Exception:
         _err("Draft: Error: Unable to create object.")
     self.finish(cont=True)
Esempio n. 17
0
 def createObject(self):
     """Create the final object in the current document."""
     plane = App.DraftWorkingPlane
     p1 = self.node[0]
     p3 = self.node[-1]
     diagonal = p3.sub(p1)
     p2 = p1.add(DraftVecUtils.project(diagonal, plane.v))
     p4 = p1.add(DraftVecUtils.project(diagonal, plane.u))
     length = p4.sub(p1).Length
     if abs(DraftVecUtils.angle(p4.sub(p1), plane.u, plane.axis)) > 1:
         length = -length
     height = p2.sub(p1).Length
     if abs(DraftVecUtils.angle(p2.sub(p1), plane.v, plane.axis)) > 1:
         height = -height
     try:
         # The command to run is built as a series of text strings
         # to be committed through the `draftutils.todo.ToDo` class.
         rot, sup, pts, fil = self.getStrings()
         base = p1
         if length < 0:
             length = -length
             base = base.add((p1.sub(p4)).negative())
         if height < 0:
             height = -height
             base = base.add((p1.sub(p2)).negative())
         Gui.addModule("Draft")
         if utils.getParam("UsePartPrimitives", False):
             # Insert a Part::Primitive object
             _cmd = 'FreeCAD.ActiveDocument.'
             _cmd += 'addObject("Part::Plane", "Plane")'
             _cmd_list = [
                 'plane = ' + _cmd, 'plane.Length = ' + str(length),
                 'plane.Width = ' + str(height), 'pl = FreeCAD.Placement()',
                 'pl.Rotation.Q=' + rot,
                 'pl.Base = ' + DraftVecUtils.toString(base),
                 'plane.Placement = pl', 'Draft.autogroup(plane)',
                 'FreeCAD.ActiveDocument.recompute()'
             ]
             self.commit(translate("draft", "Create Plane"), _cmd_list)
         else:
             _cmd = 'Draft.makeRectangle'
             _cmd += '('
             _cmd += 'length=' + str(length) + ', '
             _cmd += 'height=' + str(height) + ', '
             _cmd += 'placement=pl, '
             _cmd += 'face=' + fil + ', '
             _cmd += 'support=' + sup
             _cmd += ')'
             _cmd_list = [
                 'pl = FreeCAD.Placement()', 'pl.Rotation.Q = ' + rot,
                 'pl.Base = ' + DraftVecUtils.toString(base),
                 'rec = ' + _cmd, 'Draft.autogroup(rec)',
                 'FreeCAD.ActiveDocument.recompute()'
             ]
             self.commit(translate("draft", "Create Rectangle"), _cmd_list)
     except Exception:
         _err("Draft: error delaying commit")
     self.finish(cont=True)
Esempio n. 18
0
    def validate_input(self, selection, r_distance, tan_distance, number,
                       symmetry, axis, center):
        """Check that the input is valid.

        Some values may not need to be checked because
        the interface may not allow to input wrong data.
        """
        if not selection:
            _err(translate("draft", "At least one element must be selected."))
            return False

        if number < 2:
            _err(translate("draft", "Number of layers must be at least 2."))
            return False

        # TODO: this should handle multiple objects.
        # Each of the elements of the selection should be tested.
        obj = selection[0]
        if obj.isDerivedFrom("App::FeaturePython"):
            _err(translate("draft", "Selection is not suitable for array."))
            _err(
                translate("draft", "Object:") +
                " {}".format(selection[0].Label))
            return False

        if r_distance == 0:
            _wrn(
                translate(
                    "draft",
                    "Radial distance is zero. Resulting array may not look correct."
                ))
        elif r_distance < 0:
            _wrn(
                translate(
                    "draft",
                    "Radial distance is negative. It is made positive to proceed."
                ))
            self.r_distance = abs(r_distance)

        if tan_distance == 0:
            _err(translate("draft", "Tangential distance cannot be zero."))
            return False
        elif tan_distance < 0:
            _wrn(
                translate(
                    "draft",
                    "Tangential distance is negative. It is made positive to proceed."
                ))
            self.tan_distance = abs(tan_distance)

        # The other arguments are not tested but they should be present.
        if symmetry and axis and center:
            pass

        self.fuse = self.form.checkbox_fuse.isChecked()
        self.use_link = self.form.checkbox_link.isChecked()
        return True
Esempio n. 19
0
    def proceed(self):
        """Proceed with the command if one object was selected."""
        if self.call:
            self.view.removeEventCallback("SoEvent", self.call)

        sel = Gui.Selection.getSelectionEx()
        if len(sel) != 2:
            _err(
                _tr("Please select exactly two objects, "
                    "the base object and the path object, "
                    "before calling this command."))
        else:
            base_object = sel[0].Object
            path_object = sel[1].Object

            count = 4
            extra = App.Vector(0, 0, 0)
            subelements = list(sel[1].SubElementNames)
            align = False
            align_mode = "Original"
            tan_vector = App.Vector(1, 0, 0)
            force_vertical = False
            vertical_vector = App.Vector(0, 0, 1)
            use_link = self.use_link

            _edge_list_str = list()
            _edge_list_str = ["'" + edge + "'" for edge in subelements]
            _sub_str = ", ".join(_edge_list_str)
            subelements_list_str = "[" + _sub_str + "]"

            vertical_vector_str = DraftVecUtils.toString(vertical_vector)

            Gui.addModule("Draft")
            _cmd = "Draft.make_path_array"
            _cmd += "("
            _cmd += "App.ActiveDocument." + base_object.Name + ", "
            _cmd += "App.ActiveDocument." + path_object.Name + ", "
            _cmd += "count=" + str(count) + ", "
            _cmd += "extra=" + DraftVecUtils.toString(extra) + ", "
            _cmd += "subelements=" + subelements_list_str + ", "
            _cmd += "align=" + str(align) + ", "
            _cmd += "align_mode=" + "'" + align_mode + "', "
            _cmd += "tan_vector=" + DraftVecUtils.toString(tan_vector) + ", "
            _cmd += "force_vertical=" + str(force_vertical) + ", "
            _cmd += "vertical_vector=" + vertical_vector_str + ", "
            _cmd += "use_link=" + str(use_link)
            _cmd += ")"

            _cmd_list = [
                "_obj_ = " + _cmd, "Draft.autogroup(_obj_)",
                "App.ActiveDocument.recompute()"
            ]
            self.commit(_tr(self.name), _cmd_list)

        # Commit the transaction and execute the commands
        # through the parent class
        self.finish()
Esempio n. 20
0
    def numericRadius(self, rad):
        """Validate the radius entry field in the user interface.

        This function is called by the toolbar or taskpanel interface
        when a valid radius has been entered in the input field.
        """
        # print("dvec:", self.dvec)
        # print("rad:", rad)
        if self.dvec:
            if isinstance(self.dvec, float):
                if self.mode == "Circle":
                    r1 = self.shape.Edges[0].Curve.Radius
                    r2 = self.ghost.getRadius()
                    if r2 >= r1:
                        rad = r1 + rad
                    else:
                        rad = r1 - rad
                    delta = str(rad)
                else:
                    _err("Draft.Offset error: Unhandled case")
            # to offset bspline
            elif self.mode == "BSpline":
                new_points = []
                for old_point, new_point in zip(self.sel.Points, self.npts):
                    diff_direction = new_point.sub(old_point).normalize()
                    new_points.append(old_point.add(diff_direction * rad))
                delta = DraftVecUtils.toString(new_points)
            else:
                self.dvec.normalize()
                self.dvec.multiply(rad)
                delta = DraftVecUtils.toString(self.dvec)
            copymode = False
            occmode = self.ui.occOffset.isChecked()
            utils.param.SetBool("Offset_OCC", occmode)

            if self.ui.isCopy.isChecked():
                copymode = True
            Gui.addModule("Draft")
            _cmd = 'Draft.offset'
            _cmd += '('
            _cmd += 'FreeCAD.ActiveDocument.'
            _cmd += self.sel.Name + ', '
            _cmd += delta + ', '
            _cmd += 'copy=' + str(copymode) + ', '
            _cmd += 'occ=' + str(occmode)
            _cmd += ')'
            _cmd_list = [
                'offst = ' + _cmd, 'FreeCAD.ActiveDocument.recompute()'
            ]
            self.commit(translate("draft", "Offset"), _cmd_list)
            self.finish()
        else:
            _err(
                translate(
                    "Draft", "Offset direction is not defined. "
                    "Please move the mouse on either side "
                    "of the object first to indicate a direction"))
Esempio n. 21
0
def make_rect_array2d(obj, d_x=10, d_y=10, n_x=2, n_y=2, use_link=True):
    """Create a 2D rectangular array from the given object.

    This function wraps around `make_ortho_array2d`
    to produce strictly rectangular arrays, in which
    the displacement vectors `v_x` and `v_y`
    only have their respective components in X and Y.

    Parameters
    ----------
    obj: Part::Feature
        Any type of object that has a `Part::TopoShape`
        that can be duplicated.
        This means most 2D and 3D objects produced
        with any workbench.

    d_x, d_y: Base::Vector3, optional
        Displacement of elements in the corresponding X and Y directions.

    n_x, n_y: int, optional
        Number of elements in the corresponding X and Y directions.

    use_link: bool, optional
        If it is `True`, create `App::Link` array.
        See `make_ortho_array`.

    Returns
    -------
    Part::FeaturePython
        A scripted object with `Proxy.Type='Array'`.
        Its `Shape` is a compound of the copies of the original object.

    See Also
    --------
    make_ortho_array, make_ortho_array2d, make_rect_array
    """
    _name = "make_rect_array2d"
    utils.print_header(_name, _tr("Rectangular array 2D"))

    _msg("d_x: {}".format(d_x))
    _msg("d_y: {}".format(d_y))

    try:
        utils.type_check([(d_x, (int, float)), (d_y, (int, float))],
                         name=_name)
    except TypeError:
        _err(_tr("Wrong input: must be a number."))
        return None

    new_obj = make_ortho_array2d(obj,
                                 v_x=App.Vector(d_x, 0, 0),
                                 v_y=App.Vector(0, d_y, 0),
                                 n_x=n_x,
                                 n_y=n_y,
                                 use_link=use_link)
    return new_obj
Esempio n. 22
0
def convert_draft_texts(textslist=None):
    """Convert the given Annotation to a Draft text.

    In the past, the `Draft Text` object didn't exist; text objects
    were of type `App::Annotation`. This function was introduced
    to convert those older objects to a `Draft Text` scripted object.

    This function was already present at splitting time during v0.19.

    Parameters
    ----------
    textslist: list of objects, optional
        It defaults to `None`.
        A list containing `App::Annotation` objects or a single of these
        objects.
        If it is `None` it will convert all objects in the current document.
    """
    _name = "convert_draft_texts"
    utils.print_header(_name, "Convert Draft texts")

    found, doc = utils.find_doc(App.activeDocument())
    if not found:
        _err(_tr("No active document. Aborting."))
        return None

    if not textslist:
        textslist = list()
        for obj in doc.Objects:
            if obj.TypeId == "App::Annotation":
                textslist.append(obj)

    if not isinstance(textslist, list):
        textslist = [textslist]

    to_delete = []

    for obj in textslist:
        label = obj.Label
        obj.Label = label + ".old"

        # Create a new Draft Text object
        new_obj = make_text(obj.LabelText, placement=obj.Position)
        new_obj.Label = label
        to_delete.append(obj)

        # Move the new object to the group which contained the old object
        for in_obj in obj.InList:
            if in_obj.isDerivedFrom("App::DocumentObjectGroup"):
                if obj in in_obj.Group:
                    group = in_obj.Group
                    group.append(new_obj)
                    in_obj.Group = group

    for obj in to_delete:
        doc.removeObject(obj.Name)
Esempio n. 23
0
 def rotate_subelements(self, is_copy):
     """Rotate the subelements."""
     try:
         if is_copy:
             self.commit(translate("draft", "Copy"),
                         self.build_copy_subelements_command())
         else:
             self.commit(translate("draft", "Rotate"),
                         self.build_rotate_subelements_command())
     except Exception:
         _err(translate("draft", "Some subelements could not be moved."))
Esempio n. 24
0
    def finish(self, closed=False, cont=False):
        """Terminate the operation and close the curve if asked.

        Parameters
        ----------
        closed: bool, optional
            Close the line if `True`.
        """
        if self.ui:
            if hasattr(self, "bezcurvetrack"):
                self.bezcurvetrack.finalize()
        if not utils.getParam("UiMode", 1):
            Gui.Control.closeDialog()
        if self.obj:
            # remove temporary object, if any
            old = self.obj.Name
            todo.ToDo.delay(self.doc.removeObject, old)
        if closed is False:
            cleannd = (len(self.node) - 1) % self.degree
            if cleannd == 0:
                self.node = self.node[0:-3]
            if cleannd > 0:
                self.node = self.node[0:-cleannd]
        if len(self.node) > 1:
            try:
                # The command to run is built as a series of text strings
                # to be committed through the `draftutils.todo.ToDo` class.
                rot, sup, pts, fil = self.getStrings()
                Gui.addModule("Draft")
                _cmd = 'Draft.makeBezCurve'
                _cmd += '('
                _cmd += 'points, '
                _cmd += 'closed=' + str(closed) + ', '
                _cmd += 'support=' + sup + ', '
                _cmd += 'degree=' + str(self.degree)
                _cmd += ')'
                _cmd_list = ['points = ' + pts,
                             'bez = ' + _cmd,
                             'Draft.autogroup(bez)',
                             'FreeCAD.ActiveDocument.recompute()']
                self.commit(translate("draft", "Create BezCurve"),
                            _cmd_list)
            except Exception:
                _err("Draft: error delaying commit")

        # `Creator` is the grandfather class, the parent of `Line`;
        # we need to call it to perform final cleanup tasks.
        #
        # Calling it directly like this is a bit messy; maybe we need
        # another method that performs cleanup (superfinish)
        # that is not re-implemented by any of the child classes.
        gui_base_original.Creator.finish(self)
        if self.ui and self.ui.continueMode:
            self.Activated()
Esempio n. 25
0
 def move_subelements(self):
     """Move the subelements."""
     try:
         if self.ui.isCopy.isChecked():
             self.commit(translate("draft", "Copy"),
                         self.build_copy_subelements_command())
         else:
             self.commit(translate("draft", "Move"),
                         self.build_move_subelements_command())
     except Exception:
         _err(translate("draft", "Some subelements could not be moved."))
Esempio n. 26
0
def build_copies(base_object, pt_list=None, placement=App.Placement()):
    """Build a compound of copies from the base object and list of points.

    Returns
    -------
    Part::TopoShape
        The compound shape created by `Part.makeCompound`.
    """
    if not pt_list:
        _err(
            translate(
                "Draft", "Point object doesn't have a discrete point, "
                "it cannot be used for an array."))
        shape = base_object.Shape.copy()
        return shape

    copies = list()

    for point in pt_list:
        new_shape = base_object.Shape.copy()
        original_rotation = new_shape.Placement.Rotation

        # Reset placement of the copy, and combine the original rotation
        # with the provided placement. Two rotations (quaternions)
        # are combined by multiplying them.
        new_shape.Placement.Base = placement.Base
        new_shape.Placement.Rotation = original_rotation * placement.Rotation

        # If the point object has a placement, use it
        # to displace the copy of the shape. Otherwise
        # translate by the X, Y, Z coordinates.
        if hasattr(point, 'Placement'):
            place = point.Placement
            new_shape.translate(place.Base)

            # The following old code doesn't make much sense because it uses
            # the rotation value of the auxiliary point.
            # Even if the point does have a rotation property as part of its
            # placement, rotating a point by itself is a strange workflow.
            # We want to use the position of the point but not its rotation,
            # which will probably be zero anyway.

            # Old code:
            # new_shape.rotate(place.Base,
            #                  place.Rotation.Axis,
            #                  math.degrees(place.Rotation.Angle))
        else:
            new_shape.translate(App.Vector(point.X, point.Y, point.Z))

        copies.append(new_shape)

    shape = Part.makeCompound(copies)
    return shape
Esempio n. 27
0
 def move_subelements(self, is_copy):
     """Move the subelements."""
     Gui.addModule("Draft")
     try:
         if is_copy:
             self.commit(translate("draft", "Copy"),
                         self.build_copy_subelements_command())
         else:
             self.commit(translate("draft", "Move"),
                         self.build_move_subelements_command())
     except Exception:
         _err(translate("draft", "Some subelements could not be moved."))
Esempio n. 28
0
    def finish(self, closed=False, cont=False):
        """Terminate the operation and close the spline if asked.

        Parameters
        ----------
        closed: bool, optional
            Close the line if `True`.
        """
        # if self.ui:
        # self.linetrack.finalize()
        if not utils.getParam("UiMode", 1):
            Gui.Control.closeDialog()
        if self.obj:
            # Remove temporary object, if any
            old = self.obj.Name
            todo.ToDo.delay(self.doc.removeObject, old)
        if len(self.node) > 1:
            # The command to run is built as a series of text strings
            # to be committed through the `draftutils.todo.ToDo` class.
            try:
                # rot, sup, pts, fil = self.getStrings()

                cmd_list = [
                    'from FreeCAD import Vector',
                    'from safe.punch.beam import make_beam',
                    'from safe.punch.base_foundation import make_base_foundation',
                    'beams = []',
                ]

                for p1, p2 in zip(self.node[:-1], self.node[1:]):
                    cmd_list.append(f'beam = make_beam({p1}, {p2})')
                    cmd_list.append(f'beams.append(beam)')
                hide_beams = self.hide_beams_checkbox.isChecked()
                cmd_list.append(
                    f'make_base_foundation(beams, "{self.layer}", {self.bf_width}, {self.bf_height}, {self.bf_soil_modulus}, "{self.bf_align}", {self.bf_left_width}, {self.bf_right_width}, {hide_beams} )'
                )
                self.commit(translate("civil", "Create Base Foundation"),
                            cmd_list)
                FreeCAD.ParamGet(
                    "User parameter:BaseApp/Preferences/Mod/OSAFE").SetBool(
                        "base_foundation_hide_beams", hide_beams)
            except Exception:
                _err("Draft: error delaying commit")

        # `Creator` is the grandfather class, the parent of `Line`;
        # we need to call it to perform final cleanup tasks.
        #
        # Calling it directly like this is a bit messy; maybe we need
        # another method that performs cleanup (superfinish)
        # that is not re-implemented by any of the child classes.
        gui_base_original.Creator.finish(self)
        if self.ui and self.ui.continueMode:
            self.Activated()
Esempio n. 29
0
    def Activated(self):
        """Execute when the command is called."""
        import Part

        # If there is a selection, and this selection contains various
        # two-point lines, their shapes are extracted, and we attempt
        # to join them into a single Wire (polyline),
        # then the old lines are removed.
        if len(Gui.Selection.getSelection()) > 1:
            edges = []
            for o in Gui.Selection.getSelection():
                if utils.get_type(o) != "Wire":
                    edges = []
                    break
                edges.extend(o.Shape.Edges)
            if edges:
                try:
                    w = Part.Wire(edges)
                except Exception:
                    _err(
                        translate(
                            "draft", "Unable to create a Wire "
                            "from selected objects"))
                else:
                    # Points of the new fused Wire in string form
                    # 'FreeCAD.Vector(x,y,z), FreeCAD.Vector(x1,y1,z1), ...'
                    pts = ", ".join([str(v.Point) for v in w.Vertexes])
                    pts = pts.replace("Vector ", "FreeCAD.Vector")

                    # List of commands to remove the old objects
                    rems = list()
                    for o in Gui.Selection.getSelection():
                        rems.append('FreeCAD.ActiveDocument.'
                                    'removeObject("' + o.Name + '")')

                    Gui.addModule("Draft")
                    # The command to run is built as a series of text strings
                    # to be committed through the `draftutils.todo.ToDo` class
                    _cmd_list = ['wire = Draft.makeWire([' + pts + '])']
                    _cmd_list.extend(rems)
                    _cmd_list.append('Draft.autogroup(wire)')
                    _cmd_list.append('FreeCAD.ActiveDocument.recompute()')

                    _op_name = translate("draft", "Convert to Wire")
                    todo.ToDo.delayCommit([(_op_name, _cmd_list)])
                    return

        # If there was no selection or the selection was just one object
        # then we proceed with the normal line creation functions,
        # only this time we will be able to input more than two points
        super(Wire, self).Activated(name=translate("draft", "Polyline"),
                                    icon="Draft_Wire")
Esempio n. 30
0
    def execute(self, obj):
        """Run when the object is created or recomputed."""
        if not hasattr(obj.Base, 'Shape'):
            _err(_tr("Base object doesn't have a 'Shape', "
                     "it cannot be used for an array."))
            obj.Count = 0
            return

        pt_list, count = get_point_list(obj.PointObject)
        shape = build_copies(obj.Base, pt_list, obj.ExtraPlacement)

        obj.Shape = shape
        obj.Count = count