diff --git a/src/com/t_oster/liblasercut/utils/VectorOptimizer.java b/src/com/t_oster/liblasercut/utils/VectorOptimizer.java new file mode 100644 index 0000000000000000000000000000000000000000..db5f6abd0b665b3b8942fd43115ff518a6064ada --- /dev/null +++ b/src/com/t_oster/liblasercut/utils/VectorOptimizer.java @@ -0,0 +1,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; + } + +}