Newer
Older
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package com.t_oster.liblasercut.utils;
import com.t_oster.liblasercut.LaserProperty;
import com.t_oster.liblasercut.VectorCommand;
import com.t_oster.liblasercut.VectorPart;
import com.t_oster.liblasercut.platform.Point;
import java.util.LinkedList;
import java.util.List;
/**
*
* @author Thomas Oster <thomas.oster@rwth-aachen.de>
*/
public class VectorOptimizer
{
public enum OrderStrategy
{
FILE,
//INNER_FIRST,
NEAREST
}
class Element
{
LaserProperty prop;
Point start;
List<Point> moves = new LinkedList<Point>();
Point getEnd()
{
return moves.isEmpty() ? start : moves.get(moves.size()-1);
}
}
private OrderStrategy strategy = OrderStrategy.FILE;
public VectorOptimizer(OrderStrategy s)
{
this.strategy = s;
}
private List<Element> divide(VectorPart vp)
{
List<Element> result = new LinkedList<Element>();
Element cur = null;
Point lastMove = null;
LaserProperty lastProp = null;
boolean stop = false;
for (VectorCommand cmd : vp.getCommandList())
{
switch (cmd.getType())
{
case MOVETO:
{
lastMove = new Point(cmd.getX(), cmd.getY());
stop = true;
break;
}
case LINETO:
{
if (stop)
{
stop = false;
if (cur != null)
{
result.add(cur);
}
cur = new Element();
cur.start = lastMove;
cur.prop = lastProp;
}
cur.moves.add(new Point(cmd.getX(), cmd.getY()));
break;
}
case SETPROPERTY:
{
lastProp = cmd.getProperty();
stop = true;
break;
}
}
}
if (cur != null)
{
result.add(cur);
}
return result;
}
private double dist(Point a, Point b)
{
return Math.sqrt((a.y-b.y)*(a.y-b.y)+(a.x-b.x)*(a.x-b.x));
}
private List<Element> sort(List<Element> e)
{
List<Element> result = new LinkedList<Element>();
switch (strategy)
{
case FILE:
{
result.addAll(e);
break;
}
case NEAREST:
{
result.add(e.remove(0));
while (!e.isEmpty())
{
Point end = result.get(result.size()-1).getEnd();
//find next
int next = 0;
double dst = -1;
for (int i = 1; i < e.size(); i++)
{
double nd = dist(e.get(i).getEnd(), end);
if (nd < dst || dst == -1)
{
next = i;
dst = nd;
}
}
//add next
result.add(e.remove(next));
}
break;
}
}
return result;
}
public VectorPart optimize(VectorPart vp)
{
List<Element> opt = this.sort(this.divide(vp));
LaserProperty cp = opt.get(0).prop;
VectorPart result = new VectorPart(opt.get(0).prop);
for (Element e : opt)
{
if (!e.prop.equals(cp))
{
result.setProperty(e.prop);
cp = e.prop;
}
result.moveto(e.start.x, e.start.y);
for (Point p : e.moves)
{
result.lineto(p.x, p.y);
}
}
return result;
}
}