Completed
Push — master ( 83f463...bba739 )
by Niels
12s
created

SvgBuilder::changePen()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 1
1
<?php
2
3
namespace Nielsiano\DmplBuilder;
4
5
use Exception;
6
7
/**
8
 * Illustrate a plot program visually as an SVG line drawing.
9
 */
10
class SvgBuilder implements PlotBuilder
11
{
12
    /**
13
     * Current position.
14
     */
15
    protected $x = 0;
16
    protected $y = 0;
17
18
    /**
19
     * Extent of drawing
20
     */
21
    protected $maxX = 0;
22
    protected $maxY = 0;
23
24
    protected $instructions = [];
25
26
    protected $axesFlipped = false;
27
    protected $penIsDown = true;
28
    protected $tool = 'regular';
29
    protected $unit = 'mm';
30
    protected $scale = 0.1;
31
32
    /**
33
     * Adds a new plot of x and y to machine instructions.
34
     */
35
    public function plot(int $x, int $y): PlotBuilder
36
    {
37
38
        if ($this->axesFlipped) {
39
            list($x, $y) = [$y, $x];
40
        }
41
42
        $targetX = $this->x + $x;
43
        $targetY = $this->y + $y;
44
45
        $this->maxX = max($this->maxX, $targetX);
46
        $this->maxY = max($this->maxY, $targetY);
47
48
        if ($this->penIsDown) {
49
            $this->pushInstruction('line', [
50
                'x1'    => $this->x,
51
                'y1'    => $this->y,
52
                'x2'    => $targetX,
53
                'y2'    => $targetY,
54
                'class' => $this->tool
55
            ]);
56
        }
57
58
        $this->x = $targetX;
59
        $this->y = $targetY;
60
61
        return $this;
62
    }
63
64
    /**
65
     * Changes the pen of the plotter.
66
     */
67
    public function changePen(int $pen): PlotBuilder
68
    {
69
        // TODO: Implement changePen() method.
70
    }
71
72
    /**
73
     * Compiles a string in target format with machine instructions.
74
     */
75
    public function compile(): string
76
    {
77
        $instructions = implode("\n", $this->instructions);
78
79
        $width = ($this->maxX * $this->scale) . $this->unit;
80
        $height = ($this->maxY * $this->scale) . $this->unit;
81
82
        return <<<SVG
83
<svg xmlns="http://www.w3.org/2000/svg" width="{$width}" height="{$height}" viewBox="0 0 {$this->maxX} {$this->maxY}">
84
    <defs>
85
        <style>
86
            line.regular {
87
                stroke: rgb(0,0,255);
88
                stroke-width: 4;
89
            }
90
91
            line.flex {
92
                stroke: rgb(255,0,0);
93
                stroke-width: 4;
94
                stroke-dasharray: 20 4;
95
            }
96
        </style>
97
    </defs>
98
    {$instructions}
99
</svg>
100
SVG;
101
    }
102
103
    /**
104
     * Pushes a command to the instructions.
105
     */
106
    public function pushCommand(string $command): PlotBuilder
107
    {
108
        // TODO: Implement pushCommand() method.
109
    }
110
111
    /**
112
     * Lifts the pen up.
113
     */
114
    public function penUp(): PlotBuilder
115
    {
116
        $this->penIsDown = false;
117
118
        return $this;
119
    }
120
121
    /**
122
     * Pushes the pen down on paper.
123
     */
124
    public function penDown(): PlotBuilder
125
    {
126
        $this->penIsDown = true;
127
128
        return $this;
129
    }
130
131
    /**
132
     * Changes the plotter pen to use flexcut.
133
     */
134
    public function flexCut(): PlotBuilder
135
    {
136
        $this->tool = 'flex';
137
138
        return $this;
139
    }
140
141
    /**
142
     * Change to the regular plotter pen.
143
     */
144
    public function regularCut(): PlotBuilder
145
    {
146
        $this->tool = 'regular';
147
148
        return $this;
149
    }
150
151
    /**
152
     * Changes the pen pressure in gram.
153
     */
154
    public function pressure(int $gramPressure): PlotBuilder
155
    {
156
        // TODO: Simulate pressure with stroke width, perhaps?
157
    }
158
159
    /**
160
     * Specifies measuring unit.
161
     * 1 selects 0.001 inch
162
     * 5 selects 0.005 inch
163
     * M selects 0.1 mm
164
     */
165
    public function setMeasuringUnit($unit): PlotBuilder
166
    {
167
        switch ($unit) {
168
            case 'M':
169
                $this->unit = 'mm';
170
                $this->scale = 0.1;
171
                break;
172
            case 1:
173
                $this->unit = 'in';
174
                $this->scale = 0.001;
175
                break;
176
            case 5:
177
                $this->unit = 'in';
178
                $this->scale = 0.005;
179
                break;
180
            default:
181
                throw new Exception('Unhandled unit: ' . $unit);
182
        }
183
184
        return $this;
185
    }
186
187
    /**
188
     * Changes the plotter velocity.
189
     */
190
    public function velocity(int $velocity): PlotBuilder
191
    {
192
        // TODO: Implement velocity() method.
193
    }
194
195
    /**
196
     * Flips the x, y coordinates.
197
     */
198
    public function flipAxes(): PlotBuilder
199
    {
200
        $this->axesFlipped = true;
201
202
        return $this;
203
    }
204
205
    /**
206
     * Cuts off paper when a operation finishes.
207
     */
208
    public function cutOff(): PlotBuilder
209
    {
210
        // TODO: Implement cutOff() method.
211
    }
212
213
    protected function pushInstruction(string $name, array $parameters): PlotBuilder
214
    {
215
        $instruction = '<' . $name;
216
        foreach ($parameters as $parameter => $value) {
217
            $instruction .= ' ' . $parameter . '="' . htmlspecialchars($value) . '"';
218
        }
219
        $this->instructions[] = $instruction . ' />';
220
221
        return $this;
222
    }
223
224
}
225