Ejemplo n.º 1
0
    def execute(self, obj):
        """Execute when the object is created or recomputed.

        Set start point and end point according to the linked geometry
        and the number of subelements.

        If it has one subelement, we assume a straight edge or a circular edge.
        If it has two subelements, we assume a straight edge (two vertices).
        """
        if obj.LinkedGeometry:
            if len(obj.LinkedGeometry) == 1:
                linked_obj = obj.LinkedGeometry[0][0]
                sub_list = obj.LinkedGeometry[0][1]

                if len(sub_list) == 1:
                    # If it has one subelement, we assume an edge
                    # that can be a straight line, or a circular edge
                    subelement = sub_list[0]
                    (obj.Start,
                     obj.End) = measure_one_obj_edge(linked_obj,
                                                     subelement,
                                                     obj.Dimline,
                                                     obj.Diameter)
                elif len(sub_list) == 2:
                    # If it has two subelements, we assume a straight edge
                    # that is measured by two vertices
                    (obj.Start,
                     obj.End) = measure_one_obj_vertices(linked_obj,
                                                         sub_list)

            elif len(obj.LinkedGeometry) == 2:
                # If the list has two objects, it measures the distance
                # between the two vertices in those two objects
                (obj.Start,
                 obj.End) = measure_two_objects(obj.LinkedGeometry[0],
                                                obj.LinkedGeometry[1])

        # Update the distance property by comparing the floats
        # with the precision
        net_length = (obj.Start.sub(obj.End)).Length
        rounded_1 = round(obj.Distance.Value, utils.precision())
        rounded_2 = round(net_length, utils.precision())

        if rounded_1 != rounded_2:
            obj.Distance = net_length

        # The lines and text are created in the viewprovider, so we should
        # update it whenever the object is recomputed
        if App.GuiUp and obj.ViewObject:
            obj.ViewObject.update()
Ejemplo n.º 2
0
    def update_arrow(self, obj, vobj):
        """Update the arrow tip of the line."""
        if hasattr(self, "symbol"):
            if self.arrow.findChild(self.symbol) != -1:
                self.arrow.removeChild(self.symbol)

        s = utils.ARROW_TYPES.index(vobj.ArrowType)
        self.symbol = gui_utils.dim_symbol(s)
        self.arrow.addChild(self.symbol)

        prec = 10**(-utils.precision())
        x_axis = App.Vector(1, 0, 0)
        target_dir = None
        # search in Points to get first point != to TargetPoint and use it
        # to get the target line direction
        for pnt in obj.Points[-2::-1]:
            if not pnt.isEqual(obj.Points[-1], prec):
                target_dir = pnt.sub(obj.Points[-1])
                break
        if target_dir is None:
            target_dir = x_axis
        target_dir_xy = obj.Placement.Rotation.inverted() * target_dir
        angle = target_dir_xy.getAngle(x_axis) * App.Units.Radian
        axis = x_axis.cross(target_dir_xy)
        rot = App.Rotation(axis, angle)

        self.arrowpos.rotation.setValue((obj.Placement.Rotation * rot).Q)
        self.arrowpos.translation.setValue(obj.Points[-1])
Ejemplo n.º 3
0
    def updateData(self, obj, prop):
        if hasattr(self, "arc"):
            from pivy import coin
            import Part, DraftGeomUtils
            import DraftGui
            arcsegs = 24

            # calculate the arc data
            if DraftVecUtils.isNull(obj.Normal):
                norm = App.Vector(0, 0, 1)
            else:
                norm = obj.Normal
            radius = (obj.Dimline.sub(obj.Center)).Length
            self.circle = Part.makeCircle(radius, obj.Center, norm,
                                          obj.FirstAngle.Value,
                                          obj.LastAngle.Value)
            self.p2 = self.circle.Vertexes[0].Point
            self.p3 = self.circle.Vertexes[-1].Point
            mp = DraftGeomUtils.findMidpoint(self.circle.Edges[0])
            ray = mp.sub(obj.Center)

            # set text value
            if obj.LastAngle.Value > obj.FirstAngle.Value:
                a = obj.LastAngle.Value - obj.FirstAngle.Value
            else:
                a = (360 - obj.FirstAngle.Value) + obj.LastAngle.Value
            su = True
            if hasattr(obj.ViewObject, "ShowUnit"):
                su = obj.ViewObject.ShowUnit
            if hasattr(obj.ViewObject, "Decimals"):
                self.string = DraftGui.displayExternal(a,
                                                       obj.ViewObject.Decimals,
                                                       'Angle', su)
            else:
                self.string = DraftGui.displayExternal(a, None, 'Angle', su)
            if obj.ViewObject.Override:
                self.string = obj.ViewObject.Override.replace("$dim",\
                    self.string)
            self.text.string = self.text3d.string = utils.string_encode_coin(
                self.string)

            # check display mode
            try:
                m = obj.ViewObject.DisplayMode
            except:  # swallow all exceptions here since it always fails on first run (Displaymode enum no set yet)
                m = ["2D", "3D"][utils.get_param("dimstyle", 0)]

            # set the arc
            if m == "3D":
                # calculate the spacing of the text
                spacing = (len(self.string) *
                           obj.ViewObject.FontSize.Value) / 8.0
                pts1 = []
                cut = None
                pts2 = []
                for i in range(arcsegs + 1):
                    p = self.circle.valueAt(self.circle.FirstParameter + (
                        (self.circle.LastParameter -
                         self.circle.FirstParameter) / arcsegs) * i)
                    if (p.sub(mp)).Length <= spacing:
                        if cut is None:
                            cut = i
                    else:
                        if cut is None:
                            pts1.append([p.x, p.y, p.z])
                        else:
                            pts2.append([p.x, p.y, p.z])
                self.coords.point.setValues(pts1 + pts2)
                i1 = len(pts1)
                i2 = i1 + len(pts2)
                self.arc.coordIndex.setValues(
                    0,
                    len(pts1) + len(pts2) + 1,
                    list(range(len(pts1))) + [-1] + list(range(i1, i2)))
                if (len(pts1) >= 3) and (len(pts2) >= 3):
                    self.circle1 = Part.Arc(
                        App.Vector(pts1[0][0], pts1[0][1], pts1[0][2]),
                        App.Vector(pts1[1][0], pts1[1][1], pts1[1][2]),
                        App.Vector(pts1[-1][0], pts1[-1][1],
                                   pts1[-1][2])).toShape()
                    self.circle2 = Part.Arc(
                        App.Vector(pts2[0][0], pts2[0][1], pts2[0][2]),
                        App.Vector(pts2[1][0], pts2[1][1], pts2[1][2]),
                        App.Vector(pts2[-1][0], pts2[-1][1],
                                   pts2[-1][2])).toShape()
            else:
                pts = []
                for i in range(arcsegs + 1):
                    p = self.circle.valueAt(self.circle.FirstParameter + (
                        (self.circle.LastParameter -
                         self.circle.FirstParameter) / arcsegs) * i)
                    pts.append([p.x, p.y, p.z])
                self.coords.point.setValues(pts)
                self.arc.coordIndex.setValues(0, arcsegs + 1,
                                              list(range(arcsegs + 1)))

            # set the arrow coords and rotation
            self.trans1.translation.setValue((self.p2.x, self.p2.y, self.p2.z))
            self.coord1.point.setValue((self.p2.x, self.p2.y, self.p2.z))
            self.trans2.translation.setValue((self.p3.x, self.p3.y, self.p3.z))
            self.coord2.point.setValue((self.p3.x, self.p3.y, self.p3.z))
            # calculate small chords to make arrows look better
            arrowlength = 4 * obj.ViewObject.ArrowSize.Value
            u1 = (self.circle.valueAt(self.circle.FirstParameter + arrowlength)
                  ).sub(self.circle.valueAt(
                      self.circle.FirstParameter)).normalize()
            u2 = (self.circle.valueAt(self.circle.LastParameter)).sub(
                self.circle.valueAt(self.circle.LastParameter -
                                    arrowlength)).normalize()
            if hasattr(obj.ViewObject, "FlipArrows"):
                if obj.ViewObject.FlipArrows:
                    u1 = u1.negative()
                    u2 = u2.negative()
            w2 = self.circle.Curve.Axis
            w1 = w2.negative()
            v1 = w1.cross(u1)
            v2 = w2.cross(u2)
            q1 = App.Placement(DraftVecUtils.getPlaneRotation(u1, v1,
                                                              w1)).Rotation.Q
            q2 = App.Placement(DraftVecUtils.getPlaneRotation(u2, v2,
                                                              w2)).Rotation.Q
            self.trans1.rotation.setValue((q1[0], q1[1], q1[2], q1[3]))
            self.trans2.rotation.setValue((q2[0], q2[1], q2[2], q2[3]))

            # setting text pos & rot
            self.tbase = mp
            if hasattr(obj.ViewObject, "TextPosition"):
                if not DraftVecUtils.isNull(obj.ViewObject.TextPosition):
                    self.tbase = obj.ViewObject.TextPosition

            u3 = ray.cross(norm).normalize()
            v3 = norm.cross(u3)
            r = App.Placement(DraftVecUtils.getPlaneRotation(u3, v3,
                                                             norm)).Rotation
            offset = r.multVec(App.Vector(0, 1, 0))

            if hasattr(obj.ViewObject, "TextSpacing"):
                offset = DraftVecUtils.scaleTo(
                    offset, obj.ViewObject.TextSpacing.Value)
            else:
                offset = DraftVecUtils.scaleTo(offset, 0.05)
            if m == "3D":
                offset = offset.negative()
            self.tbase = self.tbase.add(offset)
            q = r.Q
            self.textpos.translation.setValue(
                [self.tbase.x, self.tbase.y, self.tbase.z])
            self.textpos.rotation = coin.SbRotation(q[0], q[1], q[2], q[3])

            # set the angle property
            if round(obj.Angle, utils.precision()) != round(
                    a, utils.precision()):
                obj.Angle = a
Ejemplo n.º 4
0
    def updateData(self, obj, prop):
        """Execute when a property from the Proxy class is changed."""
        if not hasattr(self, "arc"):
            return

        arcsegs = 24

        vobj = obj.ViewObject

        # Determine the orientation of the text by using a normal direction.
        # Also calculate the arc data.
        if DraftVecUtils.isNull(obj.Normal):
            norm = App.Vector(0, 0, 1)
        else:
            norm = obj.Normal

        radius = (obj.Dimline - obj.Center).Length
        self.circle = Part.makeCircle(radius, obj.Center, norm,
                                      obj.FirstAngle.Value,
                                      obj.LastAngle.Value)
        self.p2 = self.circle.Vertexes[0].Point
        self.p3 = self.circle.Vertexes[-1].Point
        midp = DraftGeomUtils.findMidpoint(self.circle.Edges[0])
        ray = midp - obj.Center

        # Set text value
        if obj.LastAngle.Value > obj.FirstAngle.Value:
            angle = obj.LastAngle.Value - obj.FirstAngle.Value
        else:
            angle = (360 - obj.FirstAngle.Value) + obj.LastAngle.Value

        show_unit = True
        if hasattr(vobj, "ShowUnit"):
            show_unit = vobj.ShowUnit

        if hasattr(vobj, "Decimals"):
            self.string = units.display_external(angle, vobj.Decimals, 'Angle',
                                                 show_unit)
        else:
            self.string = units.display_external(angle, None, 'Angle',
                                                 show_unit)

        if vobj.Override:
            self.string = vobj.Override.replace("$dim", self.string)

        self.text.string = utils.string_encode_coin(self.string)
        self.text3d.string = utils.string_encode_coin(self.string)

        # On first run the `DisplayMode` enumeration is not set, so we trap
        # the exception and set the display mode using the value
        # in the parameter database
        try:
            m = vobj.DisplayMode
        except AssertionError:
            m = ["2D", "3D"][utils.get_param("dimstyle", 0)]

        # Set the arc
        first = self.circle.FirstParameter
        last = self.circle.LastParameter

        if m == "3D":
            # Calculate the spacing of the text
            spacing = len(self.string) * vobj.FontSize.Value / 8.0
            pts1 = []
            cut = None
            pts2 = []

            for i in range(arcsegs + 1):
                p = self.circle.valueAt(first + (last - first) / arcsegs * i)
                if (p - midp).Length <= spacing:
                    if cut is None:
                        cut = i
                else:
                    if cut is None:
                        pts1.append([p.x, p.y, p.z])
                    else:
                        pts2.append([p.x, p.y, p.z])

            self.coords.point.setValues(pts1 + pts2)

            pts1_num = len(pts1)
            pts2_num = len(pts2)
            i1 = pts1_num
            i2 = i1 + pts2_num

            self.arc.coordIndex.setValues(
                0, pts1_num + pts2_num + 1,
                list(range(pts1_num)) + [-1] + list(range(i1, i2)))

            if pts1_num >= 3 and pts2_num >= 3:
                self.circle1 = Part.Arc(
                    App.Vector(pts1[0][0], pts1[0][1], pts1[0][2]),
                    App.Vector(pts1[1][0], pts1[1][1], pts1[1][2]),
                    App.Vector(pts1[-1][0], pts1[-1][1],
                               pts1[-1][2])).toShape()
                self.circle2 = Part.Arc(
                    App.Vector(pts2[0][0], pts2[0][1], pts2[0][2]),
                    App.Vector(pts2[1][0], pts2[1][1], pts2[1][2]),
                    App.Vector(pts2[-1][0], pts2[-1][1],
                               pts2[-1][2])).toShape()
        else:
            pts = []
            for i in range(arcsegs + 1):
                p = self.circle.valueAt(first + (last - first) / arcsegs * i)
                pts.append([p.x, p.y, p.z])

            self.coords.point.setValues(pts)
            self.arc.coordIndex.setValues(0, arcsegs + 1,
                                          list(range(arcsegs + 1)))

        # Set the arrow coords and rotation
        p2 = (self.p2.x, self.p2.y, self.p2.z)
        p3 = (self.p3.x, self.p3.y, self.p3.z)

        self.trans1.translation.setValue(p2)
        self.coord1.point.setValue(p2)
        self.trans2.translation.setValue(p3)
        self.coord2.point.setValue(p3)

        # Calculate small chords to make arrows look better
        arrowlength = 4 * vobj.ArrowSize.Value
        u1 = (self.circle.valueAt(first + arrowlength) -
              self.circle.valueAt(first)).normalize()
        u2 = (self.circle.valueAt(last) -
              self.circle.valueAt(last - arrowlength)).normalize()
        if hasattr(vobj, "FlipArrows") and vobj.FlipArrows:
            u1 = u1.negative()
            u2 = u2.negative()

        w2 = self.circle.Curve.Axis
        w1 = w2.negative()

        v1 = w1.cross(u1)
        v2 = w2.cross(u2)
        _plane_rot_1 = DraftVecUtils.getPlaneRotation(u1, v1, w1)
        _plane_rot_2 = DraftVecUtils.getPlaneRotation(u2, v2, w2)
        q1 = App.Placement(_plane_rot_1).Rotation.Q
        q2 = App.Placement(_plane_rot_2).Rotation.Q

        self.trans1.rotation.setValue((q1[0], q1[1], q1[2], q1[3]))
        self.trans2.rotation.setValue((q2[0], q2[1], q2[2], q2[3]))

        # Set text position and rotation
        self.tbase = midp
        if (hasattr(vobj, "TextPosition")
                and not DraftVecUtils.isNull(vobj.TextPosition)):
            self.tbase = vobj.TextPosition

        u3 = ray.cross(norm).normalize()
        v3 = norm.cross(u3)
        _plane_rot_3 = DraftVecUtils.getPlaneRotation(u3, v3, norm)
        r = App.Placement(_plane_rot_3).Rotation
        offset = r.multVec(App.Vector(0, 1, 0))

        if hasattr(vobj, "TextSpacing"):
            offset = DraftVecUtils.scaleTo(offset, vobj.TextSpacing.Value)
        else:
            offset = DraftVecUtils.scaleTo(offset, 0.05)

        if m == "3D":
            offset = offset.negative()

        self.tbase = self.tbase.add(offset)
        q = r.Q
        self.textpos.translation.setValue(
            [self.tbase.x, self.tbase.y, self.tbase.z])
        self.textpos.rotation = coin.SbRotation(q[0], q[1], q[2], q[3])

        # Set the angle property
        _round_1 = round(obj.Angle, utils.precision())
        _round_2 = round(angle, utils.precision())
        if _round_1 != _round_2:
            obj.Angle = angle