forked from jarnoharno/freestylesvg
-
Notifications
You must be signed in to change notification settings - Fork 6
/
svg_invisible.py
131 lines (105 loc) · 3.88 KB
/
svg_invisible.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# License : MIT
# Author : Jarno Leppänen, Francesco Fantoni
# Date : 2014-03-26
import os
import re
import bpy
from freestyle import *
from freestyle.functions import *
from freestyle.predicates import *
from freestyle.types import *
from freestyle.shaders import *
from parameter_editor import *
from freestyle.chainingiterators import *
try:
import xml.etree.cElementTree as et
except ImportError:
import xml.etree.ElementTree as et
# change this values to change hidden lines style, default is black lines with 1px thickness
color = "black"
width = 1
_HEADER = """\
<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n
"""
_ROOT = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="%d" height="%d"></svg>\n'
SVG_NS = "http://www.w3.org/2000/svg"
et.register_namespace("", SVG_NS)
et.register_namespace("sodipodi", "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd")
et.register_namespace("inkscape", "http://www.inkscape.org/namespaces/inkscape")
scene = getCurrentScene()
current_frame = scene.frame_current
w = scene.render.resolution_x * scene.render.resolution_percentage / 100
h = scene.render.resolution_y * scene.render.resolution_percentage / 100
path = re.sub(r'\.blend$|$', '.svg' , bpy.data.filepath)
# write header if it does not yet exists
try:
with open(path) as f:
pass
except IOError:
f = open(path, "w")
f.write(_HEADER)
f.write(_ROOT % (w,h))
f.close()
# select
upred = AndUP1D(NotUP1D(QuantitativeInvisibilityUP1D(0)),
OrUP1D(pyNatureUP1D(Nature.SILHOUETTE),
pyNatureUP1D(Nature.CREASE),
ContourUP1D()))
Operators.select(upred)
# chain
Operators.bidirectional_chain(ChainSilhouetteIterator())
# sort
Operators.sort(pyZBP1D())
# shade and write svg
tree = et.parse(path)
root = tree.getroot()
class SVGPathShader(StrokeShader):
def shade(self, stroke):
xml_string = '<path fill="none" stroke="%s" stroke-width="%d" stroke-dasharray="2,2" d="\nM '
for v in stroke:
x, y = v.point
xml_string += '%.3f,%.3f ' % (x, h - y)
xml_string += '" />'
xml_string = xml_string % (color, width)
invisible_element = et.XML(xml_string)
group_invisible.append(invisible_element)
shaders_list = [
SamplingShader(50),
SVGPathShader(),
ConstantColorShader(1, 0, 0),
ConstantThicknessShader(10)
]
# layer for the frame
if tree.find(".//{http://www.w3.org/2000/svg}g[@id='frame_%06d']" % current_frame) is None:
layer_frame = et.XML('<g id="frame_%06d"></g>' % current_frame)
layer_frame.set('{http://www.inkscape.org/namespaces/inkscape}groupmode', 'layer')
layer_frame.set('{http://www.inkscape.org/namespaces/inkscape}label', 'frame_%06d' % current_frame)
root.append(layer_frame)
else:
layer_frame = tree.find(".//{http://www.w3.org/2000/svg}g[@id='frame_%06d']" % current_frame)
# layer for invisible lines
layer_invisible = et.XML('<g id="layer_invisible"></g>')
layer_invisible.set('{http://www.inkscape.org/namespaces/inkscape}groupmode', 'layer')
layer_invisible.set('{http://www.inkscape.org/namespaces/inkscape}label', 'invisible')
layer_frame.append(layer_invisible)
group_invisible = et.XML('<g id="invisible"></g>' )
layer_invisible.append(group_invisible)
Operators.create(TrueUP1D(), shaders_list)
# prettifies
def indent(elem, level=0):
i = "\n" + level*" "
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = i + " "
if not elem.tail or not elem.tail.strip():
elem.tail = i
for elem in elem:
indent(elem, level+1)
if not elem.tail or not elem.tail.strip():
elem.tail = i
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i
indent(root)
# write SVG to file
tree.write(path, encoding='UTF-8', xml_declaration=True)