-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathobject.asy
122 lines (117 loc) · 3.56 KB
/
object.asy
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
struct Object {
// members
private path _path;
private guide _guide;
private Label _label;
private pen _drawpen;
private pen _fillpen;
private Object[] _children;
// constructors
void operator init() {
this._path = nullpath;
this._guide = nullpath;
this._label = new Label;
this._drawpen = defaultpen;
this._fillpen = nullpen;
this._children = new Object[];
}
void operator init(explicit path g, pen dp = defaultpen, pen fp = nullpen,
Object[] children = new Object[]) {
this._path = g;
this._guide = nullpath;
this._label = new Label;
this._drawpen = dp;
this._fillpen = fp;
this._children = children;
}
void operator init(explicit guide g, pen dp = defaultpen, pen fp = nullpen,
Object[] children = new Object[]) {
this._path = nullpath;
this._guide = g;
this._label = new Label;
this._drawpen = dp;
this._fillpen = fp;
this._children = children;
}
// predicates
bool empty() { return (_path == nullpath) && (_guide == nullpath); }
bool isPath() { return (_path != nullpath) && (_guide == nullpath); }
bool isGuide() { return (_path == nullpath) && (_guide != nullpath); }
bool hasChildren() { return this._children.length != 0; }
// getters & setters
path getPath() { return _path; }
void setPath(explicit path g) { _path = g; _guide = nullpath; }
guide getGuide() { return _guide; }
void setGuide(explicit guide g) { _guide = g; _path = nullpath; }
Label getLabel() { return _label; }
void setLabel(Label label) { _label = label; }
pen getDrawpen() { return _drawpen; }
void setDrawpen(pen p) { _drawpen = p; }
pen getFillpen() { return _fillpen; }
void setFillpen(pen p) { _fillpen = p; }
Object[] getChildren() { return _children; }
void setChildren(explicit Object child) {
_children.delete();
_children.push(child);
}
void setChildren(explicit Object[] children) { _children = children; }
// modifier
void addChild(Object child) { this._children.push(child); }
void removeChildren() { this._children.delete(); }
// traversal
// postorder == true -> postorder
// postorder == false -> preorder (default)
typedef void visitorfn(Object obj);
void traverse(visitorfn fn, bool postorder = false) {
if (!postorder) {
fn(this);
}
for (Object child : _children)
child.traverse(fn);
if (postorder) {
fn(this);
}
}
// helper struct for drawing
private struct Painter {
picture pic;
void paint(Object obj) {
label(pic, obj.getLabel(), obj.getDrawpen());
if (obj.empty())
return;
if (isPath())
filldraw(pic, obj.getPath(), obj.getFillpen(), obj.getDrawpen());
if (isGuide())
filldraw(pic, obj.getGuide(), obj.getFillpen(), obj.getDrawpen());
}
}
void draw(picture pic = currentpicture) {
Painter painter;
painter.pic = pic;
visitorfn fn = painter.paint;
traverse(fn);
}
}
// cast
path operator ecast(Object obj) {
assert(obj.isPath(), 'Not a path');
return obj.getPath();
}
guide operator ecast(Object obj) {
assert(obj.isGuide(), 'Not a guide');
return obj.getGuide();
}
// transform
Object operator *(transform trans, Object obj) {
Object[] cs = obj.getChildren();
Object[] children = new Object[cs.length];
for (int k = 0; k < cs.length; ++k)
children[k] = trans * cs[k];
Object ret = new Object;
ret.setPath(trans*obj.getPath());
ret.setLabel(trans*obj.getLabel());
ret.setDrawpen(obj.getDrawpen());
ret.setFillpen(obj.getFillpen());
ret.setChildren(children);
return ret;
}