Draftからsvg変換の線幅が0.35固定となっている。

Japanese forum
3939yoshi
Posts: 19
Joined: Thu Mar 02, 2017 5:24 am

Draftからsvg変換の線幅が0.35固定となっている。

Post by 3939yoshi »

Draftワークベンチに書いた線の線幅(Line Width)に1,2,3など設定しても、SVGでは0.35となる。
変換後、Pageのプロパティから手動で変更は可能である。
FreeCAD_0.17\Mod\Drift\Drift.py の class _DrawingView を修正すればよさそうだが、よくわからない。
どなたかわかりますか?

(参考:矢印のsvgでの形状はDrift.pyのgetArrow()を変更すれば簡単に修正できそうです。)
( とりあえず、線幅と矢印形が課題です。 )
User avatar
h.tsubota
Posts: 81
Joined: Mon Mar 21, 2016 2:09 pm
Location: Osaka, Japan
Contact:

Re: Draftからsvg変換の線幅が0.35固定となっている。

Post by h.tsubota »

手元のバージョン0.16でDraft.pyを確認してみました。

ソースコードを読んだ限りでは makeDrawingView() 内で属性を引き継いでいる様なので、ここで「LineColor」などと同じように

Code: Select all

if hasattr(obj.ViewObject,"LineWidth"):
    viewobj.LineWidth = obj.ViewObject.LineWidth
としてやればいいのではないかと思いました(※動作確認はしていません)。
3939yoshi
Posts: 19
Joined: Thu Mar 02, 2017 5:24 am

Re: Draftからsvg変換の線幅が0.35固定となっている。

Post by 3939yoshi »

Draft.pyの makeDrawingView()最後を以下のように変更したところ、テストした範囲ではOKでした。
これで、細線(0.08)、中線、太線が簡単に書けるようになりました。
フォントサイズも設定しました。
点線や破線や一点鎖線は[設定][Drift][表示設定]を初期値から変更しました。
ありがとうございました。
後は矢印を修正してみようと思います。

Code: Select all

        if hasattr(obj.ViewObject,"LineColor"):
            viewobj.LineColor = obj.ViewObject.LineColor
        elif hasattr(obj.ViewObject,"TextColor"):
            viewobj.LineColor = obj.ViewObject.TextColor
    return viewobj

Code: Select all

        if hasattr(obj.ViewObject,"LineColor"):
            viewobj.LineColor = obj.ViewObject.LineColor
        elif hasattr(obj.ViewObject,"TextColor"):
            viewobj.LineColor = obj.ViewObject.TextColor
        if hasattr(obj.ViewObject,"LineWidth"):
            viewobj.LineWidth = obj.ViewObject.LineWidth * 0.08
        if hasattr(obj.ViewObject,"FontSize"):
            viewobj.FontSize = obj.ViewObject.FontSize
    return viewobj
3939yoshi
Posts: 19
Joined: Thu Mar 02, 2017 5:24 am

Re: Draftからsvg変換の線幅が0.35固定となっている。

Post by 3939yoshi »

DraftのフォントファミリーにMeiryoを使用しています。以下のように2倍にするとだいたいsvgの文字の大きさがあいます。試した結果です。

Code: Select all

        if hasattr(obj.ViewObject,"LineColor"):
            viewobj.LineColor = obj.ViewObject.LineColor
        elif hasattr(obj.ViewObject,"TextColor"):
            viewobj.LineColor = obj.ViewObject.TextColor
        if hasattr(obj.ViewObject,"LineWidth"):
            viewobj.LineWidth = obj.ViewObject.LineWidth * 0.08
        if hasattr(obj.ViewObject,"FontSize"):
            viewobj.FontSize = obj.ViewObject.FontSize * 2
    return viewobj
3939yoshi
Posts: 19
Joined: Thu Mar 02, 2017 5:24 am

Re: Draftからsvg変換の線幅が0.35固定となっている。

Post by 3939yoshi »

svgへ出力される矢印の形状を塗りつぶしから線の変更点です。
Draft.pyのgetArrow()内を以下のように変更します。svgに出力した図が全体的に製図ぽっくなります。

Code: Select all

        elif obj.ViewObject.ArrowType == "Arrow":
            svg += '<path transform="rotate('+str(math.degrees(angle))
            svg += ','+ str(point.x) + ',' + str(point.y) + ') '
            svg += 'translate(' + str(point.x) + ',' + str(point.y) + ') '
            svg += 'scale('+str(arrowsize)+','+str(arrowsize)+')" freecad:skip="1" '
            svg += 'fill="'+ color +'" stroke="none" '
            svg += 'style="stroke-miterlimit:4;stroke-dasharray:none" '
            svg += 'd="M 0 0 L 4 1 L 4 -1 Z"/>\n'
        elif obj.ViewObject.ArrowType == "Tick":

Code: Select all

        elif obj.ViewObject.ArrowType == "Arrow":
            svg += '<path transform="rotate('+str(math.degrees(angle))
            svg += ','+ str(point.x) + ',' + str(point.y) + ') '
            svg += 'translate(' + str(point.x) + ',' + str(point.y) + ') '
            svg += 'scale('+str(arrowsize)+','+str(arrowsize)+')" freecad:skip="1" '
            svg += 'fill="none" stroke="'+ color + '" '
            svg += 'style="stroke-width:'+ str(linewidth) + ';stroke-miterlimit:4;stroke-dasharray:none" '
            svg += 'd="M 4 1 L 0 0 L 4 -1"/>\n'            
        elif obj.ViewObject.ArrowType == "Tick":
元々線の"EndArrow"や角度寸法の矢印の向きがsvgにしたとき正しくないようです。
確認してみようと思います。
3939yoshi
Posts: 19
Joined: Thu Mar 02, 2017 5:24 am

Re: Draftからsvg変換の線幅が0.35固定となっている。

Post by 3939yoshi »

直線や折れ線のEndArrowのsvgでの矢印向きの修正です。
Draft.pyのgetSVG()の一番最後です。
"+math.pi"を追加しています。

Code: Select all

        if FreeCAD.GuiUp:
            if hasattr(obj.ViewObject,"EndArrow") and hasattr(obj.ViewObject,"ArrowType") and (len(obj.Shape.Vertexes) > 1):
                if obj.ViewObject.EndArrow:
                    p1 = getProj(obj.Shape.Vertexes[-2].Point)
                    p2 = getProj(obj.Shape.Vertexes[-1].Point)
                    angle = -DraftVecUtils.angle(p2.sub(p1))
                    arrowsize = obj.ViewObject.ArrowSize.Value/pointratio
                    svg += getArrow(obj.ViewObject.ArrowType,p2,arrowsize,stroke,linewidth,angle)
    return svg

Code: Select all

        if FreeCAD.GuiUp:
            if hasattr(obj.ViewObject,"EndArrow") and hasattr(obj.ViewObject,"ArrowType") and (len(obj.Shape.Vertexes) > 1):
                if obj.ViewObject.EndArrow:
                    p1 = getProj(obj.Shape.Vertexes[-2].Point)
                    p2 = getProj(obj.Shape.Vertexes[-1].Point)
                    angle = -DraftVecUtils.angle(p2.sub(p1))+math.pi
                    arrowsize = obj.ViewObject.ArrowSize.Value/pointratio
                    svg += getArrow(obj.ViewObject.ArrowType,p2,arrowsize,stroke,linewidth,angle)
    return svg
3939yoshi
Posts: 19
Joined: Thu Mar 02, 2017 5:24 am

Re: Draftからsvg変換の線幅が0.35固定となっている。

Post by 3939yoshi »

Draftワークベンチのメイン画面の角度寸法線の矢印の向きを修正しました。
Draft.pyの class _ViewProviderAngularDimension() の def updateData()内です。

Code: Select all

            # 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 = FreeCAD.Placement(DraftVecUtils.getPlaneRotation(u1,v1,w1)).Rotation.Q
            q2 = FreeCAD.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]))

Code: Select all

            # calculate small chords to make arrows look better
            arrowlength = 4*obj.ViewObject.ArrowSize.Value/self.circle.Curve.Radius
            arrowlength = min([arrowlength,math.pi/4])
            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 = FreeCAD.Placement(DraftVecUtils.getPlaneRotation(u1,v1,w1)).Rotation.Q
            q2 = FreeCAD.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]))
あとはsvgの角度寸法線の矢印です。
3939yoshi
Posts: 19
Joined: Thu Mar 02, 2017 5:24 am

Re: Draftからsvg変換の線幅が0.35固定となっている。

Post by 3939yoshi »

svgの角度寸法線の矢印向きの修正点です。
Draft.pyのgetSVG内です。

Code: Select all

                # drawing arrows
                if hasattr(obj.ViewObject,"ArrowType"):
                    p2 = getProj(prx.p2)
                    p3 = getProj(prx.p3)
                    arrowsize = obj.ViewObject.ArrowSize.Value/pointratio
                    arrowlength = 4*obj.ViewObject.ArrowSize.Value
                    u1 = getProj((prx.circle.valueAt(prx.circle.FirstParameter+arrowlength)).sub(prx.circle.valueAt(prx.circle.FirstParameter)))
                    u2 = getProj((prx.circle.valueAt(prx.circle.LastParameter-arrowlength)).sub(prx.circle.valueAt(prx.circle.LastParameter)))

Code: Select all

                # drawing arrows
                if hasattr(obj.ViewObject,"ArrowType"):
                    p2 = getProj(prx.p2)
                    p3 = getProj(prx.p3)
                    arrowsize = obj.ViewObject.ArrowSize.Value/pointratio
                    arrowlength = 4*obj.ViewObject.ArrowSize.Value/prx.circle.Curve.Radius
                    arrowlength = min([arrowlength,math.pi/4])
                    u1 = getProj((prx.circle.valueAt(prx.circle.FirstParameter+arrowlength)).sub(prx.circle.valueAt(prx.circle.FirstParameter)))
                    u2 = getProj((prx.circle.valueAt(prx.circle.LastParameter-arrowlength)).sub(prx.circle.valueAt(prx.circle.LastParameter)))
3939yoshi
Posts: 19
Joined: Thu Mar 02, 2017 5:24 am

Re: Draftからsvg変換の線幅が0.35固定となっている。

Post by 3939yoshi »

svgで円弧が正しく表示されない問題の修正点です。
Draft.py のgetSVG()関数内です。

Code: Select all

                        # arc
                        if iscircle:
                            rx = ry = c.Radius
                            rot = 0
                        else: #ellipse
                            rx = c.MajorRadius
                            ry = c.MinorRadius
                            rot = math.degrees(c.AngleXU * (c.Axis * \
                                FreeCAD.Vector(0,0,1)))
                            if rot > 90:
                                rot -=180
                            if rot < -90:
                                rot += 180
                            #be carefull with the sweep flag
                        flag_large_arc = (((e.ParameterRange[1] - \
                                e.ParameterRange[0]) / math.pi) % 2) > 1
                        #flag_sweep = (c.Axis * drawing_plane_normal >= 0) \
                        #         == (e.LastParameter > e.FirstParameter)
                        #        == (e.Orientation == "Forward")
                        # other method: check the direction of the angle between tangents
                        t1 = e.tangentAt(e.FirstParameter)
                        t2 = e.tangentAt(e.FirstParameter + (e.LastParameter-e.FirstParameter)/10)
                        flag_sweep = (DraftVecUtils.angle(t1,t2,drawing_plane_normal) < 0)
                        for v in endpoints:
                            edata += 'A %s %s %s %s %s %s %s ' % \
                                    (str(rx),str(ry),str(rot),\
                                    str(int(flag_large_arc)),\
                                    str(int(flag_sweep)),str(v.x),str(v.y))
                    else:
                        edata += getDiscretized(e)

Code: Select all

                        # arc
                        if iscircle:
                            rx = ry = c.Radius
                            rot = 0
                        else: #ellipse
                            rx = c.MajorRadius
                            ry = c.MinorRadius
                            rot = math.degrees(c.AngleXU * (c.Axis * \
                                FreeCAD.Vector(0,0,1)))
                            if rot > 90:
                                rot -=180
                            if rot < -90:
                                rot += 180
                            #be carefull with the sweep flag
                        flag_large_arc = (((e.ParameterRange[1] - \
                                e.ParameterRange[0]) / math.pi) % 2) > 1
                        #flag_sweep = (c.Axis * drawing_plane_normal >= 0) \
                        #         == (e.LastParameter > e.FirstParameter)
                        #        == (e.Orientation == "Forward")
                        # other method: check the direction of the angle between tangents

                        #t1 = e.tangentAt(e.FirstParameter)
                        #t2 = e.tangentAt(e.FirstParameter + (e.LastParameter-e.FirstParameter)/10)
                        #flag_sweep = (DraftVecUtils.angle(t1,t2,drawing_plane_normal) < 0)

                        t1 = e.tangentAt(e.FirstParameter)
                        t2 = e.tangentAt(e.LastParameter)
                        flag_sweep = (DraftVecUtils.angle(t1,t2,drawing_plane_normal) >= 0)

                        if flag_large_arc: 
                            flag_sweep = not flag_sweep
                        for v in endpoints:
                            edata += 'A %s %s %s %s %s %s %s ' % \
                                    (str(rx),str(ry),str(rot),\
                                    str(int(flag_large_arc)),\
                                    str(int(flag_sweep)),str(v.x),str(v.y))
                    else:
                        edata += getDiscretized(e)
3939yoshi
Posts: 19
Joined: Thu Mar 02, 2017 5:24 am

Re: Draftからsvg変換の線幅が0.35固定となっている。

Post by 3939yoshi »

SVGの角度寸法線のテキストで向きと位置が正しくない問題の修正です。
Draft.py のgetSVG内です。

Code: Select all

                # drawing text
                if obj.ViewObject.DisplayMode == "2D":
                    t = prx.circle.tangentAt(prx.circle.FirstParameter+(prx.circle.LastParameter-prx.circle.FirstParameter)/2.0)
                    t = getProj(t)
                    tangle = DraftVecUtils.angle(t)
                    if (tangle <= -math.pi/2) or (tangle > math.pi/2):
                        tangle = tangle + math.pi
                    tbase = getProj(prx.circle.valueAt(prx.circle.FirstParameter+(prx.circle.LastParameter-prx.circle.FirstParameter)/2.0))
                    tbase = tbase.add(DraftVecUtils.rotate(Vector(0,2.0/scale,0),tangle))
                    #print(tbase)
                else:
                    tangle = 0
                    tbase = getProj(prx.tbase)
                svg += getText(stroke,fontsize,obj.ViewObject.FontName,tangle,tbase,prx.string)

Code: Select all

                # drawing text
                if obj.ViewObject.DisplayMode == "2D":
                    t = prx.circle.tangentAt(prx.circle.FirstParameter+(prx.circle.LastParameter-prx.circle.FirstParameter)/2.0)
                    t = getProj(t)
                    tangle = DraftVecUtils.angle(Vector(-1,0,0),t)
                    #if (tangle <= -math.pi/2) or (tangle > math.pi/2):
                    #    tangle = tangle + math.pi
                    tbase = getProj(prx.circle.valueAt(prx.circle.FirstParameter+(prx.circle.LastParameter-prx.circle.FirstParameter)/2.0))
                    tbase = tbase.add(DraftVecUtils.rotate(Vector(0,2.0/scale,0),tangle))
                    #print(tbase)
                else:
                    tangle = 0
                    tbase = getProj(prx.tbase)
                svg += getText(stroke,fontsize,obj.ViewObject.FontName,tangle,tbase,prx.string)
Post Reply