Exemplo n.º 1
0
 def onChanged(self, vp, prop):
     self.updateCam()
     if prop == 'Total':
         if float(vp.Total) >= float(vp.Subdivision):
             self.xy.mainDim = float(vp.Total)
             self.xz.mainDim = float(vp.Total)
             self.yz.mainDim = float(vp.Total)
         else:
             vp.Total = vp.Subdivision
     if prop == 'Subdivision':
         if float(vp.Total) >= float(vp.Subdivision):
             self.xy.subDim = float(vp.Subdivision)
             self.xz.subDim = float(vp.Subdivision)
             self.yz.subDim = float(vp.Subdivision)
         else:
             vp.Subdivision = vp.Total
     if prop == 'XY_Attenuation':
         if vp.XY_Attenuation < 0.1:
             vp.XY_Attenuation = 0.1
         elif vp.XY_Attenuation > 100:
             vp.XY_Attenuation = 100
         self.xy.factor = vp.XY_Attenuation
     if prop == 'XZ_Attenuation':
         if vp.XZ_Attenuation < 0.1:
             vp.XZ_Attenuation = 0.1
         elif vp.XZ_Attenuation > 100:
             vp.XZ_Attenuation = 100
         self.xz.factor = vp.XZ_Attenuation
     if prop == 'YZ_Attenuation':
         if vp.YZ_Attenuation < 0.1:
             vp.YZ_Attenuation = 0.1
         elif vp.YZ_Attenuation > 100:
             vp.YZ_Attenuation = 100
         self.yz.factor = vp.YZ_Attenuation
     if prop == 'XY_Visibility':
         if vp.XY_Visibility < 0.0:
             vp.XY_Visibility = 0.0
         elif vp.XY_Visibility > 1.0:
             vp.XY_Visibility = 1.0
         self.xy.maxviz = vp.XY_Visibility
     if prop == 'XZ_Visibility':
         if vp.XZ_Visibility < 0.0:
             vp.XZ_Visibility = 0.0
         elif vp.XZ_Visibility > 1.0:
             vp.XZ_Visibility = 1.0
         self.xz.maxviz = vp.XZ_Visibility
     if prop == 'YZ_Visibility':
         if vp.YZ_Visibility < 0.0:
             vp.YZ_Visibility = 0.0
         elif vp.YZ_Visibility > 1.0:
             vp.YZ_Visibility = 1.0
         self.yz.maxviz = vp.YZ_Visibility
     if prop == 'GridColor':
         self.xy.gridcolor = vp.GridColor
         self.xz.gridcolor = vp.GridColor
         self.yz.gridcolor = vp.GridColor
     if prop == 'Placement':
         FreeCAD.Console.PrintMessage('Placement update\n')
         tr = vp.Object.Placement.Base
         ro = vp.Object.Placement.Rotation.Q
         self.trans.translation = coin.SbVec3f(tr.x, tr.y, tr.z)
         self.trans.rotation = coin.SbRotation(ro[0], ro[1], ro[2], ro[3])
         self.xy.updateTransformedNormal()
         self.xz.updateTransformedNormal()
         self.yz.updateTransformedNormal()
Exemplo n.º 2
0
def render(outputfile,scene=None,camera=None,zoom=False,width=400,height=300,background=(1.0,1.0,1.0),lightdir=None):

    """render(outputfile,scene=None,camera=None,zoom=False,width=400,height=300,background=(1.0,1.0,1.0),lightdir=None):
    Renders a PNG image of given width and height and background color from the given coin scene, using
    the given coin camera (ortho or perspective). If zoom is True the camera will be resized to fit all
    objects. The outputfile must be a file path to save a png image. Optionally a light direction as a (x,y,z)
    tuple can be given. In this case, a directional light will be added and shadows will
    be turned on. This might not work with some 3D drivers."""

    # On Linux, the X server must have indirect rendering enabled in order to be able to do offline
    # PNG rendering. Unfortunately, this is turned off by default on most recent distros. The easiest
    # way I found is to edit (or create if inexistent) /etc/X11/xorg.conf and add this:
    #
    # Section "ServerFlags"
    #    Option "AllowIndirectGLX" "on"
    #    Option "IndirectGLX" "on"
    # EndSection
    #
    # But there are other ways, google of GLX indirect rendering

    if isinstance(camera,str):
        camera = getCoinCamera(camera)

    print("Starting offline renderer")
    # build an offline scene root separator
    root = coin.SoSeparator()
    if not lightdir:
        # add one light (mandatory)
        light = coin.SoDirectionalLight()
        root.addChild(light)
    if not camera:
        # create a default camera if none was given
        camera = coin.SoPerspectiveCamera()
        cameraRotation = coin.SbRotation.identity()
        cameraRotation *= coin.SbRotation(coin.SbVec3f(1,0,0),-0.4)
        cameraRotation *= coin.SbRotation(coin.SbVec3f(0,1,0), 0.4)
        camera.orientation = cameraRotation
        # make sure all objects get in the view later
        zoom = True
    root.addChild(camera)
    if scene:
        root.addChild(scene)
    else:
        # no scene was given, add a simple cube
        cube = coin.SoCube()
        root.addChild(cube)
    if lightdir:
        root = embedLight(root,lightdir)
    vpRegion = coin.SbViewportRegion(width,height)
    if zoom:
        camera.viewAll(root,vpRegion)
    print("Creating viewport")
    offscreenRenderer = coin.SoOffscreenRenderer(vpRegion)
    offscreenRenderer.setBackgroundColor(coin.SbColor(background[0],background[1],background[2]))
    print("Ready to render")
    # ref ensures that the node will not be garbage-collected during rendering
    root.ref()
    ok = offscreenRenderer.render(root)
    root.unref()
    if ok:
        offscreenRenderer.writeToFile(outputfile,"PNG")
        print("Rendering",outputfile,"done")
    else:
        print("Error rendering image")
Exemplo n.º 3
0
    def updateData(self, obj, prop):
        """Execute when a property from the Proxy class is changed.

        It only runs if `Start`, `End`, `Dimline`, or `Direction` changed.
        """
        if prop not in ("Start", "End", "Dimline", "Direction"):
            return

        if obj.Start == obj.End:
            return

        if not hasattr(self, "node"):
            return

        vobj = obj.ViewObject

        # Calculate the 4 points
        #
        #       |        d          |
        #   ---p2-------------c----p3----    c
        #       |                   |
        #       |                   |
        #      p1                  p4
        #
        # - `c` is the `Dimline`, a point that lies on the dimension line
        #   or on its extension.
        # - The line itself between `p2` to `p3` is the `base`.
        # - The distance between `p2` (`base`) to `p1` is `proj`, an extension
        #   line from the dimension to the measured object.
        # - If the `proj` distance is zero, `p1` and `p2` are the same point,
        #   and same with `p3` and `p4`.
        #
        self.p1 = obj.Start
        self.p4 = obj.End
        base = None

        if (hasattr(obj, "Direction")
                and not DraftVecUtils.isNull(obj.Direction)):
            v2 = self.p1 - obj.Dimline
            v3 = self.p4 - obj.Dimline
            v2 = DraftVecUtils.project(v2, obj.Direction)
            v3 = DraftVecUtils.project(v3, obj.Direction)
            self.p2 = obj.Dimline + v2
            self.p3 = obj.Dimline + v3
            if DraftVecUtils.equals(self.p2, self.p3):
                base = None
                proj = None
            else:
                base = Part.LineSegment(self.p2, self.p3).toShape()
                proj = DraftGeomUtils.findDistance(self.p1, base)
                if proj:
                    proj = proj.negative()

        if not base:
            if DraftVecUtils.equals(self.p1, self.p4):
                base = None
                proj = None
            else:
                base = Part.LineSegment(self.p1, self.p4).toShape()
                proj = DraftGeomUtils.findDistance(obj.Dimline, base)

            if proj:
                self.p2 = self.p1 + proj.negative()
                self.p3 = self.p4 + proj.negative()
            else:
                self.p2 = self.p1
                self.p3 = self.p4

        if proj:
            if hasattr(vobj, "ExtLines") and hasattr(vobj, "ScaleMultiplier"):
                # The scale multiplier also affects the value
                # of the extension line; this makes sure a maximum length
                # is used if the calculated value is larger than it.
                dmax = vobj.ExtLines.Value * vobj.ScaleMultiplier
                if dmax and proj.Length > dmax:
                    if dmax > 0:
                        self.p1 = self.p2 + DraftVecUtils.scaleTo(proj, dmax)
                        self.p4 = self.p3 + DraftVecUtils.scaleTo(proj, dmax)
                    else:
                        rest = proj.Length + dmax
                        self.p1 = self.p2 + DraftVecUtils.scaleTo(proj, rest)
                        self.p4 = self.p3 + DraftVecUtils.scaleTo(proj, rest)
        else:
            proj = (self.p3 - self.p2).cross(App.Vector(0, 0, 1))

        # Calculate the arrow positions
        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 dimension and extension lines overshoots positions
        self.transDimOvershoot1.translation.setValue(p2)
        self.transDimOvershoot2.translation.setValue(p3)
        self.transExtOvershoot1.translation.setValue(p2)
        self.transExtOvershoot2.translation.setValue(p3)

        # Determine the orientation of the text by using a normal direction.
        # By default the value of +Z will be used, or a calculated value
        # from p2 and p3. So the text will lie on the XY plane
        # or a plane coplanar with p2 and p3.
        u = self.p3 - self.p2
        u.normalize()

        if proj:
            _norm = u.cross(proj)
            norm = _norm.negative()
        else:
            norm = App.Vector(0, 0, 1)

        # If `Normal` exists and is different from the default `(0,0,0)`,
        # it will be used.
        if hasattr(obj, "Normal") and not DraftVecUtils.isNull(obj.Normal):
            norm = App.Vector(obj.Normal)

        if not DraftVecUtils.isNull(norm):
            norm.normalize()

        # Calculate the position of the arrows and extension lines
        v1 = norm.cross(u)
        _plane_rot = DraftVecUtils.getPlaneRotation(u, v1, norm)
        rot1 = App.Placement(_plane_rot).Rotation.Q
        self.transDimOvershoot1.rotation.setValue(
            (rot1[0], rot1[1], rot1[2], rot1[3]))
        self.transDimOvershoot2.rotation.setValue(
            (rot1[0], rot1[1], rot1[2], rot1[3]))

        if hasattr(vobj, "FlipArrows") and vobj.FlipArrows:
            u = u.negative()

        v2 = norm.cross(u)
        _plane_rot = DraftVecUtils.getPlaneRotation(u, v2, norm)
        rot2 = App.Placement(_plane_rot).Rotation.Q
        self.trans1.rotation.setValue((rot2[0], rot2[1], rot2[2], rot2[3]))
        self.trans2.rotation.setValue((rot2[0], rot2[1], rot2[2], rot2[3]))

        if self.p1 != self.p2:
            u3 = self.p1 - self.p2
            u3.normalize()
            v3 = norm.cross(u3)
            _plane_rot = DraftVecUtils.getPlaneRotation(u3, v3, norm)
            rot3 = App.Placement(_plane_rot).Rotation.Q
            self.transExtOvershoot1.rotation.setValue(
                (rot3[0], rot3[1], rot3[2], rot3[3]))
            self.transExtOvershoot2.rotation.setValue(
                (rot3[0], rot3[1], rot3[2], rot3[3]))

        # Offset is the distance from the dimension line to the textual
        # element that displays the value of the measurement
        if hasattr(vobj, "TextSpacing") and hasattr(vobj, "ScaleMultiplier"):
            ts = vobj.TextSpacing.Value * vobj.ScaleMultiplier
            offset = DraftVecUtils.scaleTo(v1, ts)
        else:
            offset = DraftVecUtils.scaleTo(v1, 0.05)

        rott = rot1
        if hasattr(vobj, "FlipText") and vobj.FlipText:
            _rott = App.Rotation(rott[0], rott[1], rott[2], rott[3])
            rott = _rott.multiply(App.Rotation(norm, 180)).Q
            offset = offset.negative()

        # 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)]

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

        # The position of the text element in the dimension is provided
        # in absolute coordinates by the value of `TextPosition`,
        # if it is different from the default `(0,0,0)`
        if (hasattr(vobj, "TextPosition")
                and not DraftVecUtils.isNull(vobj.TextPosition)):
            self.tbase = vobj.TextPosition
        else:
            # Otherwise the position is calculated from the end points
            # of the dimension line, and the offset that depends
            # on `TextSpacing`
            center = self.p2 + (self.p3 - self.p2).multiply(0.5)
            self.tbase = center + offset

        self.textpos.translation.setValue(
            [self.tbase.x, self.tbase.y, self.tbase.z])
        self.textpos.rotation = coin.SbRotation(rott[0], rott[1], rott[2],
                                                rott[3])

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

        # Set text element showing the value of the dimension
        length = (self.p3 - self.p2).Length
        unit = None

        if hasattr(vobj, "UnitOverride"):
            unit = vobj.UnitOverride

        # Special representation if we use 'Building US' scheme
        u_params = App.ParamGet("User parameter:BaseApp/Preferences/Units")
        if u_params.GetInt("UserSchema", 0) == 5:
            s = App.Units.Quantity(length, App.Units.Length).UserString
            self.string = s.replace("' ", "'- ")  # feet
            self.string = s.replace("+", " ")
        elif hasattr(vobj, "Decimals"):
            self.string = units.display_external(length, vobj.Decimals,
                                                 'Length', show_unit, unit)
        else:
            self.string = units.display_external(length, None, 'Length',
                                                 show_unit, unit)

        if hasattr(vobj, "Override") and 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)

        # Set the lines
        if m == "3D":
            # Calculate the spacing of the text
            textsize = len(self.string) * vobj.FontSize.Value / 4.0
            spacing = (self.p3 - self.p2).Length / 2.0 - textsize

            self.p2a = self.p2 + DraftVecUtils.scaleTo(self.p3 - self.p2,
                                                       spacing)
            self.p2b = self.p3 + DraftVecUtils.scaleTo(self.p2 - self.p3,
                                                       spacing)
            self.coords.point.setValues([[self.p1.x, self.p1.y, self.p1.z],
                                         [self.p2.x, self.p2.y, self.p2.z],
                                         [self.p2a.x, self.p2a.y, self.p2a.z],
                                         [self.p2b.x, self.p2b.y, self.p2b.z],
                                         [self.p3.x, self.p3.y, self.p3.z],
                                         [self.p4.x, self.p4.y, self.p4.z]])
            # self.line.numVertices.setValues([3, 3])
            self.line.coordIndex.setValues(0, 7, (0, 1, 2, -1, 3, 4, 5))
        else:
            self.coords.point.setValues([[self.p1.x, self.p1.y, self.p1.z],
                                         [self.p2.x, self.p2.y, self.p2.z],
                                         [self.p3.x, self.p3.y, self.p3.z],
                                         [self.p4.x, self.p4.y, self.p4.z]])
            # self.line.numVertices.setValue(4)
            self.line.coordIndex.setValues(0, 4, (0, 1, 2, 3))
Exemplo 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
Exemplo n.º 5
0
    def drag_rotation(self, vector, modify):
        """
        Manage rotation during dragging
        """

        datum = self.datums['rotation']

        #center is the first selected node
        _ctr = datum['center']

        #ref_vec is the refernce vector from the previous mouse position
        #used to calculate the change in rotation
        _ref_vec = datum['ref_vec']

        #angle is the cumulative angle of rotation
        _angle = datum['angle']

        #non-continuous rotation case
        if not _ctr:

            _ctr = self.datums['drag_start']

            datum['center'] = _ctr

            _ref_vec = vector.sub(_ctr)

            if _ref_vec != Vector():
                _ref_vec.normalize()

            datum['ref_vec'] = _ref_vec

            self.nodes['transform'].center = coin.SbVec3f(tuple(_ctr))

        _ctr = _ctr.add(
            Vector(self.nodes['transform'].translation.getValue())
        )
        #scale the rotation by one-tenth if shift is depressed
        _scale = 1.0

        if modify:
            _scale = 0.1

        #calculate the direction of rotation between the current mouse position
        #vector and the previous.  Normalize and reverse sign on direction.z
        _vec = vector.sub(_ctr)

        if _vec != Vector():
            _vec.normalize()

        _dir = _vec.cross(_ref_vec).z

        if _dir != 0:
            _dir = -_dir / abs(_dir)

        #calculate the cumulatibe rotation
        _rot = _angle + _vec.getAngle(_ref_vec) * _dir * _scale

        #store the updated values
        datum['ref_vec'] = _vec
        datum['angle'] = _rot

        #return the +z axis rotation for the transformation
        return coin.SbRotation(coin.SbVec3f(0.0, 0.0, 1.0), _rot)
Exemplo n.º 6
0
    def makeFrame(self, frame_labels):
        """
Method which makes a Coin3D frame to show a current pose in a RobRotation.

A frame is made from 3 red, green and blue arrows representing X, Y and Z.
Arrows are each constructed from a shaft and an arrowhead. Their dimensions
and other attributes are unassigned as they are extracted from appropriate
`RobRotation` properties.

Returns:
    A SoSeparator with the frame shown in the FreeCAD View.
        """
        # make a generic shaft from 0 in Y direction
        shaft_vertices = coin.SoVertexProperty()
        shaft_vertices.vertex.setNum(2)
        shaft_vertices.vertex.set1Value(0, 0, 0, 0)
        self.frame_shaft = coin.SoLineSet()
        self.frame_shaft.vertexProperty.setValue(shaft_vertices)
        self.frame_shaft.numVertices.setNum(1)
        self.frame_shaft.numVertices.setValue(2)

        # make a generic conic arrowhead oriented in Y axis direction and
        # move it at the end of the shaft
        self.frame_arrowhead_translation = coin.SoTranslation()
        self.frame_arrowhead_cone = coin.SoCone()
        self.frame_arrowhead = coin.SoSwitch()
        self.frame_arrowhead.addChild(self.frame_arrowhead_translation)
        self.frame_arrowhead.addChild(self.frame_arrowhead_cone)

        # make rotations to rotate prepared shaft and arrowhead for Y axis
        # direction also to X and Z
        rot_y2x = coin.SoRotation()
        rot_y2x.rotation.setValue(coin.SbRotation(coin.SbVec3f(0, 1, 0),
                                                  coin.SbVec3f(1, 0, 0)))
        rot_y2z = coin.SoRotation()
        rot_y2z.rotation.setValue(coin.SbRotation(coin.SbVec3f(0, 1, 0),
                                                  coin.SbVec3f(0, 0, 1)))

        # prepare colors for X,Y,Z which will correspond to R,G,B as customary
        self.frame_color_x = coin.SoPackedColor()
        self.frame_color_y = coin.SoPackedColor()
        self.frame_color_z = coin.SoPackedColor()

        # make complete colored and rotated arrows
        x_arrow = coin.SoSeparator()
        x_arrow.addChild(rot_y2x)
        x_arrow.addChild(self.frame_color_x)
        x_arrow.addChild(self.frame_shaft)
        x_arrow.addChild(self.frame_arrowhead)
        x_arrow.addChild(frame_labels[0])
        y_arrow = coin.SoSeparator()
        y_arrow.addChild(self.frame_color_y)
        y_arrow.addChild(self.frame_shaft)
        y_arrow.addChild(self.frame_arrowhead)
        y_arrow.addChild(frame_labels[1])
        z_arrow = coin.SoSeparator()
        z_arrow.addChild(rot_y2z)
        z_arrow.addChild(self.frame_color_z)
        z_arrow.addChild(self.frame_shaft)
        z_arrow.addChild(self.frame_arrowhead)
        z_arrow.addChild(frame_labels[2])

        # prepare draw style to control shaft width
        self.frame_drawstyle = coin.SoDrawStyle()

        # make complete frame and it to shaded display mode
        separated_frame = coin.SoSeparator()
        separated_frame.addChild(self.frame_drawstyle)
        separated_frame.addChild(x_arrow)
        separated_frame.addChild(y_arrow)
        separated_frame.addChild(z_arrow)

        return separated_frame
Exemplo n.º 7
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
Exemplo n.º 8
0
    def updateData(self, obj, prop):
        """called when the base object is changed"""
        import DraftGui
        if prop in ["Start","End","Dimline","Direction"]:

            if obj.Start == obj.End:
                return

            if not hasattr(self,"node"):
                return

            import Part, DraftGeomUtils
            from pivy import coin

            # calculate the 4 points
            self.p1 = obj.Start
            self.p4 = obj.End
            base = None
            if hasattr(obj,"Direction"):
                if not DraftVecUtils.isNull(obj.Direction):
                    v2 = self.p1.sub(obj.Dimline)
                    v3 = self.p4.sub(obj.Dimline)
                    v2 = DraftVecUtils.project(v2,obj.Direction)
                    v3 = DraftVecUtils.project(v3,obj.Direction)
                    self.p2 = obj.Dimline.add(v2)
                    self.p3 = obj.Dimline.add(v3)
                    if DraftVecUtils.equals(self.p2,self.p3):
                        base = None
                        proj = None
                    else:
                        base = Part.LineSegment(self.p2,self.p3).toShape()
                        proj = DraftGeomUtils.findDistance(self.p1,base)
                        if proj:
                            proj = proj.negative()
            if not base:
                if DraftVecUtils.equals(self.p1,self.p4):
                    base = None
                    proj = None
                else:
                    base = Part.LineSegment(self.p1,self.p4).toShape()
                    proj = DraftGeomUtils.findDistance(obj.Dimline,base)
                if proj:
                    self.p2 = self.p1.add(proj.negative())
                    self.p3 = self.p4.add(proj.negative())
                else:
                    self.p2 = self.p1
                    self.p3 = self.p4
            if proj:
                if hasattr(obj.ViewObject,"ExtLines") and hasattr(obj.ViewObject,"ScaleMultiplier"):
                    dmax = obj.ViewObject.ExtLines.Value * obj.ViewObject.ScaleMultiplier
                    if dmax and (proj.Length > dmax):
                        if (dmax > 0):
                            self.p1 = self.p2.add(DraftVecUtils.scaleTo(proj,dmax))
                            self.p4 = self.p3.add(DraftVecUtils.scaleTo(proj,dmax))
                        else:
                            rest = proj.Length + dmax
                            self.p1 = self.p2.add(DraftVecUtils.scaleTo(proj,rest))
                            self.p4 = self.p3.add(DraftVecUtils.scaleTo(proj,rest))
            else:
                proj = (self.p3.sub(self.p2)).cross(App.Vector(0,0,1))

            # calculate the arrows positions
            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 dimension and extension lines overshoots positions
            self.transDimOvershoot1.translation.setValue((self.p2.x,self.p2.y,self.p2.z))
            self.transDimOvershoot2.translation.setValue((self.p3.x,self.p3.y,self.p3.z))
            self.transExtOvershoot1.translation.setValue((self.p2.x,self.p2.y,self.p2.z))
            self.transExtOvershoot2.translation.setValue((self.p3.x,self.p3.y,self.p3.z))

            # calculate the text position and orientation
            if hasattr(obj,"Normal"):
                if DraftVecUtils.isNull(obj.Normal):
                    if proj:
                        norm = (self.p3.sub(self.p2).cross(proj)).negative()
                    else:
                        norm = App.Vector(0,0,1)
                else:
                    norm = App.Vector(obj.Normal)
            else:
                if proj:
                    norm = (self.p3.sub(self.p2).cross(proj)).negative()
                else:
                    norm = App.Vector(0,0,1)
            if not DraftVecUtils.isNull(norm):
                norm.normalize()
            u = self.p3.sub(self.p2)
            u.normalize()
            v1 = norm.cross(u)
            rot1 = App.Placement(DraftVecUtils.getPlaneRotation(u,v1,norm)).Rotation.Q
            self.transDimOvershoot1.rotation.setValue((rot1[0],rot1[1],rot1[2],rot1[3]))
            self.transDimOvershoot2.rotation.setValue((rot1[0],rot1[1],rot1[2],rot1[3]))
            if hasattr(obj.ViewObject,"FlipArrows"):
                if obj.ViewObject.FlipArrows:
                    u = u.negative()
            v2 = norm.cross(u)
            rot2 = App.Placement(DraftVecUtils.getPlaneRotation(u,v2,norm)).Rotation.Q
            self.trans1.rotation.setValue((rot2[0],rot2[1],rot2[2],rot2[3]))
            self.trans2.rotation.setValue((rot2[0],rot2[1],rot2[2],rot2[3]))
            if self.p1 != self.p2:
                u3 = self.p1.sub(self.p2)
                u3.normalize()
                v3 = norm.cross(u3)
                rot3 = App.Placement(DraftVecUtils.getPlaneRotation(u3,v3,norm)).Rotation.Q
                self.transExtOvershoot1.rotation.setValue((rot3[0],rot3[1],rot3[2],rot3[3]))
                self.transExtOvershoot2.rotation.setValue((rot3[0],rot3[1],rot3[2],rot3[3]))
            if hasattr(obj.ViewObject,"TextSpacing") and hasattr(obj.ViewObject,"ScaleMultiplier"):
                ts = obj.ViewObject.TextSpacing.Value * obj.ViewObject.ScaleMultiplier
                offset = DraftVecUtils.scaleTo(v1,ts)
            else:
                offset = DraftVecUtils.scaleTo(v1,0.05)
            rott = rot1
            if hasattr(obj.ViewObject,"FlipText"):
                if obj.ViewObject.FlipText:
                    rott = App.Rotation(*rott).multiply(App.Rotation(norm,180)).Q
                    offset = offset.negative()
            # setting text
            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)]
            if m == "3D":
                offset = offset.negative()
            self.tbase = (self.p2.add((self.p3.sub(self.p2).multiply(0.5)))).add(offset)
            if hasattr(obj.ViewObject,"TextPosition"):
                if not DraftVecUtils.isNull(obj.ViewObject.TextPosition):
                    self.tbase = obj.ViewObject.TextPosition
            self.textpos.translation.setValue([self.tbase.x,self.tbase.y,self.tbase.z])
            self.textpos.rotation = coin.SbRotation(rott[0],rott[1],rott[2],rott[3])
            su = True
            if hasattr(obj.ViewObject,"ShowUnit"):
                su = obj.ViewObject.ShowUnit
            # set text value
            l = self.p3.sub(self.p2).Length
            unit = None
            if hasattr(obj.ViewObject,"UnitOverride"):
                unit = obj.ViewObject.UnitOverride
            # special representation if "Building US" scheme
            if App.ParamGet("User parameter:BaseApp/Preferences/Units").GetInt("UserSchema",0) == 5:
                s = App.Units.Quantity(l,App.Units.Length).UserString
                self.string = s.replace("' ","'- ")
                self.string = s.replace("+"," ")
            elif hasattr(obj.ViewObject,"Decimals"):
                self.string = DraftGui.displayExternal(l,obj.ViewObject.Decimals,'Length',su,unit)
            else:
                self.string = DraftGui.displayExternal(l,None,'Length',su,unit)
            if hasattr(obj.ViewObject,"Override"):
                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)

            # set the lines
            if m == "3D":
                # calculate the spacing of the text
                textsize = (len(self.string)*obj.ViewObject.FontSize.Value)/4.0
                spacing = ((self.p3.sub(self.p2)).Length/2.0) - textsize
                self.p2a = self.p2.add(DraftVecUtils.scaleTo(self.p3.sub(self.p2),spacing))
                self.p2b = self.p3.add(DraftVecUtils.scaleTo(self.p2.sub(self.p3),spacing))
                self.coords.point.setValues([[self.p1.x,self.p1.y,self.p1.z],
                                             [self.p2.x,self.p2.y,self.p2.z],
                                             [self.p2a.x,self.p2a.y,self.p2a.z],
                                             [self.p2b.x,self.p2b.y,self.p2b.z],
                                             [self.p3.x,self.p3.y,self.p3.z],
                                             [self.p4.x,self.p4.y,self.p4.z]])
                #self.line.numVertices.setValues([3,3])
                self.line.coordIndex.setValues(0,7,(0,1,2,-1,3,4,5))
            else:
                self.coords.point.setValues([[self.p1.x,self.p1.y,self.p1.z],
                                             [self.p2.x,self.p2.y,self.p2.z],
                                             [self.p3.x,self.p3.y,self.p3.z],
                                             [self.p4.x,self.p4.y,self.p4.z]])
                #self.line.numVertices.setValue(4)
                self.line.coordIndex.setValues(0,4,(0,1,2,3))
Exemplo n.º 9
0
    def makeFrame(self, frame_labels):
        # make a generic shaft from 0 in Y direction
        shaft_vertices = coin.SoVertexProperty()
        shaft_vertices.vertex.setNum(2)
        shaft_vertices.vertex.set1Value(0, 0, 0, 0)
        self.frame_shaft = coin.SoLineSet()
        self.frame_shaft.vertexProperty.setValue(shaft_vertices)
        self.frame_shaft.numVertices.setNum(1)
        self.frame_shaft.numVertices.setValue(2)

        # make a generic conic arrowhead oriented in Y axis direction and
        # move it at the end of the shaft
        self.frame_arrowhead_translation = coin.SoTranslation()
        self.frame_arrowhead_cone = coin.SoCone()
        self.frame_arrowhead = coin.SoSwitch()
        self.frame_arrowhead.addChild(self.frame_arrowhead_translation)
        self.frame_arrowhead.addChild(self.frame_arrowhead_cone)

        # make rotations to rotate prepared shaft and arrowhead for Y axis
        # direction also to X and Z
        rot_y2x = coin.SoRotation()
        rot_y2x.rotation.setValue(
            coin.SbRotation(coin.SbVec3f(0, 1, 0), coin.SbVec3f(1, 0, 0)))
        rot_y2z = coin.SoRotation()
        rot_y2z.rotation.setValue(
            coin.SbRotation(coin.SbVec3f(0, 1, 0), coin.SbVec3f(0, 0, 1)))

        # prepare colors for X,Y,Z which will correspond to R,G,B as customary
        self.frame_color_x = coin.SoPackedColor()
        self.frame_color_y = coin.SoPackedColor()
        self.frame_color_z = coin.SoPackedColor()

        # make complete colored and rotated arrows
        x_arrow = coin.SoSeparator()
        x_arrow.addChild(rot_y2x)
        x_arrow.addChild(self.frame_color_x)
        x_arrow.addChild(self.frame_shaft)
        x_arrow.addChild(self.frame_arrowhead)
        x_arrow.addChild(frame_labels[0])
        y_arrow = coin.SoSeparator()
        y_arrow.addChild(self.frame_color_y)
        y_arrow.addChild(self.frame_shaft)
        y_arrow.addChild(self.frame_arrowhead)
        y_arrow.addChild(frame_labels[1])
        z_arrow = coin.SoSeparator()
        z_arrow.addChild(rot_y2z)
        z_arrow.addChild(self.frame_color_z)
        z_arrow.addChild(self.frame_shaft)
        z_arrow.addChild(self.frame_arrowhead)
        z_arrow.addChild(frame_labels[2])

        # prepare draw style to control shaft width
        self.frame_drawstyle = coin.SoDrawStyle()

        # make complete frame and it to shaded display mode
        separated_frame = coin.SoSeparator()
        separated_frame.addChild(self.frame_drawstyle)
        separated_frame.addChild(x_arrow)
        separated_frame.addChild(y_arrow)
        separated_frame.addChild(z_arrow)

        return separated_frame