From d98d54fa6e17afef15f495f6f1b7f0cbea67f64b Mon Sep 17 00:00:00 2001 From: Michael Carleton Date: Tue, 3 Jan 2023 22:31:23 +0000 Subject: [PATCH 1/9] mavenise include fastmatm some refactor --- .gitignore | 5 + TestMultiSheets1b.java | 200 --------- core.jar | Bin 296656 -> 0 bytes dalsoo.jar | Bin 18739 -> 0 bytes pom.xml | 37 ++ .../main/java/whitegreen/dalsoo}/Convex.java | 52 ++- .../main/java/whitegreen/dalsoo}/M.java | 380 +++++++++++------- .../main/java/whitegreen/dalsoo}/Pack.java | 198 +++++---- .../main/java/whitegreen/dalsoo}/Strip.java | 45 +-- .../whitegreen/dalsoo/TestMultiSheets1b.java | 234 +++++++++++ 10 files changed, 666 insertions(+), 485 deletions(-) delete mode 100644 TestMultiSheets1b.java delete mode 100644 core.jar delete mode 100644 dalsoo.jar create mode 100644 pom.xml rename {pack => src/main/java/whitegreen/dalsoo}/Convex.java (70%) rename {pack => src/main/java/whitegreen/dalsoo}/M.java (70%) rename {pack => src/main/java/whitegreen/dalsoo}/Pack.java (71%) rename {pack => src/main/java/whitegreen/dalsoo}/Strip.java (72%) create mode 100644 src/main/java/whitegreen/dalsoo/TestMultiSheets1b.java diff --git a/.gitignore b/.gitignore index a1c2a23..3d175d1 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,8 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* + +/target/ +.classpath +.project +/.settings/ \ No newline at end of file diff --git a/TestMultiSheets1b.java b/TestMultiSheets1b.java deleted file mode 100644 index 0470a0c..0000000 --- a/TestMultiSheets1b.java +++ /dev/null @@ -1,200 +0,0 @@ -package tests; - -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Random; -import pack.M; -import pack.Pack; -import pack.Strip; -import processing.core.PApplet; - -/** - * - * @author Hao Hua, Southeast University Nanjing, http://labaaa.org - * - * 2D bin packing places a given set of polygons in standard single/multiple rectangular sheet(s), to minimize the use of the sheet(s). - * This library does not involve other libraries, however, the example uses core.jar (https://processing.org) for a graphical interface. - * The algorithm is effective when the ratio (number of polygons / number of the types of polygons) is small. - * - * - * 1. Input - * a. Only simple polygon: no holes, no self-intersection. - * b. Data structure: point - double[]; polygon - double[][]; all polygons - double[][][]. - * One might use other library to convert other formats (e.g. dxf, obj) of polygon to double[][]. - * c. It's better to represent a polygon with a moderate number of points. - * Too many points (e.g. a local detail contains dozens of points) slows down the algorithm. Avoid using too many points for a smooth curve. - * One might use segment_max_length to create more points on a long edge of a polygon, if the polygon has very few points or the edge is very long. - * - * - * 2. Choose an algorithm - * a. useAbey=true, Jostle heuristics for the 2D-irregular shapes bin packing problems with free rotation, R. P. Abeysooriya 2018 - * rotSteps: Each polygon is rotated in the layout. Few steps (say 16) -> run fast & poor result; many steps (say 48) -> run slow & good results - * segment_max_length: if (an edge of a polygon > segment_max_length), breaks it into smaller segments. - * large value -> run fast & poor result; small value -> run slow & good results - * segment_max_length is related to translation steps. - * - * b. useAbey=false, Waste minimization in irregular stock cutting, D. Dalalah, 2014 - * the rotation/translation steps depend on the polygons. - * - * - * 3. Output - * - * - * - * - */ -public class TestMultiSheets1b extends PApplet { - private DecimalFormat df=new DecimalFormat("##.###"); - private Random ran; - - //input - private double[][][] randompolys; //the input polygons - private final float WID = 2400; //width of the standard rectangular sheet - private final float HEI = 1200; - private final double margin= 6.0; - private final double preferX=0.499; // 0.501 or 1 - - //parameters - private final double segment_max_length =250.0; //250,400,800, use to break long edges if necessary, relative to the scale of the polgyons - private final int rotSteps=36 ; //18,24,36,48, rotation steps - private ArrayList packs=new ArrayList(); - private boolean useAbey=false; - // true: rotation steps depend on polygons, R. P. Abeysooriya 2018 - // false: rotation steps are a prior, D. Dalalah, 2014 - - //output - private int[] result_pack_id; // result_pack_id[9]=2 means the 9th polygon is on the 2nd sheet. - private double[][] result_cos_sin; // result_cos_sin[9]={0.5, 0.866} means the 9th polygon is rotated 60 degree w.r.t its reference point - private double[][] result_position; // result_cos_sin[9] denotes the x,y-coordinate of the 9th polygon w.r.t its reference point - - public void setup() { - size(1300, 800); - int seed = 4346; - ran = new Random(seed); - randompolys = randomPolygons(210);// prepare the input polygons - - Double segment_len = useAbey ? null : segment_max_length; - Pack pack = new Pack(randompolys, margin, segment_len, rotSteps, WID, HEI, preferX); - pack.packOneSheet(useAbey); - packs.add(pack); - - for (int i = 0; i < 100; i++) { // packing one sheet after another, 100 is estimated - int size = packs.size(); - if (packs.get(size - 1).isEmpty()) { - println(size + " sheets"); - break; - } - pack = packs.get(size - 1).clone(); - pack.packOneSheet(useAbey); - packs.add(pack); - } - report(); - } - - private void report() { - result_pack_id = new int[randompolys.length]; - result_cos_sin = new double[randompolys.length][]; - result_position = new double[randompolys.length][]; - for (int i = 0; i < packs.size(); i++) { - Pack pack = packs.get(i); - for (Strip strip : pack.fixs) { - result_pack_id[strip.id] = i; - result_cos_sin[strip.id] = strip.trigo; - result_position[strip.id] = strip.position; - } - } - } - - private double[][][] randomPolygons(int num) { - double[][][] protos = new double[6][][]; - // protos[0] = new double[][] { { 0, 0 }, { 0, 2 }, { 6, 2 }, { 6, 12 }, { 8, 12 }, { 8, 0 } }; - protos[0] = new double[][] { { 0, 0 }, { 0, 10 }, { 10, 10 }, { 10, 0 } }; - protos[1] = new double[][] { { 0, 0 }, { 0, 16 }, { 1, 16 }, { 1, 0 } }; - protos[2] = new double[][] { { 0, 0 }, { 0, 12 }, { 9, 6 } }; - protos[3] = new double[][] { { 0, 0 }, { 0, 2 }, { 8, 2 }, { 8, 8 }, { 0, 8 }, { 0, 10 }, { 10, 10 }, { 10, 0 } }; - protos[4] = new double[][] { { 0, 0 }, { 0, 2 }, { 6, 2 }, { 6, 12 }, { 8, 12 }, { 8, 0 } }; - protos[5] = new double[][] { { 0, 0 }, { 0, 5 }, { 4, 1 }, { 8, 5 }, { 4, 10 }, { 0, 6 }, { 0, 11 }, { 9, 11 }, { 9, 0 } }; - - double[][][] polys = new double[num][][]; - for (int i = 0; i < num; i++) { - double[][] pl = protos[ran.nextInt(protos.length)]; - double sc = 8 + ran.nextDouble() * 12; // 8+ ran.nextDouble()*12 10+ ran.nextDouble()*20 - polys[i] = shake(3*sc, pl); // - } - for (int i = 0; i < num; i++) { - double[][] poly=polys[i] ; - double dx= ran.nextDouble() * 1000; - double dy= ran.nextDouble() * 1000; - for(double[] p: poly){ - M._add(p, new double[]{dx,dy}); - } - } - return polys; - } - - private double[][] shake(double s, double[][] ps) { - double[][] arr = new double[ps.length][]; - double sng = ran.nextBoolean() ? s : (-s); // mirror - double theta = ran.nextDouble() * 2 * PI; - double cos = Math.cos(theta); - double sin = Math.sin(theta); - for (int i = 0; i < ps.length; i++) { - double[] p = M.scale(sng, ps[i]); - p[0] += (ran.nextDouble() - 0.5) * 0.25 * s; - p[1] += (ran.nextDouble() - 0.5) * 0.25 * s; - double x = cos * p[0] + sin * p[1]; - double y = -sin * p[0] + cos * p[1]; - arr[i] = new double[] { x, y }; - } - return arr; - } - - public void draw() { - background(255); - smooth(); - translate(40, 10); - float sc = 0.15f; - - //display method 1 -// for (int i = 0; i < randompolys.length; i++) { -// int pack_id = result_pack_id[i]; -// pushMatrix(); -// translate((pack_id % 3) * 380, (pack_id / 3) * 200); -// -// noFill(); -// rect(0, 0, sc * WID, sc * HEI); -// fill(0, 255, 0); -// double[][] poly = randompolys[i]; -// poly = M.rotate(result_cos_sin[i], poly); -// poly = M.move(result_position[i], poly); -// draw(poly, sc); -// -// popMatrix(); -// } - //display method 2 - for (int i = 0; i < 5; i++) { - for (int j = 0; j < 3; j++) { - int id = i * 3 + j; - if (id >= packs.size()) - return; - Pack pack = packs.get(id); - pushMatrix(); - translate(j * 380, i * 200); // (j * 270, i * 150 - noFill(); - rect(0, 0, sc * WID, sc * HEI); - fill(0, 255, 0); - for (Strip strip : pack.fixs) - draw(strip.inps, sc); - popMatrix(); - } - } - } - - private void draw(double[][] ps, float sc) { - beginShape(); - for (double[] p : ps) - vertex((float) p[0] * sc, (float) p[1] * sc); - endShape(CLOSE); - } - -} diff --git a/core.jar b/core.jar deleted file mode 100644 index e1c38b6fcb1cc9d916f9ece1b4e060eff3eb2ddf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 296656 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
    u&-1_z5%COg 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%0A5Y$EZWwS5!Wz`u({wm6*B8IGeB%~&qmFS6y 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 J7KksP{{ei<+%W(E diff --git a/dalsoo.jar b/dalsoo.jar deleted file mode 100644 index 58c4538632251a99885d9ff918a25408cc26c0b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18739 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 + 4.0.0 + whitegreen + dalsoo + 0.0.1-SNAPSHOT + Dalsoo-Bin-Packing + + + + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + + + + jitpack.io + https://jitpack.io + + + + + com.github.micycle1 + processing3 + 3.5.4 + + + net.jafama + jafama + 2.3.2 + + + \ No newline at end of file diff --git a/pack/Convex.java b/src/main/java/whitegreen/dalsoo/Convex.java similarity index 70% rename from pack/Convex.java rename to src/main/java/whitegreen/dalsoo/Convex.java index 912f4a8..4018ab7 100644 --- a/pack/Convex.java +++ b/src/main/java/whitegreen/dalsoo/Convex.java @@ -1,29 +1,32 @@ -package pack; +package whitegreen.dalsoo; import java.util.ArrayList; //Hao Hua, Southeast University, whitegreen@163.com - public class Convex { public ArrayList convex; // convex is clockwise private static final double area_zero = 1E-6; // for mm - public Convex clone(){ - ArrayList list=new ArrayList(); + @Override + public Convex clone() { + ArrayList list = new ArrayList<>(); list.addAll(convex); - Convex con= new Convex(); - con.convex= list; + Convex con = new Convex(); + con.convex = list; return con; } - public Convex(){ + + public Convex() { } + public Convex(double[][] points) { // always ready for new points double[][] tri = { points[0], points[1], points[2] }; double area = M.area(tri); - if (Math.abs(area) < area_zero) + if (Math.abs(area) < area_zero) { throw new RuntimeException(); - convex = new ArrayList(); + } + convex = new ArrayList<>(); if (area > 0) { convex.add(points[0]); convex.add(points[1]); @@ -33,27 +36,31 @@ public Convex(double[][] points) { // always ready for new points convex.add(points[0]); convex.add(points[2]); } - for (int i = 3; i < points.length; i++) + for (int i = 3; i < points.length; i++) { increment_hull(points[i]); + } } public void increment_hull(double[] np) { // convex is clockwise - if (M.inside(np, convex)) + if (M.inside(np, convex)) { return; + } int size = convex.size(); boolean[] visible = new boolean[size]; - boolean hasTure=false; + boolean hasTure = false; for (int i = 0; i < size; i++) { double[] q0 = convex.get(i); double[] q1 = convex.get((i + 1) % size); double[] d = M.sub(q1, q0); double[] a = M.sub(np, q0); visible[i] = -d[1] * a[0] + d[0] * a[1] > 0; // n={-d[1], d[0]} on the left - if(visible[i]) - hasTure=true; + if (visible[i]) { + hasTure = true; + } + } + if (!hasTure) { + return; } - if(!hasTure) - return; int T1st = -1; for (int i = 0; i < size; i++) { // find 1st visible @@ -65,19 +72,22 @@ public void increment_hull(double[] np) { // convex is clockwise } if (0 > T1st) { System.out.println(np[0] + "*" + np[1]); - for (double[] p : convex) - System.out.println( "new double[]{"+p[0] + "," + p[1]+"}"); - for (boolean b:visible) + for (double[] p : convex) { + System.out.println("new double[]{" + p[0] + "," + p[1] + "}"); + } + for (boolean b : visible) { System.out.println(b); + } throw new RuntimeException(); } - ArrayList list = new ArrayList(size); + ArrayList list = new ArrayList<>(size); list.add(convex.get(T1st)); list.add(np); for (int i = 0; i < size; i++) { int j = (T1st + i + 1) % size; - if (!visible[j]) + if (!visible[j]) { list.add(convex.get(j)); + } } convex = list; } diff --git a/pack/M.java b/src/main/java/whitegreen/dalsoo/M.java similarity index 70% rename from pack/M.java rename to src/main/java/whitegreen/dalsoo/M.java index f06be49..318ef7d 100644 --- a/pack/M.java +++ b/src/main/java/whitegreen/dalsoo/M.java @@ -1,36 +1,42 @@ -package pack; +package whitegreen.dalsoo; import java.util.ArrayList; +import net.jafama.FastMath; + //Hao Hua, Southeast University, whitegreen@163.com +public final class M { + + private static final double denominator_lim = 1e-32; -public class M { - - private static final double denominator_lim=0.00000001; - - //math ************************************************************************************* + // math + // ************************************************************************************* public static int powerInt(int a) { int v = 1; - for (int i =2; i <= a; i++) + for (int i = 2; i <= a; i++) { v *= i; + } return v; } - - //vector ********************************************************************** + + // vector ********************************************************************** public static void assign(double[] a, double[] b) { - for (int i = 0; i < a.length; i++) + for (int i = 0; i < a.length; i++) { a[i] = b[i]; + } } - - public static double[] mean(double[][] ps){ - double[] re=new double[ps[0].length]; - for(int i=0;i vs) { int d = vs.get(0).length; double[] p = new double[d]; for (double[] v : vs) { - for (int j = 0; j < d; j++) + for (int j = 0; j < d; j++) { p[j] += v[j]; + } } return p; } public static double[] add(double sa, double[] a, double sb, double[] b) { double[] p = new double[a.length]; - for (int i = 0; i < p.length; i++) - p[i] = sa*a[i] + sb*b[i]; + for (int i = 0; i < p.length; i++) { + p[i] = sa * a[i] + sb * b[i]; + } return p; } public static void _add(double[] a, double[] b) { - for (int i = 0; i < a.length; i++) + for (int i = 0; i < a.length; i++) { a[i] += b[i]; + } } public static double[] scale(double s, double[] a) { double[] p = new double[a.length]; - for (int i = 0; i < p.length; i++) + for (int i = 0; i < p.length; i++) { p[i] = a[i] * s; + } return p; } - public static void _scale(double s, double[] a) { - for (int i = 0; i < a.length; i++) + for (int i = 0; i < a.length; i++) { a[i] *= s; + } } public static double[] scaleTo(double scale, double[] a) { - double sc =scale/ mag(a); + double sc = scale / mag(a); double[] p = new double[a.length]; - for (int i = 0; i < p.length; i++) + for (int i = 0; i < p.length; i++) { p[i] = a[i] * sc; + } return p; } + public static void _scaleTo(double scale, double[] a) { - double sc =scale/ mag(a); - for (int i = 0; i < a.length; i++) + double sc = scale / mag(a); + for (int i = 0; i < a.length; i++) { a[i] *= sc; + } } public static double[] normalize(double[] v) { double mag = mag(v); double[] p = new double[v.length]; - for (int i = 0; i < p.length; i++) + for (int i = 0; i < p.length; i++) { p[i] = v[i] / mag; + } return p; } + public static void _normalize(double[] v) { double mag = mag(v); - for (int i = 0; i < v.length; i++) + for (int i = 0; i < v.length; i++) { v[i] /= mag; + } } public static double[] between(double s, double[] a, double[] b) { double[] p = new double[a.length]; - for (int i = 0; i < p.length; i++) + for (int i = 0; i < p.length; i++) { p[i] = (1 - s) * a[i] + s * b[i]; + } return p; } + public static double dot(double[] a, double[] b) { - double sum=0; - for (int i = 0; i b[1] ) - return false; - if( a[3]b[3]) + + // computational geometry + // ************************************************************************ + public static boolean intersect_boundBox(double[][] poly1, double[][] poly2) { + double[] a = boundBox(poly1); + double[] b = boundBox(poly2); + if (a[1] < b[0] || a[0] > b[1] || a[3] < b[2] || a[2] > b[3]) { return false; + } return true; } @@ -349,20 +406,25 @@ public static double[] boundBox(double[][] poly) { // orthogonal, minx, max, min double maxx = v[0]; double miny = v[1]; double maxy = v[1]; - for(double[] p: poly){ - if(minx>p[0]) - minx=p[0]; - if(maxxp[1]) - miny=p[1]; - if(maxy p[0]) { + minx = p[0]; + } + if (maxx < p[0]) { + maxx = p[0]; + } + + if (miny > p[1]) { + miny = p[1]; + } + if (maxy < p[1]) { + maxy = p[1]; + } + } + return new double[] { minx, maxx, miny, maxy }; + } + + public static double[][] offset(final double distance, final double[][] poly) { double[][] ps = new double[poly.length][]; for (int i = 0; i < poly.length; i++) { @@ -371,34 +433,36 @@ public static double[][] offset(double dis, double[][] poly) { double[] vb = sub(p, poly[(i - 1 + poly.length) % poly.length]); double[] na = { -va[1], va[0] }; double[] nb = { -vb[1], vb[0] }; - double[] pa = add(p, scaleTo(dis, na)); - double[] pb = add(p, scaleTo(dis, nb)); + double[] pa = distance == 0 ? p : add(p, scaleTo(distance, na)); + double[] pb = distance == 0 ? p : add(p, scaleTo(distance, nb)); ps[i] = lineIntersect(pa, va, pb, vb); } return ps; } - + public static double[] point_Project_Plane(double[] q, double[] p, double[] n) { // q is the point double d = -dot(p, n); double[] tmp = scale(dot(q, n) + d, n); return sub(q, tmp); } - + public static double[] vector_Project_Plane(double[] v, double[] p, double[] n) { // v is the vector - double[] tmp = scale(dot(v, n) , n); + double[] tmp = scale(dot(v, n), n); return sub(v, tmp); } - - public static double[][] circleLine_intersection (double[] cnt, double r, double[] p , double[] d){ //two intersections or nothing + + public static double[][] circleLine_intersection(double[] cnt, double r, double[] p, double[] d) { // two intersections or + // nothing // d must be normalized System.out.println(mag_sq(d)); double[] m = sub(p, cnt); double b = 2 * dot(m, d); double c = mag_sq(m) - r * r; double b4c = b * b - 4 * c; - if (b4c < 0) + if (b4c < 0) { return null; - double delta = Math.sqrt(b4c); + } + double delta = FastMath.sqrt(b4c); double s1 = 0.5 * (-b + delta); double s2 = 0.5 * (-b - delta); double[][] re = { add(p, scale(s1, d)), add(p, scale(s2, d)) }; @@ -410,8 +474,8 @@ public static double[] planes_Intersect(double[] r1, double[] n1, double[] r2, d double h2 = dot(n2, r2); double dn12 = dot(n1, n2); double fem = 1 - dn12 * dn12; - if (Math.abs(fem) < denominator_lim){ - //return M.between(0.5, r1, r2); + if (FastMath.abs(fem) < denominator_lim) { + // return M.between(0.5, r1, r2); throw new RuntimeException(); } double c1 = (h1 - h2 * dn12) / fem; @@ -421,22 +485,26 @@ public static double[] planes_Intersect(double[] r1, double[] n1, double[] r2, d // _normalize(direction); } - public static double[] planeLine_Intersect(double[] n, double[] point, double[] p, double[] dir) { //n={a b c} + public static double[] planeLine_Intersect(double[] n, double[] point, double[] p, double[] dir) { // n={a b c} return planeLine_Intersect(n, -dot(n, point), p, dir); } - public static double[] planeLine_Intersect(double[] n, double d, double[] p, double[] dir) { //n={a b c} n&d: plane, p&dir: line + public static double[] planeLine_Intersect(double[] n, double d, double[] p, double[] dir) { // n={a b c} n&d: plane, p&dir: + // line double fz = (dot(n, p)) + d; double fm = dot(n, dir); - if (Math.abs(fm) < denominator_lim) + if (FastMath.abs(fm) < denominator_lim) { return null; - double t = -fz / fm; + } + double t = -fz / fm; return add(p, scale(t, dir)); } - public static double[] lineIntersect3D(double[] p0, double[] d0, double[] p1, double[] d1) { //project p1d1 to p0d0, d0, d1 normalized - if (Math.abs( dot(d0,d1)) < denominator_lim)// parallel + public static double[] lineIntersect3D(double[] p0, double[] d0, double[] p1, double[] d1) { // project p1d1 to p0d0, d0, d1 + // normalized + if (FastMath.abs(dot(d0, d1)) < denominator_lim) { // parallel return null; + } double[] dx = d0; // mag=1 double[] dz = cross(d0, d1); double[] dy = cross(dx, dz); @@ -451,11 +519,11 @@ public static double[] lineIntersect3D(double[] p0, double[] d0, double[] p1, do return add(p0, scale(xx, dx)); } - public static double[] lineIntersect(double[] p0, double[] n0, double[] p1, double[] n1) { // in 2d double cross_base = kross(n0, n1); - if (Math.abs(cross_base) < denominator_lim)// parallel + if (FastMath.abs(cross_base) < denominator_lim) { // parallel return null; + } double[] d = sub(p1, p0); double s = kross(d, n1) / cross_base; return new double[] { p0[0] + s * n0[0], p0[1] + s * n0[1] }; @@ -483,23 +551,23 @@ public static double areaAbs(ArrayList ps) { // signed double[] pb = ps.get((i + 1) % size); sum += pa[1] * pb[0] - pa[0] * pb[1]; } - return Math.abs(0.5f * sum); + return FastMath.abs(0.5f * sum); } public static double areaAbs(double[][] ps) { - return Math.abs(area(ps)); + return FastMath.abs(area(ps)); } public static double[][] getRotateMatrix(double[] xyz) { // double rx, double ry, double rz double a = -xyz[2]; // rz double b = -xyz[1]; double c = -xyz[0]; - double ca = Math.cos(a); - double sa = Math.sin(a); - double cb = Math.cos(b); - double sb = Math.sin(b); - double cc = Math.cos(c); - double sc = Math.sin(c); + double ca = FastMath.cos(a); + double sa = FastMath.sin(a); + double cb = FastMath.cos(b); + double sb = FastMath.sin(b); + double cc = FastMath.cos(c); + double sc = FastMath.sin(c); double[][] tt = new double[3][]; tt[0] = new double[] { ca * cb, sa * cc + ca * sb * sc, sa * sc - ca * sb * cc }; tt[1] = new double[] { -sa * cb, ca * cc - sa * sb * sc, ca * sc + sa * sb * cc }; @@ -508,40 +576,39 @@ public static double[][] getRotateMatrix(double[] xyz) { // double rx, double ry } public static double[] rotateX(double theta, double[] p) { - double c = Math.cos(theta); - double s = Math.sin(theta); + double c = FastMath.cos(theta); + double s = FastMath.sin(theta); double[][] m = { { 1, 0, 0 }, { 0, c, -s }, { 0, s, c } }; return mul(m, p); } public static double[] rotateY(double theta, double[] p) { - double c = Math.cos(theta); - double s = Math.sin(theta); + double c = FastMath.cos(theta); + double s = FastMath.sin(theta); double[][] m = { { c, 0, s }, { 0, 1, 0 }, { -s, 0, c } }; return mul(m, p); } public static double[] rotateZ(double theta, double[] p) { - double c = Math.cos(theta); - double s = Math.sin(theta); + double c = FastMath.cos(theta); + double s = FastMath.sin(theta); double[][] m = { { c, -s, 0 }, { s, c, 0 }, { 0, 0, 1 } }; return mul(m, p); } - + public static double[] rotate_Rodriguez(double[] v, double theta, double[] dir) { - double cos = Math.cos(theta); - double sin = Math.sin(theta); + double cos = FastMath.cos(theta); + double sin = FastMath.sin(theta); double[] v1 = M.scale(cos, v); double[] v2 = M.scale((1 - cos) * dot(v, dir), dir); double[] v3 = M.scale(sin, cross(dir, v)); return M.add(v1, M.add(v2, v3)); } - // double[][] offset(double s, double[][] ps) { // double[][] nps = new double[ps.length][]; // double[] cnt = center(ps); -// for (int i = 0; i < ps.length; i++) +// for (int i = 0; i < ps.length; i++) // nps[i] = between(s, ps[i], cnt); // return nps; // } @@ -550,7 +617,8 @@ public static boolean inside(double[] p, double[][] vs) { int i, j = vs.length - 1; boolean oddNodes = false; for (i = 0; i < vs.length; i++) { - if ((vs[i][1] < p[1] && vs[j][1] >= p[1] || vs[j][1] < p[1] && vs[i][1] >= p[1]) && (vs[i][0] <= p[0] || vs[j][0] <= p[0])) { + if ((vs[i][1] < p[1] && vs[j][1] >= p[1] || vs[j][1] < p[1] && vs[i][1] >= p[1]) + && (vs[i][0] <= p[0] || vs[j][0] <= p[0])) { if (vs[i][0] + (p[1] - vs[i][1]) / (vs[j][1] - vs[i][1]) * (vs[j][0] - vs[i][0]) < p[0]) { oddNodes = !oddNodes; } @@ -559,7 +627,7 @@ public static boolean inside(double[] p, double[][] vs) { } return oddNodes; } - + public static boolean inside(double[] p, ArrayList vs) { int size = vs.size(); int i, j = size - 1; @@ -576,7 +644,7 @@ public static boolean inside(double[] p, ArrayList vs) { } return oddNodes; } - + public static boolean intersection(double[] a, double[] b, double[] c, double[] d) { double[][] abd = { a, b, d }; double[][] abc = { a, b, c }; @@ -584,35 +652,37 @@ public static boolean intersection(double[] a, double[] b, double[] c, double[] double[][] cdb = { c, d, b }; return area(abd) * area(abc) < 0 && area(cda) * area(cdb) < 0; } - + // public static double[] lineIntersect(double[] p0, double[] n0, double[] p1, double[] n1){ //in 2d // double cross_base= cross(n0, n1); -// if(Math.abs(cross_base)<0.000001)//parallel +// if(FastMath.abs(cross_base)<0.000001)//parallel // return null; // double[] d= sub(p1,p0); // double s= cross(d, n1)/cross_base; // return new double[]{p0[0]+s*n0[0], p0[1]+s*n0[1]}; //TRICK 3D // } - - //special ************************************************************************************* - + + // special + // ************************************************************************************* + public static double[][] exp(double[][] m, int iteration) { double[][] re = I(m.length); for (int i = 0; i < iteration; i++) { - double[][] tmp = M.scale(mul(m, i+1), 1.0/powerInt(i+1)); + double[][] tmp = M.scale(mul(m, i + 1), 1.0 / powerInt(i + 1)); re = M.add(re, tmp); } return re; } - + public static double[][] ln(double[][] rotate_matrix) {// group to algebra double tr = 0; - for (int i = 0; i < rotate_matrix.length; i++) + for (int i = 0; i < rotate_matrix.length; i++) { tr += rotate_matrix[i][i]; - double theta = Math.acos(0.5 * (tr - 1)); + } + double theta = FastMath.acos(0.5 * (tr - 1)); double[][] t = M.sub(rotate_matrix, M.transpose(rotate_matrix)); - double[][] re= M.scale(t, 0.5 * theta / Math.sin(theta)); // sin(0)************* - return re; + double[][] re = M.scale(t, 0.5 * theta / FastMath.sin(theta)); // sin(0)************* + return re; } public static double[] algebra_ele(double[][] mat) { @@ -627,11 +697,11 @@ public static double[][] algebra_matrix(double[] ele) { public static double[][] exp(double[] ele) { // algebra to group double sq_theta = M.mag_sq(ele); - double theta = Math.sqrt(sq_theta); + double theta = FastMath.sqrt(sq_theta); double[][] ele_mat = algebra_matrix(ele); double[][] re = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }; - re = M.add(re, M.scale(ele_mat, Math.sin(theta) / theta)); - return M.add(re, M.scale(M.mul(ele_mat, ele_mat), (1 - Math.cos(theta)) / sq_theta)); + re = M.add(re, M.scale(ele_mat, FastMath.sin(theta) / theta)); + return M.add(re, M.scale(M.mul(ele_mat, ele_mat), (1 - FastMath.cos(theta)) / sq_theta)); } } diff --git a/pack/Pack.java b/src/main/java/whitegreen/dalsoo/Pack.java similarity index 71% rename from pack/Pack.java rename to src/main/java/whitegreen/dalsoo/Pack.java index f53c849..61c74d7 100644 --- a/pack/Pack.java +++ b/src/main/java/whitegreen/dalsoo/Pack.java @@ -1,89 +1,104 @@ -package pack; +package whitegreen.dalsoo; + +import static java.lang.Math.PI; //Hao Hua, Southeast University, whitegreen@163.com import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; -import java.util.Comparator; -public class Pack { - public ArrayList fixs = new ArrayList(); - public ArrayList movs = new ArrayList(); +import net.jafama.FastMath; + +public final class Pack { + + public ArrayList fixs = new ArrayList<>(); + public ArrayList movs = new ArrayList<>(); public Convex cntConvex; + /** + * Sin and cos values for each rotation step. + */ private final double[][] trigos; private final int rotSteps; - private static final double PI = Math.PI; - private final double WID, HEI; + private final double width, height; private static final double areasc = 1E-6; // private final double preferX; // 0.501 or 1 - public Pack clone() { - Pack np = new Pack(trigos, rotSteps, WID, HEI, preferX); - np.movs = movs; - np.cntConvex = cntConvex; - return np; - } - - public Pack(double[][] trigos, int rotSteps, double WID, double HEI, double preferX) { + Pack(double[][] trigos, int rotSteps, double width, double height, double preferX) { this.trigos = trigos; this.rotSteps = rotSteps; - this.WID = WID; - this.HEI = HEI; + this.width = width; + this.height = height; this.preferX = preferX; - - float[][] arr = { { 1, 2 }, { 2, 0 }, { 3, -2 } }; - Arrays.sort(arr, new Comparator() { - public int compare(float[] a, float[] b) { - if (a[0] < b[0]) - return -1; - else if (a[0] > b[0]) - return 1; - else - return 0; - } - }); -// for(float[] v: arr){ -// System.out.println(v[0]); -// } - } - - public boolean isEmpty() { - return movs.isEmpty(); } - public Pack(double[][][] polys, double offset, Double segment_max_length, int rotSteps, double WID, double HEI, double preferX) { + /** + * + * @param polys array of polygons [p1, p2]; for each polygon, its + * vertices are expressed in [x, y] coordinate pairs: + * [[p1x, p1y], [p2x, p2y]...] + * @param spacing boundary spacing between packed objects + * @param segment_max_length + * @param rotSteps + * @param width width of each bin + * @param height height of each bin + * @param preferX + */ + public Pack(double[][][] polys, double spacing, Double segment_max_length, int rotSteps, double width, double height, + double preferX) { + if (0 > preferX || 1 < preferX) { + throw new IllegalArgumentException("skew must be between 0 and 1 (inclusive)"); + } for (int i = 0; i < polys.length; i++) { double[][] poly = polys[i]; - Strip strip = new Strip(i, poly, offset, segment_max_length); + Strip strip = new Strip(i, poly, spacing, segment_max_length); movs.add(strip); } - Collections.sort(movs); // ascend, remove form the end (largest) - if (0 > preferX || 1 < preferX) - throw new RuntimeException(); + Collections.sort(movs); // sort by area, smallest first this.preferX = preferX; this.rotSteps = rotSteps; trigos = new double[rotSteps][]; for (int i = 0; i < rotSteps; i++) { double theta = i * 2 * PI / rotSteps; - trigos[i] = new double[] { Math.cos(theta), Math.sin(theta) }; + trigos[i] = new double[] { FastMath.cos(theta), FastMath.sin(theta) }; + } + this.width = width; + this.height = height; + } + + public void packOneSheet(boolean abey) { + place1stStrip(); + int size = movs.size(); + for (int i = 0; i < size; i++) { + // place next largest polygon + if (abey) { + placeAnotherStrip_Abey(size - 1 - i); + } else { + placeAnotherStrip_Dalalah(size - 1 - i); + } + } + ArrayList list = new ArrayList<>(); + for (Strip stp : movs) { + if (null == stp) { + continue; + } + list.add(stp); } - this.WID = WID; - this.HEI = HEI; - System.out.println(WID + "*" + HEI); + movs = list; +// System.out.println(fixs.size() + "->" + movs.size()); } private void place1stStrip() { - int rotid = -1; + int rotid = 0; double minArea = 1000000000; int sid = movs.size() - 1; // ***************************************** last one Strip first = movs.get(sid); for (int i = 0; i < rotSteps; i++) { double[][] tp = M.rotate(trigos[i], first.outps); double[] bd = M.boundBox(tp); // minx, maxx, miny, maxy - if (bd[1] - bd[0] > WID || bd[3] - bd[2] > HEI) + if (bd[1] - bd[0] > width || bd[3] - bd[2] > height) { continue; + } double area = areasc * (bd[1] - bd[0]) * (bd[3] - bd[2]); double[] center = M.mean(tp); double len = preferX * (center[0] - bd[0]) + (1 - preferX) * (center[1] - bd[2]); @@ -101,29 +116,11 @@ private void place1stStrip() { cntConvex = new Convex(first.inps); } - public void packOneSheet(boolean Abey) { - place1stStrip(); - int size = movs.size(); - for (int i = 0; i < size; i++) { - if (Abey) - placeAnotherStrip_Abey(size - 1 - i); - else - placeAnotherStrip_Dalalah(size - 1 - i); - } - ArrayList list = new ArrayList(); - for (Strip stp : movs) { - if (null == stp) - continue; - list.add(stp); - } - movs = list; - System.out.println(fixs.size() + "->" + movs.size()); - } - public double leftOverArea() { double sum = 0; - for (Strip strip : movs) + for (Strip strip : movs) { sum += strip.inarea; + } return sum; } @@ -160,10 +157,11 @@ private boolean placeAnotherStrip_Abey(int sid) { for (int h = 0; h < 2; h++) { // two angles double[] cossin; - if (0 == h) + if (0 == h) { cossin = new double[] { ca0 * cb2 + sa0 * sb2, sa0 * cb2 - ca0 * sb2 }; // a0 - b2 - else + } else { cossin = new double[] { ca2 * cb0 + sa2 * sb0, sa2 * cb0 - ca2 * sb0 };// a2 - b0 + } double[][] rot_opl = M.rotate(cossin, opl); double[] trans = M.sub(v, rot_opl[i]); // ***************** @@ -171,8 +169,9 @@ private boolean placeAnotherStrip_Abey(int sid) { if (feasible(trans_rot_outpoly)) { double[][] trans_rot_inpoly = M.move(trans, M.rotate(cossin, stp.inps)); Convex tmpcon = cntConvex.clone(); - for (double[] trp : trans_rot_inpoly) + for (double[] trp : trans_rot_inpoly) { tmpcon.increment_hull(trp); + } double conarea = areasc * M.areaAbs(tmpcon.convex); double[] center = M.mean(trans_rot_inpoly); @@ -185,12 +184,13 @@ private boolean placeAnotherStrip_Abey(int sid) { min_con = tmpcon; } } - }// for h + } // for h } } } // for each vertex of new strip - if (null == min_cossin) // no solution, stop + if (null == min_cossin) { // no solution, stop return false; + } stp.fix_rotate_move(min_cossin, min_trans); movs.set(sid, null); fixs.add(stp); @@ -216,8 +216,9 @@ private boolean placeAnotherStrip_Dalalah(int sid) { if (feasible(trans_rot_outpoly)) { double[][] trans_rot_inpoly = M.move(trans, rotated_inpoly); Convex tmpcon = cntConvex.clone(); - for (double[] trp : trans_rot_inpoly) + for (double[] trp : trans_rot_inpoly) { tmpcon.increment_hull(trp); + } double conarea = areasc * M.areaAbs(tmpcon.convex); double[] center = M.mean(trans_rot_outpoly);// trans_rot_outpoly @@ -233,8 +234,9 @@ private boolean placeAnotherStrip_Dalalah(int sid) { } } // for each vertex of new strip } // for each angle of new strip - if (0 > min_rotid) // no solution, stop + if (0 > min_rotid) { // no solution, stop return false; + } stp.fix_rotate_move(trigos[min_rotid], min_trans); // movs.remove(sid); movs.set(sid, null); @@ -245,14 +247,14 @@ private boolean placeAnotherStrip_Dalalah(int sid) { private boolean feasible(double[][] poly) { for (double[] p : poly) { - if (p[0] < 0 || p[0] > WID) - return false; - if (p[1] < 0 || p[1] > HEI) + if (p[0] < 0 || p[0] > width || p[1] < 0 || p[1] > height) { return false; + } } for (Strip fixed : fixs) { - if (overlap(poly, fixed.inps)) + if (overlap(poly, fixed.inps)) { return false; + } } return true; } @@ -260,30 +262,40 @@ private boolean feasible(double[][] poly) { public int[] getStripIds() { int size = fixs.size(); int[] ids = new int[size]; - for (int i = 0; i < size; i++) + for (int i = 0; i < size; i++) { ids[i] = fixs.get(i).id; + } return ids; } public double[][] getStripRotations() { int size = fixs.size(); double[][] rots = new double[size][]; - for (int i = 0; i < size; i++) + for (int i = 0; i < size; i++) { rots[i] = fixs.get(i).trigo; + } return rots; } public double[][] getStripPositions() { int size = fixs.size(); double[][] ps = new double[size][]; - for (int i = 0; i < size; i++) + for (int i = 0; i < size; i++) { ps[i] = fixs.get(i).position; + } return ps; } - private static boolean overlap(double[][] poly1, double[][] poly2) { - if (!M.intersect_boundBox(poly1, poly2)) + /** + * Algorithm spends most time here! + * @param poly1 + * @param poly2 + * @return + */ + private static final boolean overlap(final double[][] poly1, final double[][] poly2) { + if (!M.intersect_boundBox(poly1, poly2)) { return false; + } double[][] sml, big; if (M.areaAbs(poly1) < M.areaAbs(poly2)) { sml = poly1; @@ -293,16 +305,30 @@ private static boolean overlap(double[][] poly1, double[][] poly2) { big = poly1; } for (double[] p : sml) { - if (M.inside(p, big)) + if (M.inside(p, big)) { return true; + } } for (int i = 0; i < sml.length; i++) { for (int j = 0; j < big.length; j++) { - if (M.intersection(sml[i], sml[(i + 1) % sml.length], big[j], big[(j + 1) % big.length])) + if (M.intersection(sml[i], sml[(i + 1) % sml.length], big[j], big[(j + 1) % big.length])) { return true; + } } } return false; } + @Override + public Pack clone() { + Pack np = new Pack(trigos, rotSteps, width, height, preferX); + np.movs = movs; + np.cntConvex = cntConvex; + return np; + } + + public boolean isEmpty() { + return movs.isEmpty(); + } + } diff --git a/pack/Strip.java b/src/main/java/whitegreen/dalsoo/Strip.java similarity index 72% rename from pack/Strip.java rename to src/main/java/whitegreen/dalsoo/Strip.java index ab3ad42..c540525 100644 --- a/pack/Strip.java +++ b/src/main/java/whitegreen/dalsoo/Strip.java @@ -1,35 +1,37 @@ -package pack; +package whitegreen.dalsoo; import java.util.ArrayList; //Hao Hua, Southeast University, whitegreen@163.com - public class Strip implements Comparable { + public double[][] outps; // offset & add edge points , as referent point of placement, clock-wise - public final double[][] inps; // original polygon, for 1. convex, 2. intersection + public final double[][] inps; // original polygon, for 1. convex, 2. intersection public final double inarea; - public double[] trigo; //cos & sin - public double[] position ; + public double[] trigo; // cos & sin + public double[] position; public final int id; - public Strip(int id, double[][] original_poly, double offset, Double segment_max_length) { - this.id=id; - if(offset<=0) - throw new RuntimeException(); + public Strip(int id, double[][] original_poly, double spacing, Double segment_max_length) { + this.id = id; + if (spacing < 0) { + throw new IllegalArgumentException("spacing must be >=0"); + } double area = M.area(original_poly); if (0 < area) { inps = M.clone(original_poly); } else { inps = new double[original_poly.length][]; - for (int i = 0; i < inps.length; i++) + for (int i = 0; i < inps.length; i++) { inps[i] = original_poly[inps.length - 1 - i].clone(); + } } inarea = Math.abs(area); - outps = M.offset(offset, inps); // clockwise + outps = M.offset(spacing, inps); // clockwise - if (null != segment_max_length) { - ArrayList list = new ArrayList(); + if (segment_max_length != null) { + ArrayList list = new ArrayList<>(); for (int i = 0; i < outps.length; i++) { double[] pa = outps[i]; double[] pb = outps[(i + 1) % outps.length]; @@ -42,22 +44,19 @@ public Strip(int id, double[][] original_poly, double offset, Double segment_max list.add(M.between(s, pa, pb)); } } - }// for + } // for outps = new double[list.size()][]; - for (int i = 0; i < outps.length; i++) + for (int i = 0; i < outps.length; i++) { outps[i] = list.get(i); - }// if + } + } // if } + @Override public int compareTo(Strip pl) { - if (this.inarea > pl.inarea) - return 1; //return 1 for ascendant sorting - else if (this.inarea < pl.inarea) - return -1; - else - return 0; + return Double.compare(this.inarea, pl.inarea); } - + public void fix_rotate_move(double[] cossin, double[] dv) { // finalize trigo = cossin.clone(); position = dv.clone(); diff --git a/src/main/java/whitegreen/dalsoo/TestMultiSheets1b.java b/src/main/java/whitegreen/dalsoo/TestMultiSheets1b.java new file mode 100644 index 0000000..d777113 --- /dev/null +++ b/src/main/java/whitegreen/dalsoo/TestMultiSheets1b.java @@ -0,0 +1,234 @@ +package whitegreen.dalsoo; + +import java.util.ArrayList; +import java.util.Random; + +import net.jafama.FastMath; +import processing.core.PApplet; + +/** + * + * @author Hao Hua, Southeast University Nanjing, http://labaaa.org + * + * 2D bin packing places a given set of polygons in standard + * single/multiple rectangular sheet(s), to minimize the use of the + * sheet(s). This library does not involve other libraries, however, the + * example uses core.jar (https://processing.org) for a graphical + * interface. The algorithm is effective when the ratio (number of + * polygons / number of the types of polygons) is small. + * + * + * 1. Input a. Only simple polygon: no holes, no self-intersection. b. + * Data structure: point - double[]; polygon - double[][]; all polygons + * - double[][][]. One might use other library to convert other formats + * (e.g. dxf, obj) of polygon to double[][]. c. It's better to represent + * a polygon with a moderate number of points. Too many points (e.g. a + * local detail contains dozens of points) slows down the algorithm. + * Avoid using too many points for a smooth curve. One might use + * segment_max_length to create more points on a long edge of a polygon, + * if the polygon has very few points or the edge is very long. + * + * + * 2. Choose an algorithm a. useAbey=true, Jostle heuristics for the + * 2D-irregular shapes bin packing problems with free rotation, R. P. + * Abeysooriya 2018 rotSteps: Each polygon is rotated in the layout. Few + * steps (say 16) -> run fast & poor result; many steps (say 48) -> run + * slow & good results segment_max_length: if (an edge of a polygon > + * segment_max_length), breaks it into smaller segments. large value -> + * run fast & poor result; small value -> run slow & good results + * segment_max_length is related to translation steps. + * + * b. useAbey=false, Waste minimization in irregular stock cutting, D. + * Dalalah, 2014 the rotation/translation steps depend on the polygons. + * + * + * 3. Output + * + */ +public class TestMultiSheets1b extends PApplet { + // https://github.com/whitegreen/Dalsoo-Bin-Packing + + public static void main(String[] args) { + System.setProperty("sun.java2d.uiScale", "1.0"); + System.setProperty("prism.allowhidpi", "false"); + PApplet.main(TestMultiSheets1b.class); + } + + private Random ran; + + // input + private double[][][] randompolys; // the input polygons + private final float WID = 2400 * 2; // width of the standard rectangular sheet + private final float HEI = 1200 * 2; + private final double margin = 4.0; + // when 0, polys will pack horizontally, 1= vertically + private final double preferX = .666; // 0.501 or 1 + + // parameters + private final double segment_max_length = 400.0; // 250,400,800, use to break long edges if necessary, relative to the scale + // of the polgyons + private final int rotSteps = 10; // 18,24,36,48, rotation steps + private boolean useAbey = true; + private ArrayList packs = new ArrayList<>(); + // true: rotation steps depend on polygons, R. P. Abeysooriya 2018 + // false: rotation steps are a prior, D. Dalalah, 2014 + + // output + private int[] result_pack_id; // result_pack_id[9]=2 means the 9th polygon is on the 2nd sheet. + private double[][] result_cos_sin; // result_cos_sin[9]={0.5, 0.866} means the 9th polygon is rotated 60 degree + // w.r.t its reference point + private double[][] result_position; // result_cos_sin[9] denotes the x,y-coordinate of the 9th polygon w.r.t its + // reference point + + @Override + public void settings() { + size(1600, 800); + } + + @Override + public void setup() { + long t0 = System.currentTimeMillis(); + int seed = 4346; + ran = new Random(0); + randompolys = randomPolygons(350);// prepare the input polygons + + Double segment_len = useAbey ? null : segment_max_length; + Pack pack = new Pack(randompolys, margin, segment_len, rotSteps, WID, HEI, preferX); + pack.packOneSheet(useAbey); + packs.add(pack); + + while(!packs.get(packs.size() - 1).isEmpty()) { + pack = packs.get(packs.size() - 1).clone(); + pack.packOneSheet(useAbey); + packs.add(pack); + } + +// for (int i = 0; i < 100; i++) { // packing one sheet after another, 100 is estimated +// int size = packs.size(); +// if (packs.get(size - 1).isEmpty()) { +// println(size + " sheets"); +// break; +// } +// pack = packs.get(size - 1).clone(); +// pack.packOneSheet(useAbey); +// packs.add(pack); +// } + report(); + + System.out.println((System.currentTimeMillis() - t0) / 1000f); + } + + private void report() { + result_pack_id = new int[randompolys.length]; + result_cos_sin = new double[randompolys.length][]; + result_position = new double[randompolys.length][]; + for (int i = 0; i < packs.size(); i++) { + Pack pack = packs.get(i); + for (Strip strip : pack.fixs) { + result_pack_id[strip.id] = i; + result_cos_sin[strip.id] = strip.trigo; + result_position[strip.id] = strip.position; + } + } + } + + private double[][][] randomPolygons(int num) { + double[][][] protos = new double[6][][]; + // protos[0] = new double[][] { { 0, 0 }, { 0, 2 }, { 6, 2 }, { 6, 12 }, { 8, 12 + // }, { 8, 0 } }; + protos[0] = new double[][] { { 0, 0 }, { 0, 10 }, { 10, 10 }, { 10, 0 } }; + protos[1] = new double[][] { { 0, 0 }, { 0, 16 }, { 1, 16 }, { 1, 0 } }; + protos[2] = new double[][] { { 0, 0 }, { 0, 12 }, { 9, 6 } }; + protos[3] = new double[][] { { 0, 0 }, { 0, 2 }, { 8, 2 }, { 8, 8 }, { 0, 8 }, { 0, 10 }, { 10, 10 }, { 10, 0 } }; + protos[4] = new double[][] { { 0, 0 }, { 0, 2 }, { 6, 2 }, { 6, 12 }, { 8, 12 }, { 8, 0 } }; + protos[5] = new double[][] { { 0, 0 }, { 0, 5 }, { 4, 1 }, { 8, 5 }, { 4, 10 }, { 0, 6 }, { 0, 11 }, { 9, 11 }, + { 9, 0 } }; + + double[][][] polys = new double[num][][]; + for (int i = 0; i < num; i++) { + double[][] pl = protos[ran.nextInt(protos.length)]; + double sc = 8 + ran.nextDouble() * 12; // 8+ ran.nextDouble()*12 10+ ran.nextDouble()*20 + polys[i] = shake(3 * sc, pl); // + } + for (int i = 0; i < num; i++) { + double[][] poly = polys[i]; + double dx = ran.nextDouble() * 1000; + double dy = ran.nextDouble() * 1000; + for (double[] p : poly) { + M._add(p, new double[] { dx, dy }); + } + } + return polys; + } + + private double[][] shake(double s, double[][] ps) { + double[][] arr = new double[ps.length][]; + double sng = ran.nextBoolean() ? s : (-s); // mirror + double theta = ran.nextDouble() * 2 * PI; + double cos = FastMath.cos(theta); + double sin = FastMath.sin(theta); + for (int i = 0; i < ps.length; i++) { + double[] p = M.scale(sng, ps[i]); + p[0] += (ran.nextDouble() - 0.5) * 0.25 * s; + p[1] += (ran.nextDouble() - 0.5) * 0.25 * s; + double x = cos * p[0] + sin * p[1]; + double y = -sin * p[0] + cos * p[1]; + arr[i] = new double[] { x, y }; + } + return arr; + } + + @Override + public void draw() { + background(255); + smooth(); + translate(40, 10); + float sc = 0.15f; + + // display method 1 +// for (int i = 0; i < randompolys.length; i++) { +// int pack_id = result_pack_id[i]; +// pushMatrix(); +//// translate((pack_id % 3) * 380, (pack_id / 3) * 200); +// +// noFill(); +// rect(0, 0, sc * WID, sc * HEI); +// fill(0, 255, 0); +// double[][] poly = randompolys[i]; +// poly = M.rotate(result_cos_sin[i], poly); +// poly = M.move(result_position[i], poly); +// draw(poly, sc); +// +// popMatrix(); +// } +// display method 2 + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 3; j++) { + int id = i * 3 + j; + if (id >= packs.size()) { + return; + } + Pack pack = packs.get(id); + pushMatrix(); + translate(j * (sc*WID), i * (sc*height)); // (j * 270, i * 150 + noFill(); + rect(0, 0, sc * WID, sc * HEI); + fill(0, 255, 0); + for (Strip strip : pack.fixs) { + draw(strip.inps, sc); + } + popMatrix(); + } + } + + } + + private void draw(double[][] ps, float sc) { + beginShape(); + for (double[] p : ps) { + vertex((float) p[0] * sc, (float) p[1] * sc); + } + endShape(CLOSE); + } + +} From 1e63bb626130caa56ffe2421e000ba0317f893a2 Mon Sep 17 00:00:00 2001 From: Michael Carleton Date: Tue, 3 Jan 2023 22:47:27 +0000 Subject: [PATCH 2/9] refactor --- src/main/java/whitegreen/dalsoo/Convex.java | 1 + src/main/java/whitegreen/dalsoo/Strip.java | 12 ++++++------ .../java/whitegreen/dalsoo/TestMultiSheets1b.java | 8 ++++---- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/java/whitegreen/dalsoo/Convex.java b/src/main/java/whitegreen/dalsoo/Convex.java index 4018ab7..4734a44 100644 --- a/src/main/java/whitegreen/dalsoo/Convex.java +++ b/src/main/java/whitegreen/dalsoo/Convex.java @@ -5,6 +5,7 @@ //Hao Hua, Southeast University, whitegreen@163.com public class Convex { + public ArrayList convex; // convex is clockwise private static final double area_zero = 1E-6; // for mm diff --git a/src/main/java/whitegreen/dalsoo/Strip.java b/src/main/java/whitegreen/dalsoo/Strip.java index c540525..99fac4b 100644 --- a/src/main/java/whitegreen/dalsoo/Strip.java +++ b/src/main/java/whitegreen/dalsoo/Strip.java @@ -5,7 +5,7 @@ //Hao Hua, Southeast University, whitegreen@163.com public class Strip implements Comparable { - + public double[][] outps; // offset & add edge points , as referent point of placement, clock-wise public final double[][] inps; // original polygon, for 1. convex, 2. intersection public final double inarea; @@ -52,11 +52,6 @@ public Strip(int id, double[][] original_poly, double spacing, Double segment_ma } // if } - @Override - public int compareTo(Strip pl) { - return Double.compare(this.inarea, pl.inarea); - } - public void fix_rotate_move(double[] cossin, double[] dv) { // finalize trigo = cossin.clone(); position = dv.clone(); @@ -76,4 +71,9 @@ public void fix_rotate_move(double[] cossin, double[] dv) { // finalize } } + @Override + public int compareTo(Strip pl) { + return Double.compare(this.inarea, pl.inarea); + } + } diff --git a/src/main/java/whitegreen/dalsoo/TestMultiSheets1b.java b/src/main/java/whitegreen/dalsoo/TestMultiSheets1b.java index d777113..673b0e2 100644 --- a/src/main/java/whitegreen/dalsoo/TestMultiSheets1b.java +++ b/src/main/java/whitegreen/dalsoo/TestMultiSheets1b.java @@ -96,11 +96,11 @@ public void setup() { Pack pack = new Pack(randompolys, margin, segment_len, rotSteps, WID, HEI, preferX); pack.packOneSheet(useAbey); packs.add(pack); - - while(!packs.get(packs.size() - 1).isEmpty()) { + + while (!packs.get(packs.size() - 1).isEmpty()) { pack = packs.get(packs.size() - 1).clone(); pack.packOneSheet(useAbey); - packs.add(pack); + packs.add(pack); } // for (int i = 0; i < 100; i++) { // packing one sheet after another, 100 is estimated @@ -210,7 +210,7 @@ public void draw() { } Pack pack = packs.get(id); pushMatrix(); - translate(j * (sc*WID), i * (sc*height)); // (j * 270, i * 150 + translate(j * (sc * WID), i * (sc * height)); // (j * 270, i * 150 noFill(); rect(0, 0, sc * WID, sc * HEI); fill(0, 255, 0); From d01de4c0a5937b8e4113f7edeebc24036cc6b66d Mon Sep 17 00:00:00 2001 From: Michael Carleton Date: Wed, 4 Jan 2023 02:46:33 +0000 Subject: [PATCH 3/9] speed up ~2-3x include jts to buffer convex polygons when degeneracy occurs --- pom.xml | 5 + src/main/java/whitegreen/dalsoo/Convex.java | 8 +- src/main/java/whitegreen/dalsoo/M.java | 68 +++++--- src/main/java/whitegreen/dalsoo/Pack.java | 167 ++++++++++++++------ src/main/java/whitegreen/dalsoo/Strip.java | 24 ++- 5 files changed, 193 insertions(+), 79 deletions(-) diff --git a/pom.xml b/pom.xml index 72b0c2e..34c626c 100644 --- a/pom.xml +++ b/pom.xml @@ -33,5 +33,10 @@ jafama 2.3.2 + + org.locationtech.jts + jts-core + 1.19.0 + \ No newline at end of file diff --git a/src/main/java/whitegreen/dalsoo/Convex.java b/src/main/java/whitegreen/dalsoo/Convex.java index 4734a44..e555847 100644 --- a/src/main/java/whitegreen/dalsoo/Convex.java +++ b/src/main/java/whitegreen/dalsoo/Convex.java @@ -20,10 +20,10 @@ public Convex clone() { public Convex() { } - - public Convex(double[][] points) { // always ready for new points - double[][] tri = { points[0], points[1], points[2] }; - double area = M.area(tri); + + public Convex(Strip strip) { + double[][] points = strip.inps; + double area = strip.inarea; if (Math.abs(area) < area_zero) { throw new RuntimeException(); } diff --git a/src/main/java/whitegreen/dalsoo/M.java b/src/main/java/whitegreen/dalsoo/M.java index 318ef7d..132126e 100644 --- a/src/main/java/whitegreen/dalsoo/M.java +++ b/src/main/java/whitegreen/dalsoo/M.java @@ -2,13 +2,18 @@ import java.util.ArrayList; +import org.locationtech.jts.operation.buffer.BufferOp; +import org.locationtech.jts.operation.buffer.BufferParameters; + import net.jafama.FastMath; //Hao Hua, Southeast University, whitegreen@163.com public final class M { - private static final double denominator_lim = 1e-32; + private static final double denominator_lim = 1e-10; + private static final BufferParameters bp = new BufferParameters(8, BufferParameters.CAP_FLAT, BufferParameters.JOIN_MITRE, + BufferParameters.DEFAULT_MITRE_LIMIT); // math // ************************************************************************************* @@ -241,7 +246,7 @@ public static double[] cross(double[] a, double[] b) { return v; } - double[] center(double[][] ps) { + static double[] center(double[][] ps) { int len = ps[0].length; double[] sum = new double[len]; for (double[] element : ps) { @@ -400,6 +405,19 @@ public static boolean intersect_boundBox(double[][] poly1, double[][] poly2) { return true; } + /** + * + * @param a [minx, maxx, miny, maxy] + * @param b [minx, maxx, miny, maxy] + * @return + */ + public static boolean intersect_boundBoxes(double[] a, double[] b) { + if (a[1] < b[0] || a[0] > b[1] || a[3] < b[2] || a[2] > b[3]) { + return false; + } + return true; + } + public static double[] boundBox(double[][] poly) { // orthogonal, minx, max, miny, maxy double[] v = poly[0]; double minx = v[0]; @@ -424,8 +442,7 @@ public static double[] boundBox(double[][] poly) { // orthogonal, minx, max, min return new double[] { minx, maxx, miny, maxy }; } - public static double[][] offset(final double distance, final double[][] poly) { - + public static double[][] buffer(final double[][] poly, final double distance) { double[][] ps = new double[poly.length][]; for (int i = 0; i < poly.length; i++) { double[] p = poly[i]; @@ -436,6 +453,13 @@ public static double[][] offset(final double distance, final double[][] poly) { double[] pa = distance == 0 ? p : add(p, scaleTo(distance, na)); double[] pb = distance == 0 ? p : add(p, scaleTo(distance, nb)); ps[i] = lineIntersect(pa, va, pb, vb); + if (ps[i] == null) { + /* + * Fall back to JTS buffer if lineIntersect returns null for any intersection + * (occurs on rather concave shapes). + */ + return Pack.toArray(BufferOp.bufferOp(Pack.toPolygon(poly), distance, bp).getCoordinates()); + } } return ps; } @@ -533,7 +557,7 @@ private static double kross(double[] a, double[] b) { return a[0] * b[1] - a[1] * b[0]; } - public static double area(double[][] ps) { // signed + public static double area(final double[][] ps) { // signed double sum = 0; for (int i = 0; i < ps.length; i++) { double[] pa = ps[i]; @@ -605,14 +629,6 @@ public static double[] rotate_Rodriguez(double[] v, double theta, double[] dir) return M.add(v1, M.add(v2, v3)); } -// double[][] offset(double s, double[][] ps) { -// double[][] nps = new double[ps.length][]; -// double[] cnt = center(ps); -// for (int i = 0; i < ps.length; i++) -// nps[i] = between(s, ps[i], cnt); -// return nps; -// } - public static boolean inside(double[] p, double[][] vs) { int i, j = vs.length - 1; boolean oddNodes = false; @@ -645,7 +661,16 @@ public static boolean inside(double[] p, ArrayList vs) { return oddNodes; } - public static boolean intersection(double[] a, double[] b, double[] c, double[] d) { + /** + * Determines whether two line segments intersect. + * + * @param a line 1 p1 + * @param b line 1 p2 + * @param c line 2 p1 + * @param d line 2 p2 + * @return + */ + public static boolean intersection(final double[] a, final double[] b, final double[] c, final double[] d) { double[][] abd = { a, b, d }; double[][] abc = { a, b, c }; double[][] cda = { c, d, a }; @@ -653,14 +678,13 @@ public static boolean intersection(double[] a, double[] b, double[] c, double[] return area(abd) * area(abc) < 0 && area(cda) * area(cdb) < 0; } -// public static double[] lineIntersect(double[] p0, double[] n0, double[] p1, double[] n1){ //in 2d -// double cross_base= cross(n0, n1); -// if(FastMath.abs(cross_base)<0.000001)//parallel -// return null; -// double[] d= sub(p1,p0); -// double s= cross(d, n1)/cross_base; -// return new double[]{p0[0]+s*n0[0], p0[1]+s*n0[1]}; //TRICK 3D -// } + public static boolean intersectionFast(final double[] a, final double[] b, final double[] c, final double[] d) { + return triangleArea(a, b, d) * triangleArea(a, b, c) < 0 && triangleArea(c, d, a) * triangleArea(c, d, b) < 0; + } + + public static double triangleArea(final double[] a, final double[] b, final double c[]) { + return (a[0] * (b[1] - c[1]) + b[0] * (c[1] - a[1]) + c[0] * (a[1] - b[1])); // omit /2 + } // special // ************************************************************************************* diff --git a/src/main/java/whitegreen/dalsoo/Pack.java b/src/main/java/whitegreen/dalsoo/Pack.java index 61c74d7..1c29440 100644 --- a/src/main/java/whitegreen/dalsoo/Pack.java +++ b/src/main/java/whitegreen/dalsoo/Pack.java @@ -2,15 +2,22 @@ import static java.lang.Math.PI; -//Hao Hua, Southeast University, whitegreen@163.com - import java.util.ArrayList; -import java.util.Collections; - +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Polygon; import net.jafama.FastMath; +/** + * + * @author Hao Hua, Southeast University, whitegreen@163.com + * @author Michael Carleton + * + */ public final class Pack { + private static final GeometryFactory GEOM_FACT = new GeometryFactory(); + public ArrayList fixs = new ArrayList<>(); public ArrayList movs = new ArrayList<>(); public Convex cntConvex; @@ -53,7 +60,7 @@ public Pack(double[][][] polys, double spacing, Double segment_max_length, int r Strip strip = new Strip(i, poly, spacing, segment_max_length); movs.add(strip); } - Collections.sort(movs); // sort by area, smallest first +// Collections.sort(movs); // sort by area, smallest first this.preferX = preferX; this.rotSteps = rotSteps; @@ -85,7 +92,6 @@ public void packOneSheet(boolean abey) { list.add(stp); } movs = list; -// System.out.println(fixs.size() + "->" + movs.size()); } private void place1stStrip() { @@ -112,16 +118,8 @@ private void place1stStrip() { double[] bd = M.boundBox(tp); first.fix_rotate_move(trigos[rotid], new double[] { -bd[0], -bd[2] }); movs.remove(sid); - fixs.add(first); - cntConvex = new Convex(first.inps); - } - - public double leftOverArea() { - double sum = 0; - for (Strip strip : movs) { - sum += strip.inarea; - } - return sum; + placeStrip(first); + cntConvex = new Convex(first); } private boolean placeAnotherStrip_Abey(int sid) { @@ -193,7 +191,7 @@ private boolean placeAnotherStrip_Abey(int sid) { } stp.fix_rotate_move(min_cossin, min_trans); movs.set(sid, null); - fixs.add(stp); + placeStrip(stp); cntConvex = min_con; return true; } @@ -240,7 +238,7 @@ private boolean placeAnotherStrip_Dalalah(int sid) { stp.fix_rotate_move(trigos[min_rotid], min_trans); // movs.remove(sid); movs.set(sid, null); - fixs.add(stp); + placeStrip(stp); cntConvex = min_con; return true; } @@ -248,49 +246,22 @@ private boolean placeAnotherStrip_Dalalah(int sid) { private boolean feasible(double[][] poly) { for (double[] p : poly) { if (p[0] < 0 || p[0] > width || p[1] < 0 || p[1] > height) { + // out of bounds -- infeasible! return false; } } + final double[] bb = M.boundBox(poly); + for (Strip fixed : fixs) { - if (overlap(poly, fixed.inps)) { + if (overlapFast(poly, bb, fixed)) { return false; } } return true; } - public int[] getStripIds() { - int size = fixs.size(); - int[] ids = new int[size]; - for (int i = 0; i < size; i++) { - ids[i] = fixs.get(i).id; - } - return ids; - } - - public double[][] getStripRotations() { - int size = fixs.size(); - double[][] rots = new double[size][]; - for (int i = 0; i < size; i++) { - rots[i] = fixs.get(i).trigo; - } - return rots; - } - - public double[][] getStripPositions() { - int size = fixs.size(); - double[][] ps = new double[size][]; - for (int i = 0; i < size; i++) { - ps[i] = fixs.get(i).position; - } - return ps; - } - /** - * Algorithm spends most time here! - * @param poly1 - * @param poly2 - * @return + * @deprecated */ private static final boolean overlap(final double[][] poly1, final double[][] poly2) { if (!M.intersect_boundBox(poly1, poly2)) { @@ -319,6 +290,102 @@ private static final boolean overlap(final double[][] poly1, final double[][] po return false; } + /** + * Determines whether poly overlaps with strip. + * + * @param poly1 vertices of poly 1 + * @param poly1BB bounding box of poly 1 + * @param poly1Area area of poly 1 + * @param poly2 vertices of poly 2 + * @return + */ + private static final boolean overlapFast(final double[][] poly1, final double[] poly1BB, final Strip strip) { + + // 1. test bounding boxes + if (!M.intersect_boundBoxes(poly1BB, strip.bb)) { + return false; + } + // 2. test the centroid against candidate poly + /* + * NOTE this isn't completely robust (a robust method would test every point of + * strip against candidate) but would catch almost all occurrences (so is worth + * the speed-up overall). + */ + if (M.inside(strip.centroid, poly1)) { + return true; + } + + // 3. test edge intersections + for (int i = 0; i < poly1.length; i++) { + for (int j = 0; j < strip.inps.length; j++) { + if (M.intersectionFast(poly1[i], poly1[(i + 1) % poly1.length], strip.inps[j], + strip.inps[(j + 1) % strip.inps.length])) { + return true; + } + } + } + return false; + + } + + private void placeStrip(Strip strip) { + strip.fix(); + fixs.add(strip); + } + + static Polygon toPolygon(double[][] poly) { + Coordinate[] coords = new Coordinate[poly.length + 1]; + for (int i = 0; i < coords.length - 1; i++) { + coords[i] = new Coordinate(poly[i][0], poly[i][1]); + } + coords[coords.length - 1] = new Coordinate(poly[0][0], poly[0][1]); // close + return GEOM_FACT.createPolygon(coords); + } + + static double[][] toArray(Coordinate[] coords) { + double[][] poly = new double[coords.length - 1][2]; + for (int i = 0; i < coords.length - 1; i++) { // -1, unclose + poly[i][0] = coords[i].x; + poly[i][1] = coords[i].y; + } + return poly; + } + + public double leftOverArea() { + double sum = 0; + for (Strip strip : movs) { + sum += strip.inarea; + } + return sum; + } + + public int[] getStripIds() { + int size = fixs.size(); + int[] ids = new int[size]; + for (int i = 0; i < size; i++) { + ids[i] = fixs.get(i).id; + } + return ids; + } + + public double[][] getStripRotations() { + int size = fixs.size(); + double[][] rots = new double[size][]; + for (int i = 0; i < size; i++) { + rots[i] = fixs.get(i).trigo; + } + return rots; + } + + public double[][] getStripPositions() { + int size = fixs.size(); + double[][] ps = new double[size][]; + for (int i = 0; i < size; i++) { + ps[i] = fixs.get(i).position; + } + return ps; + } + @Override public Pack clone() { Pack np = new Pack(trigos, rotSteps, width, height, preferX); diff --git a/src/main/java/whitegreen/dalsoo/Strip.java b/src/main/java/whitegreen/dalsoo/Strip.java index 99fac4b..5c147c4 100644 --- a/src/main/java/whitegreen/dalsoo/Strip.java +++ b/src/main/java/whitegreen/dalsoo/Strip.java @@ -2,10 +2,15 @@ import java.util.ArrayList; -//Hao Hua, Southeast University, whitegreen@163.com - +/** + * + * @author Hao Hua, Southeast University, whitegreen@163.com + * + */ public class Strip implements Comparable { +// private static final + public double[][] outps; // offset & add edge points , as referent point of placement, clock-wise public final double[][] inps; // original polygon, for 1. convex, 2. intersection public final double inarea; @@ -27,8 +32,9 @@ public Strip(int id, double[][] original_poly, double spacing, Double segment_ma inps[i] = original_poly[inps.length - 1 - i].clone(); } } + inarea = Math.abs(area); - outps = M.offset(spacing, inps); // clockwise + outps = M.buffer(inps, spacing); // clockwise if (segment_max_length != null) { ArrayList list = new ArrayList<>(); @@ -71,6 +77,18 @@ public void fix_rotate_move(double[] cossin, double[] dv) { // finalize } } + double[] bb; + double[] centroid; + + /** + * Call when strip is fixed. Will pre-compute and save values used for overlap + * detection. + */ + public void fix() { + bb = M.boundBox(inps); + centroid = M.center(inps); + } + @Override public int compareTo(Strip pl) { return Double.compare(this.inarea, pl.inarea); From c9f15e776058eec0a6e5a3822b83f5b6da956e16 Mon Sep 17 00:00:00 2001 From: Michael Carleton Date: Wed, 4 Jan 2023 12:51:23 +0000 Subject: [PATCH 4/9] refactor class and method names --- pom.xml | 6 +- src/main/java/whitegreen/dalsoo/Convex.java | 10 +- .../dalsoo/{Pack.java => DalsooPack.java} | 269 +++++++++--------- ...TestMultiSheets1b.java => DemoApplet.java} | 36 +-- .../dalsoo/{M.java => MathUtil.java} | 55 ++-- .../dalsoo/{Strip.java => PackedPoly.java} | 38 ++- 6 files changed, 222 insertions(+), 192 deletions(-) rename src/main/java/whitegreen/dalsoo/{Pack.java => DalsooPack.java} (50%) rename src/main/java/whitegreen/dalsoo/{TestMultiSheets1b.java => DemoApplet.java} (88%) rename src/main/java/whitegreen/dalsoo/{M.java => MathUtil.java} (91%) rename src/main/java/whitegreen/dalsoo/{Strip.java => PackedPoly.java} (68%) diff --git a/pom.xml b/pom.xml index 34c626c..115d095 100644 --- a/pom.xml +++ b/pom.xml @@ -1,9 +1,9 @@ 4.0.0 whitegreen - dalsoo - 0.0.1-SNAPSHOT - Dalsoo-Bin-Packing + dalsoopack + 0.9-SNAPSHOT + Dalsoo Bin-Packing diff --git a/src/main/java/whitegreen/dalsoo/Convex.java b/src/main/java/whitegreen/dalsoo/Convex.java index e555847..c2e8659 100644 --- a/src/main/java/whitegreen/dalsoo/Convex.java +++ b/src/main/java/whitegreen/dalsoo/Convex.java @@ -4,7 +4,7 @@ //Hao Hua, Southeast University, whitegreen@163.com -public class Convex { +class Convex { public ArrayList convex; // convex is clockwise private static final double area_zero = 1E-6; // for mm @@ -21,7 +21,7 @@ public Convex clone() { public Convex() { } - public Convex(Strip strip) { + public Convex(PackedPoly strip) { double[][] points = strip.inps; double area = strip.inarea; if (Math.abs(area) < area_zero) { @@ -43,7 +43,7 @@ public Convex(Strip strip) { } public void increment_hull(double[] np) { // convex is clockwise - if (M.inside(np, convex)) { + if (MathUtil.inside(np, convex)) { return; } int size = convex.size(); @@ -52,8 +52,8 @@ public void increment_hull(double[] np) { // convex is clockwise for (int i = 0; i < size; i++) { double[] q0 = convex.get(i); double[] q1 = convex.get((i + 1) % size); - double[] d = M.sub(q1, q0); - double[] a = M.sub(np, q0); + double[] d = MathUtil.sub(q1, q0); + double[] a = MathUtil.sub(np, q0); visible[i] = -d[1] * a[0] + d[0] * a[1] > 0; // n={-d[1], d[0]} on the left if (visible[i]) { hasTure = true; diff --git a/src/main/java/whitegreen/dalsoo/Pack.java b/src/main/java/whitegreen/dalsoo/DalsooPack.java similarity index 50% rename from src/main/java/whitegreen/dalsoo/Pack.java rename to src/main/java/whitegreen/dalsoo/DalsooPack.java index 1c29440..2230ea3 100644 --- a/src/main/java/whitegreen/dalsoo/Pack.java +++ b/src/main/java/whitegreen/dalsoo/DalsooPack.java @@ -3,34 +3,38 @@ import static java.lang.Math.PI; import java.util.ArrayList; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.jts.geom.GeometryFactory; -import org.locationtech.jts.geom.Polygon; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + import net.jafama.FastMath; /** + * Bin-packs irregular shapes sequentially. + *

    + * Algorithms are adapted from the papers of Abeysooriya 2018 and Dalalah 2014. + * Bin packing places a given set of polygons in standard single/multiple + * rectangular sheet(s), minimising the use of the sheet(s). * * @author Hao Hua, Southeast University, whitegreen@163.com * @author Michael Carleton * */ -public final class Pack { - - private static final GeometryFactory GEOM_FACT = new GeometryFactory(); +public final class DalsooPack { - public ArrayList fixs = new ArrayList<>(); - public ArrayList movs = new ArrayList<>(); - public Convex cntConvex; - /** - * Sin and cos values for each rotation step. - */ + public List packedPolys = new ArrayList<>(); + List pendingPolys = new ArrayList<>(); + Convex cntConvex; + + /** Sin and cos values for each rotation step. */ private final double[][] trigos; private final int rotSteps; + /** bin dimensions */ private final double width, height; - private static final double areasc = 1E-6; // - private final double preferX; // 0.501 or 1 + private static final double areasc = 1E-6; + private final double preferX; - Pack(double[][] trigos, int rotSteps, double width, double height, double preferX) { + DalsooPack(double[][] trigos, int rotSteps, double width, double height, double preferX) { this.trigos = trigos; this.rotSteps = rotSteps; this.width = width; @@ -39,29 +43,38 @@ public final class Pack { } /** + * Creates an packing. Call {@link #packOneBin(boolean, boolean)} to start + * packing. * * @param polys array of polygons [p1, p2]; for each polygon, its * vertices are expressed in [x, y] coordinate pairs: - * [[p1x, p1y], [p2x, p2y]...] - * @param spacing boundary spacing between packed objects + * [[p1x, p1y], [p2x, p2y]...]. Polygons should be + * simple, having no holes and no self-intersection. + * @param spacing boundary spacing between packed objects. * @param segment_max_length - * @param rotSteps + * @param rotSteps number of unique rotation variants of each polygon. + * a larger number results in higher-quality packing + * but longer runtime (not used in abey packing). * @param width width of each bin * @param height height of each bin - * @param preferX + * @param hSkew horizontal skew [0...1]. Determines to what extent + * shapes are packed horizontally (vs vertically). + * i.e. When =1.0, shapes will start packing against + * the y axis, and fill left-to-right (horizontal); + * When =0.0, shapes will pack from the x-axis and + * fill top-to-bottom (vertical). */ - public Pack(double[][][] polys, double spacing, Double segment_max_length, int rotSteps, double width, double height, - double preferX) { - if (0 > preferX || 1 < preferX) { + public DalsooPack(double[][][] polys, double spacing, Double segment_max_length, int rotSteps, double width, double height, + double hSkew) { + if (0 > hSkew || 1 < hSkew) { throw new IllegalArgumentException("skew must be between 0 and 1 (inclusive)"); } for (int i = 0; i < polys.length; i++) { double[][] poly = polys[i]; - Strip strip = new Strip(i, poly, spacing, segment_max_length); - movs.add(strip); + PackedPoly strip = new PackedPoly(i, poly, spacing, segment_max_length); + pendingPolys.add(strip); } -// Collections.sort(movs); // sort by area, smallest first - this.preferX = preferX; + this.preferX = hSkew; this.rotSteps = rotSteps; trigos = new double[rotSteps][]; @@ -73,40 +86,51 @@ public Pack(double[][][] polys, double spacing, Double segment_max_length, int r this.height = height; } - public void packOneSheet(boolean abey) { - place1stStrip(); - int size = movs.size(); + /** + * Packs all polygons, possibly across multiple bins. + * + * @param abey + */ + public void packAll(boolean abey) { + + } + + /** + * + * @param abey + * @param largestFirst sort the polygons by area and pack + */ + public void packOneBin(boolean abey, boolean largestFirst) { + if (largestFirst) { + Collections.sort(pendingPolys); // sort by area, smallest first + } + packFirstPoly(); + int size = pendingPolys.size(); for (int i = 0; i < size; i++) { // place next largest polygon if (abey) { - placeAnotherStrip_Abey(size - 1 - i); + packPolyAbey(size - 1 - i); } else { - placeAnotherStrip_Dalalah(size - 1 - i); + packPolyDalalah(size - 1 - i); } } - ArrayList list = new ArrayList<>(); - for (Strip stp : movs) { - if (null == stp) { - continue; - } - list.add(stp); - } - movs = list; + + pendingPolys.removeIf(Objects::isNull); } - private void place1stStrip() { + private void packFirstPoly() { int rotid = 0; double minArea = 1000000000; - int sid = movs.size() - 1; // ***************************************** last one - Strip first = movs.get(sid); + int sid = pendingPolys.size() - 1; // ***************************************** last one + PackedPoly first = pendingPolys.get(sid); for (int i = 0; i < rotSteps; i++) { - double[][] tp = M.rotate(trigos[i], first.outps); - double[] bd = M.boundBox(tp); // minx, maxx, miny, maxy + double[][] tp = MathUtil.rotate(trigos[i], first.outps); + double[] bd = MathUtil.boundBox(tp); // minx, maxx, miny, maxy if (bd[1] - bd[0] > width || bd[3] - bd[2] > height) { continue; } double area = areasc * (bd[1] - bd[0]) * (bd[3] - bd[2]); - double[] center = M.mean(tp); + double[] center = MathUtil.mean(tp); double len = preferX * (center[0] - bd[0]) + (1 - preferX) * (center[1] - bd[2]); area *= len; if (minArea > area) { @@ -114,16 +138,16 @@ private void place1stStrip() { rotid = i; } } - double[][] tp = M.rotate(trigos[rotid], first.outps); - double[] bd = M.boundBox(tp); + double[][] tp = MathUtil.rotate(trigos[rotid], first.outps); + double[] bd = MathUtil.boundBox(tp); first.fix_rotate_move(trigos[rotid], new double[] { -bd[0], -bd[2] }); - movs.remove(sid); - placeStrip(first); + pendingPolys.remove(sid); + placePackedPoly(first); cntConvex = new Convex(first); } - private boolean placeAnotherStrip_Abey(int sid) { - Strip stp = movs.get(sid); + private boolean packPolyAbey(int sid) { + PackedPoly stp = pendingPolys.get(sid); double min = 1000000000; double[] min_cossin = null; double[] min_trans = null; @@ -131,23 +155,23 @@ private boolean placeAnotherStrip_Abey(int sid) { double[][] opl = stp.outps; for (int i = 0; i < opl.length; i++) { // each vertex of new strip double[] p = opl[i]; - double[] d0 = M.sub(opl[(i - 1 + opl.length) % opl.length], p); - double[] d2 = M.sub(opl[(i + 1) % opl.length], p); - double mag0 = M.mag(d0); - double mag2 = M.mag(d2); + double[] d0 = MathUtil.sub(opl[(i - 1 + opl.length) % opl.length], p); + double[] d2 = MathUtil.sub(opl[(i + 1) % opl.length], p); + double mag0 = MathUtil.mag(d0); + double mag2 = MathUtil.mag(d2); double cb0 = d0[0] / mag0; double sb0 = d0[1] / mag0; double cb2 = d2[0] / mag2; double sb2 = d2[1] / mag2; - for (Strip fixed : fixs) { + for (PackedPoly fixed : packedPolys) { double[][] fopl = fixed.outps; for (int j = 0; j < fopl.length; j++) { // each vertex of each fixed strip double[] v = fopl[j]; - double[] t0 = M.sub(fopl[(j - 1 + fopl.length) % fopl.length], v); - double[] t2 = M.sub(fopl[(j + 1) % fopl.length], v); - double m0 = M.mag(t0); - double m2 = M.mag(t2); + double[] t0 = MathUtil.sub(fopl[(j - 1 + fopl.length) % fopl.length], v); + double[] t2 = MathUtil.sub(fopl[(j + 1) % fopl.length], v); + double m0 = MathUtil.mag(t0); + double m2 = MathUtil.mag(t2); double ca0 = t0[0] / m0; double sa0 = t0[1] / m0; double ca2 = t2[0] / m2; @@ -161,18 +185,18 @@ private boolean placeAnotherStrip_Abey(int sid) { cossin = new double[] { ca2 * cb0 + sa2 * sb0, sa2 * cb0 - ca2 * sb0 };// a2 - b0 } - double[][] rot_opl = M.rotate(cossin, opl); - double[] trans = M.sub(v, rot_opl[i]); // ***************** - double[][] trans_rot_outpoly = M.move(trans, rot_opl); - if (feasible(trans_rot_outpoly)) { - double[][] trans_rot_inpoly = M.move(trans, M.rotate(cossin, stp.inps)); + double[][] rot_opl = MathUtil.rotate(cossin, opl); + double[] trans = MathUtil.sub(v, rot_opl[i]); // ***************** + double[][] trans_rot_outpoly = MathUtil.move(trans, rot_opl); + if (isFeasible(trans_rot_outpoly)) { + double[][] trans_rot_inpoly = MathUtil.move(trans, MathUtil.rotate(cossin, stp.inps)); Convex tmpcon = cntConvex.clone(); for (double[] trp : trans_rot_inpoly) { tmpcon.increment_hull(trp); } - double conarea = areasc * M.areaAbs(tmpcon.convex); - double[] center = M.mean(trans_rot_inpoly); + double conarea = areasc * MathUtil.areaAbs(tmpcon.convex); + double[] center = MathUtil.mean(trans_rot_inpoly); double area; area = conarea * (preferX * Math.abs(center[0]) + (1 - preferX) * Math.abs(center[1])); if (min > area) { @@ -190,36 +214,36 @@ private boolean placeAnotherStrip_Abey(int sid) { return false; } stp.fix_rotate_move(min_cossin, min_trans); - movs.set(sid, null); - placeStrip(stp); + pendingPolys.set(sid, null); // done, mark as null + placePackedPoly(stp); cntConvex = min_con; return true; } - private boolean placeAnotherStrip_Dalalah(int sid) { - Strip stp = movs.get(sid); + private boolean packPolyDalalah(int sid) { + PackedPoly stp = pendingPolys.get(sid); double min = 1000000000; int min_rotid = -1; double[] min_trans = null; Convex min_con = null; for (int i = 0; i < rotSteps; i++) {// each angle of new strip - double[][] rotated_outpoly = M.rotate(trigos[i], stp.outps); - double[][] rotated_inpoly = M.rotate(trigos[i], stp.inps); + double[][] rotated_outpoly = MathUtil.rotate(trigos[i], stp.outps); + double[][] rotated_inpoly = MathUtil.rotate(trigos[i], stp.inps); for (double[] p : rotated_outpoly) { // each vertex of new strip - for (Strip fixed : fixs) { + for (PackedPoly fixed : packedPolys) { for (double[] v : fixed.outps) { // each vertex of each fixed strip - double[] trans = M.sub(v, p); - double[][] trans_rot_outpoly = M.move(trans, rotated_outpoly); - if (feasible(trans_rot_outpoly)) { - double[][] trans_rot_inpoly = M.move(trans, rotated_inpoly); + double[] trans = MathUtil.sub(v, p); + double[][] trans_rot_outpoly = MathUtil.move(trans, rotated_outpoly); + if (isFeasible(trans_rot_outpoly)) { + double[][] trans_rot_inpoly = MathUtil.move(trans, rotated_inpoly); Convex tmpcon = cntConvex.clone(); for (double[] trp : trans_rot_inpoly) { tmpcon.increment_hull(trp); } - double conarea = areasc * M.areaAbs(tmpcon.convex); - double[] center = M.mean(trans_rot_outpoly);// trans_rot_outpoly + double conarea = areasc * MathUtil.areaAbs(tmpcon.convex); + double[] center = MathUtil.mean(trans_rot_outpoly);// trans_rot_outpoly double area = conarea * (preferX * Math.abs(center[0]) + Math.abs(center[1])); if (min > area) { min = area; @@ -237,22 +261,25 @@ private boolean placeAnotherStrip_Dalalah(int sid) { } stp.fix_rotate_move(trigos[min_rotid], min_trans); // movs.remove(sid); - movs.set(sid, null); - placeStrip(stp); + pendingPolys.set(sid, null); + placePackedPoly(stp); cntConvex = min_con; return true; } - private boolean feasible(double[][] poly) { + /** + * Determines whether the potential polygon can be placed. + */ + private boolean isFeasible(double[][] poly) { for (double[] p : poly) { if (p[0] < 0 || p[0] > width || p[1] < 0 || p[1] > height) { // out of bounds -- infeasible! return false; } } - final double[] bb = M.boundBox(poly); + final double[] bb = MathUtil.boundBox(poly); - for (Strip fixed : fixs) { + for (PackedPoly fixed : packedPolys) { if (overlapFast(poly, bb, fixed)) { return false; } @@ -264,11 +291,11 @@ private boolean feasible(double[][] poly) { * @deprecated */ private static final boolean overlap(final double[][] poly1, final double[][] poly2) { - if (!M.intersect_boundBox(poly1, poly2)) { + if (!MathUtil.intersect_boundBox(poly1, poly2)) { return false; } double[][] sml, big; - if (M.areaAbs(poly1) < M.areaAbs(poly2)) { + if (MathUtil.areaAbs(poly1) < MathUtil.areaAbs(poly2)) { sml = poly1; big = poly2; } else { @@ -276,13 +303,13 @@ private static final boolean overlap(final double[][] poly1, final double[][] po big = poly1; } for (double[] p : sml) { - if (M.inside(p, big)) { + if (MathUtil.inside(p, big)) { return true; } } for (int i = 0; i < sml.length; i++) { for (int j = 0; j < big.length; j++) { - if (M.intersection(sml[i], sml[(i + 1) % sml.length], big[j], big[(j + 1) % big.length])) { + if (MathUtil.intersection(sml[i], sml[(i + 1) % sml.length], big[j], big[(j + 1) % big.length])) { return true; } } @@ -291,7 +318,7 @@ private static final boolean overlap(final double[][] poly1, final double[][] po } /** - * Determines whether poly overlaps with strip. + * Determines whether potential poly overlaps with placed poly. * * @param poly1 vertices of poly 1 * @param poly1BB bounding box of poly 1 @@ -299,10 +326,10 @@ private static final boolean overlap(final double[][] poly1, final double[][] po * @param poly2 vertices of poly 2 * @return */ - private static final boolean overlapFast(final double[][] poly1, final double[] poly1BB, final Strip strip) { + private static final boolean overlapFast(final double[][] poly1, final double[] poly1BB, final PackedPoly strip) { // 1. test bounding boxes - if (!M.intersect_boundBoxes(poly1BB, strip.bb)) { + if (!MathUtil.intersect_boundBoxes(poly1BB, strip.bb)) { return false; } // 2. test the centroid against candidate poly @@ -311,14 +338,14 @@ private static final boolean overlapFast(final double[][] poly1, final double[] * strip against candidate) but would catch almost all occurrences (so is worth * the speed-up overall). */ - if (M.inside(strip.centroid, poly1)) { + if (MathUtil.inside(strip.centroid, poly1)) { return true; } // 3. test edge intersections for (int i = 0; i < poly1.length; i++) { for (int j = 0; j < strip.inps.length; j++) { - if (M.intersectionFast(poly1[i], poly1[(i + 1) % poly1.length], strip.inps[j], + if (MathUtil.intersectionFast(poly1[i], poly1[(i + 1) % poly1.length], strip.inps[j], strip.inps[(j + 1) % strip.inps.length])) { return true; } @@ -328,74 +355,56 @@ private static final boolean overlapFast(final double[][] poly1, final double[] } - private void placeStrip(Strip strip) { - strip.fix(); - fixs.add(strip); - } - - static Polygon toPolygon(double[][] poly) { - Coordinate[] coords = new Coordinate[poly.length + 1]; - for (int i = 0; i < coords.length - 1; i++) { - coords[i] = new Coordinate(poly[i][0], poly[i][1]); - } - coords[coords.length - 1] = new Coordinate(poly[0][0], poly[0][1]); // close - return GEOM_FACT.createPolygon(coords); - } - - static double[][] toArray(Coordinate[] coords) { - double[][] poly = new double[coords.length - 1][2]; - for (int i = 0; i < coords.length - 1; i++) { // -1, unclose - poly[i][0] = coords[i].x; - poly[i][1] = coords[i].y; - } - return poly; + private void placePackedPoly(PackedPoly strip) { + strip.place(); + packedPolys.add(strip); } - public double leftOverArea() { + public double getEmptyArea() { double sum = 0; - for (Strip strip : movs) { + for (PackedPoly strip : pendingPolys) { sum += strip.inarea; } return sum; } - public int[] getStripIds() { - int size = fixs.size(); + public int[] getPackingIds() { + int size = packedPolys.size(); int[] ids = new int[size]; for (int i = 0; i < size; i++) { - ids[i] = fixs.get(i).id; + ids[i] = packedPolys.get(i).id; } return ids; } - public double[][] getStripRotations() { - int size = fixs.size(); + public double[][] getPackingRotations() { + int size = packedPolys.size(); double[][] rots = new double[size][]; for (int i = 0; i < size; i++) { - rots[i] = fixs.get(i).trigo; + rots[i] = packedPolys.get(i).trigo; } return rots; } - public double[][] getStripPositions() { - int size = fixs.size(); + public double[][] getPackingPositions() { + int size = packedPolys.size(); double[][] ps = new double[size][]; for (int i = 0; i < size; i++) { - ps[i] = fixs.get(i).position; + ps[i] = packedPolys.get(i).position; } return ps; } @Override - public Pack clone() { - Pack np = new Pack(trigos, rotSteps, width, height, preferX); - np.movs = movs; + public DalsooPack clone() { + DalsooPack np = new DalsooPack(trigos, rotSteps, width, height, preferX); + np.pendingPolys = pendingPolys; np.cntConvex = cntConvex; return np; } public boolean isEmpty() { - return movs.isEmpty(); + return pendingPolys.isEmpty(); } } diff --git a/src/main/java/whitegreen/dalsoo/TestMultiSheets1b.java b/src/main/java/whitegreen/dalsoo/DemoApplet.java similarity index 88% rename from src/main/java/whitegreen/dalsoo/TestMultiSheets1b.java rename to src/main/java/whitegreen/dalsoo/DemoApplet.java index 673b0e2..cb6d644 100644 --- a/src/main/java/whitegreen/dalsoo/TestMultiSheets1b.java +++ b/src/main/java/whitegreen/dalsoo/DemoApplet.java @@ -45,31 +45,31 @@ * 3. Output * */ -public class TestMultiSheets1b extends PApplet { +public class DemoApplet extends PApplet { // https://github.com/whitegreen/Dalsoo-Bin-Packing public static void main(String[] args) { System.setProperty("sun.java2d.uiScale", "1.0"); System.setProperty("prism.allowhidpi", "false"); - PApplet.main(TestMultiSheets1b.class); + PApplet.main(DemoApplet.class); } private Random ran; // input private double[][][] randompolys; // the input polygons - private final float WID = 2400 * 2; // width of the standard rectangular sheet - private final float HEI = 1200 * 2; - private final double margin = 4.0; + private final float WID = 2400 * 4; // width of the standard rectangular sheet + private final float HEI = 1200 * 4; + private final double margin = 3.0; // when 0, polys will pack horizontally, 1= vertically - private final double preferX = .666; // 0.501 or 1 + private final double preferX = 0; // 0.501 or 1 // parameters - private final double segment_max_length = 400.0; // 250,400,800, use to break long edges if necessary, relative to the scale + private final double segment_max_length = 4000.0; // 250,400,800, use to break long edges if necessary, relative to the scale // of the polgyons private final int rotSteps = 10; // 18,24,36,48, rotation steps private boolean useAbey = true; - private ArrayList packs = new ArrayList<>(); + private ArrayList packs = new ArrayList<>(); // true: rotation steps depend on polygons, R. P. Abeysooriya 2018 // false: rotation steps are a prior, D. Dalalah, 2014 @@ -90,16 +90,16 @@ public void setup() { long t0 = System.currentTimeMillis(); int seed = 4346; ran = new Random(0); - randompolys = randomPolygons(350);// prepare the input polygons + randompolys = randomPolygons(320);// prepare the input polygons Double segment_len = useAbey ? null : segment_max_length; - Pack pack = new Pack(randompolys, margin, segment_len, rotSteps, WID, HEI, preferX); - pack.packOneSheet(useAbey); + DalsooPack pack = new DalsooPack(randompolys, margin, segment_len, rotSteps, WID, HEI, preferX); + pack.packOneBin(useAbey, false); packs.add(pack); while (!packs.get(packs.size() - 1).isEmpty()) { pack = packs.get(packs.size() - 1).clone(); - pack.packOneSheet(useAbey); + pack.packOneBin(useAbey, false); packs.add(pack); } @@ -123,8 +123,8 @@ private void report() { result_cos_sin = new double[randompolys.length][]; result_position = new double[randompolys.length][]; for (int i = 0; i < packs.size(); i++) { - Pack pack = packs.get(i); - for (Strip strip : pack.fixs) { + DalsooPack pack = packs.get(i); + for (PackedPoly strip : pack.packedPolys) { result_pack_id[strip.id] = i; result_cos_sin[strip.id] = strip.trigo; result_position[strip.id] = strip.position; @@ -155,7 +155,7 @@ private double[][][] randomPolygons(int num) { double dx = ran.nextDouble() * 1000; double dy = ran.nextDouble() * 1000; for (double[] p : poly) { - M._add(p, new double[] { dx, dy }); + MathUtil._add(p, new double[] { dx, dy }); } } return polys; @@ -168,7 +168,7 @@ private double[][] shake(double s, double[][] ps) { double cos = FastMath.cos(theta); double sin = FastMath.sin(theta); for (int i = 0; i < ps.length; i++) { - double[] p = M.scale(sng, ps[i]); + double[] p = MathUtil.scale(sng, ps[i]); p[0] += (ran.nextDouble() - 0.5) * 0.25 * s; p[1] += (ran.nextDouble() - 0.5) * 0.25 * s; double x = cos * p[0] + sin * p[1]; @@ -208,13 +208,13 @@ public void draw() { if (id >= packs.size()) { return; } - Pack pack = packs.get(id); + DalsooPack pack = packs.get(id); pushMatrix(); translate(j * (sc * WID), i * (sc * height)); // (j * 270, i * 150 noFill(); rect(0, 0, sc * WID, sc * HEI); fill(0, 255, 0); - for (Strip strip : pack.fixs) { + for (PackedPoly strip : pack.packedPolys) { draw(strip.inps, sc); } popMatrix(); diff --git a/src/main/java/whitegreen/dalsoo/M.java b/src/main/java/whitegreen/dalsoo/MathUtil.java similarity index 91% rename from src/main/java/whitegreen/dalsoo/M.java rename to src/main/java/whitegreen/dalsoo/MathUtil.java index 132126e..f5a71db 100644 --- a/src/main/java/whitegreen/dalsoo/M.java +++ b/src/main/java/whitegreen/dalsoo/MathUtil.java @@ -2,6 +2,9 @@ import java.util.ArrayList; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Polygon; import org.locationtech.jts.operation.buffer.BufferOp; import org.locationtech.jts.operation.buffer.BufferParameters; @@ -9,7 +12,7 @@ //Hao Hua, Southeast University, whitegreen@163.com -public final class M { +public final class MathUtil { private static final double denominator_lim = 1e-10; private static final BufferParameters bp = new BufferParameters(8, BufferParameters.CAP_FLAT, BufferParameters.JOIN_MITRE, @@ -73,8 +76,8 @@ public static double dist(double[] a, double[] b) { } public static double triArea(double[] a, double[] b) { - double[] cross = M.cross(a, b); - return M.mag(cross) * 0.5; + double[] cross = MathUtil.cross(a, b); + return MathUtil.mag(cross) * 0.5; } public static double mag(double[] a) { @@ -339,7 +342,7 @@ public static double[][] scale(double[][] a, double s) { public static double[][] mul(double[][] m, int iteration) { double[][] a = m; for (int i = 0; i < iteration - 1; i++) { - a = M.mul(a, m); + a = MathUtil.mul(a, m); } return a; } @@ -458,11 +461,31 @@ public static double[][] buffer(final double[][] poly, final double distance) { * Fall back to JTS buffer if lineIntersect returns null for any intersection * (occurs on rather concave shapes). */ - return Pack.toArray(BufferOp.bufferOp(Pack.toPolygon(poly), distance, bp).getCoordinates()); + return toArray(BufferOp.bufferOp(toPolygon(poly), distance, bp).getCoordinates()); } } return ps; } + + private static final GeometryFactory GEOM_FACT = new GeometryFactory(); + + private static Polygon toPolygon(double[][] poly) { + Coordinate[] coords = new Coordinate[poly.length + 1]; + for (int i = 0; i < coords.length - 1; i++) { + coords[i] = new Coordinate(poly[i][0], poly[i][1]); + } + coords[coords.length - 1] = new Coordinate(poly[0][0], poly[0][1]); // close + return GEOM_FACT.createPolygon(coords); + } + + private static double[][] toArray(Coordinate[] coords) { + double[][] poly = new double[coords.length - 1][2]; + for (int i = 0; i < coords.length - 1; i++) { // -1, unclose + poly[i][0] = coords[i].x; + poly[i][1] = coords[i].y; + } + return poly; + } public static double[] point_Project_Plane(double[] q, double[] p, double[] n) { // q is the point double d = -dot(p, n); @@ -623,10 +646,10 @@ public static double[] rotateZ(double theta, double[] p) { public static double[] rotate_Rodriguez(double[] v, double theta, double[] dir) { double cos = FastMath.cos(theta); double sin = FastMath.sin(theta); - double[] v1 = M.scale(cos, v); - double[] v2 = M.scale((1 - cos) * dot(v, dir), dir); - double[] v3 = M.scale(sin, cross(dir, v)); - return M.add(v1, M.add(v2, v3)); + double[] v1 = MathUtil.scale(cos, v); + double[] v2 = MathUtil.scale((1 - cos) * dot(v, dir), dir); + double[] v3 = MathUtil.scale(sin, cross(dir, v)); + return MathUtil.add(v1, MathUtil.add(v2, v3)); } public static boolean inside(double[] p, double[][] vs) { @@ -692,8 +715,8 @@ public static double triangleArea(final double[] a, final double[] b, final doub public static double[][] exp(double[][] m, int iteration) { double[][] re = I(m.length); for (int i = 0; i < iteration; i++) { - double[][] tmp = M.scale(mul(m, i + 1), 1.0 / powerInt(i + 1)); - re = M.add(re, tmp); + double[][] tmp = MathUtil.scale(mul(m, i + 1), 1.0 / powerInt(i + 1)); + re = MathUtil.add(re, tmp); } return re; } @@ -704,8 +727,8 @@ public static double[][] ln(double[][] rotate_matrix) {// group to algebra tr += rotate_matrix[i][i]; } double theta = FastMath.acos(0.5 * (tr - 1)); - double[][] t = M.sub(rotate_matrix, M.transpose(rotate_matrix)); - double[][] re = M.scale(t, 0.5 * theta / FastMath.sin(theta)); // sin(0)************* + double[][] t = MathUtil.sub(rotate_matrix, MathUtil.transpose(rotate_matrix)); + double[][] re = MathUtil.scale(t, 0.5 * theta / FastMath.sin(theta)); // sin(0)************* return re; } @@ -720,12 +743,12 @@ public static double[][] algebra_matrix(double[] ele) { } public static double[][] exp(double[] ele) { // algebra to group - double sq_theta = M.mag_sq(ele); + double sq_theta = MathUtil.mag_sq(ele); double theta = FastMath.sqrt(sq_theta); double[][] ele_mat = algebra_matrix(ele); double[][] re = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }; - re = M.add(re, M.scale(ele_mat, FastMath.sin(theta) / theta)); - return M.add(re, M.scale(M.mul(ele_mat, ele_mat), (1 - FastMath.cos(theta)) / sq_theta)); + re = MathUtil.add(re, MathUtil.scale(ele_mat, FastMath.sin(theta) / theta)); + return MathUtil.add(re, MathUtil.scale(MathUtil.mul(ele_mat, ele_mat), (1 - FastMath.cos(theta)) / sq_theta)); } } diff --git a/src/main/java/whitegreen/dalsoo/Strip.java b/src/main/java/whitegreen/dalsoo/PackedPoly.java similarity index 68% rename from src/main/java/whitegreen/dalsoo/Strip.java rename to src/main/java/whitegreen/dalsoo/PackedPoly.java index 5c147c4..2f541ce 100644 --- a/src/main/java/whitegreen/dalsoo/Strip.java +++ b/src/main/java/whitegreen/dalsoo/PackedPoly.java @@ -7,9 +7,7 @@ * @author Hao Hua, Southeast University, whitegreen@163.com * */ -public class Strip implements Comparable { - -// private static final +public class PackedPoly implements Comparable { public double[][] outps; // offset & add edge points , as referent point of placement, clock-wise public final double[][] inps; // original polygon, for 1. convex, 2. intersection @@ -18,36 +16,36 @@ public class Strip implements Comparable { public double[] position; public final int id; - public Strip(int id, double[][] original_poly, double spacing, Double segment_max_length) { + PackedPoly(int id, double[][] original_poly, double spacing, Double segmentMaxLength) { this.id = id; if (spacing < 0) { throw new IllegalArgumentException("spacing must be >=0"); } - double area = M.area(original_poly); + double area = MathUtil.area(original_poly); if (0 < area) { - inps = M.clone(original_poly); + inps = MathUtil.clone(original_poly); } else { inps = new double[original_poly.length][]; for (int i = 0; i < inps.length; i++) { inps[i] = original_poly[inps.length - 1 - i].clone(); } } - + inarea = Math.abs(area); - outps = M.buffer(inps, spacing); // clockwise + outps = MathUtil.buffer(inps, spacing); // clockwise - if (segment_max_length != null) { + if (segmentMaxLength != null && segmentMaxLength > 0) { ArrayList list = new ArrayList<>(); for (int i = 0; i < outps.length; i++) { double[] pa = outps[i]; double[] pb = outps[(i + 1) % outps.length]; list.add(pa); - double dis = M.dist(pa, pb); - if (segment_max_length < dis) { - int num = 1 + (int) (dis / segment_max_length); + double dis = MathUtil.dist(pa, pb); + if (segmentMaxLength < dis) { + int num = 1 + (int) (dis / segmentMaxLength); for (int j = 1; j < num; j++) { double s = (double) j / num; - list.add(M.between(s, pa, pb)); + list.add(MathUtil.between(s, pa, pb)); } } } // for @@ -58,7 +56,7 @@ public Strip(int id, double[][] original_poly, double spacing, Double segment_ma } // if } - public void fix_rotate_move(double[] cossin, double[] dv) { // finalize + void fix_rotate_move(double[] cossin, double[] dv) { // finalize trigo = cossin.clone(); position = dv.clone(); double cos = trigo[0]; @@ -81,16 +79,16 @@ public void fix_rotate_move(double[] cossin, double[] dv) { // finalize double[] centroid; /** - * Call when strip is fixed. Will pre-compute and save values used for overlap - * detection. + * Call when placed in the bin. Will pre-compute and save values used for + * overlap detection against future polygons. */ - public void fix() { - bb = M.boundBox(inps); - centroid = M.center(inps); + void place() { + bb = MathUtil.boundBox(inps); + centroid = MathUtil.center(inps); } @Override - public int compareTo(Strip pl) { + public int compareTo(PackedPoly pl) { return Double.compare(this.inarea, pl.inarea); } From 23b2ce941a0c8e6d856919413643b850e11cc40f Mon Sep 17 00:00:00 2001 From: Michael Carleton Date: Wed, 4 Jan 2023 13:30:56 +0000 Subject: [PATCH 5/9] move demo file to test src folder --- pom.xml | 41 ++++++++++++++++--- .../java/whitegreen/dalsoo/DemoApplet.java | 0 2 files changed, 36 insertions(+), 5 deletions(-) rename src/{main => test}/java/whitegreen/dalsoo/DemoApplet.java (100%) diff --git a/pom.xml b/pom.xml index 115d095..57b512f 100644 --- a/pom.xml +++ b/pom.xml @@ -4,6 +4,9 @@ dalsoopack 0.9-SNAPSHOT Dalsoo Bin-Packing + + UTF-8 + @@ -14,6 +17,33 @@ 1.8 + + maven-source-plugin + 3.2.1 + + + attach-sources + + jar-no-fork + + + + + + maven-javadoc-plugin + 3.4.1 + + false + + + + attach-javadocs + + jar + + + + @@ -23,11 +53,6 @@ - - com.github.micycle1 - processing3 - 3.5.4 - net.jafama jafama @@ -38,5 +63,11 @@ jts-core 1.19.0 + + com.github.micycle1 + processing3 + 3.5.4 + test + \ No newline at end of file diff --git a/src/main/java/whitegreen/dalsoo/DemoApplet.java b/src/test/java/whitegreen/dalsoo/DemoApplet.java similarity index 100% rename from src/main/java/whitegreen/dalsoo/DemoApplet.java rename to src/test/java/whitegreen/dalsoo/DemoApplet.java From bbd34d59e95bd8009d2989b50522c63ec3611f17 Mon Sep 17 00:00:00 2001 From: Michael Carleton Date: Thu, 5 Jan 2023 12:31:37 +0000 Subject: [PATCH 6/9] "ps" -> "pts" --- src/main/java/whitegreen/dalsoo/Convex.java | 2 +- .../java/whitegreen/dalsoo/DalsooPack.java | 22 +++++----- .../java/whitegreen/dalsoo/PackedPoly.java | 43 ++++++++++--------- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/main/java/whitegreen/dalsoo/Convex.java b/src/main/java/whitegreen/dalsoo/Convex.java index c2e8659..c1714d8 100644 --- a/src/main/java/whitegreen/dalsoo/Convex.java +++ b/src/main/java/whitegreen/dalsoo/Convex.java @@ -22,7 +22,7 @@ public Convex() { } public Convex(PackedPoly strip) { - double[][] points = strip.inps; + double[][] points = strip.inpts; double area = strip.inarea; if (Math.abs(area) < area_zero) { throw new RuntimeException(); diff --git a/src/main/java/whitegreen/dalsoo/DalsooPack.java b/src/main/java/whitegreen/dalsoo/DalsooPack.java index 2230ea3..9d19a9c 100644 --- a/src/main/java/whitegreen/dalsoo/DalsooPack.java +++ b/src/main/java/whitegreen/dalsoo/DalsooPack.java @@ -124,7 +124,7 @@ private void packFirstPoly() { int sid = pendingPolys.size() - 1; // ***************************************** last one PackedPoly first = pendingPolys.get(sid); for (int i = 0; i < rotSteps; i++) { - double[][] tp = MathUtil.rotate(trigos[i], first.outps); + double[][] tp = MathUtil.rotate(trigos[i], first.outpts); double[] bd = MathUtil.boundBox(tp); // minx, maxx, miny, maxy if (bd[1] - bd[0] > width || bd[3] - bd[2] > height) { continue; @@ -138,7 +138,7 @@ private void packFirstPoly() { rotid = i; } } - double[][] tp = MathUtil.rotate(trigos[rotid], first.outps); + double[][] tp = MathUtil.rotate(trigos[rotid], first.outpts); double[] bd = MathUtil.boundBox(tp); first.fix_rotate_move(trigos[rotid], new double[] { -bd[0], -bd[2] }); pendingPolys.remove(sid); @@ -152,7 +152,7 @@ private boolean packPolyAbey(int sid) { double[] min_cossin = null; double[] min_trans = null; Convex min_con = null; - double[][] opl = stp.outps; + double[][] opl = stp.outpts; for (int i = 0; i < opl.length; i++) { // each vertex of new strip double[] p = opl[i]; double[] d0 = MathUtil.sub(opl[(i - 1 + opl.length) % opl.length], p); @@ -165,7 +165,7 @@ private boolean packPolyAbey(int sid) { double sb2 = d2[1] / mag2; for (PackedPoly fixed : packedPolys) { - double[][] fopl = fixed.outps; + double[][] fopl = fixed.outpts; for (int j = 0; j < fopl.length; j++) { // each vertex of each fixed strip double[] v = fopl[j]; double[] t0 = MathUtil.sub(fopl[(j - 1 + fopl.length) % fopl.length], v); @@ -189,7 +189,7 @@ private boolean packPolyAbey(int sid) { double[] trans = MathUtil.sub(v, rot_opl[i]); // ***************** double[][] trans_rot_outpoly = MathUtil.move(trans, rot_opl); if (isFeasible(trans_rot_outpoly)) { - double[][] trans_rot_inpoly = MathUtil.move(trans, MathUtil.rotate(cossin, stp.inps)); + double[][] trans_rot_inpoly = MathUtil.move(trans, MathUtil.rotate(cossin, stp.inpts)); Convex tmpcon = cntConvex.clone(); for (double[] trp : trans_rot_inpoly) { tmpcon.increment_hull(trp); @@ -227,12 +227,12 @@ private boolean packPolyDalalah(int sid) { double[] min_trans = null; Convex min_con = null; for (int i = 0; i < rotSteps; i++) {// each angle of new strip - double[][] rotated_outpoly = MathUtil.rotate(trigos[i], stp.outps); - double[][] rotated_inpoly = MathUtil.rotate(trigos[i], stp.inps); + double[][] rotated_outpoly = MathUtil.rotate(trigos[i], stp.outpts); + double[][] rotated_inpoly = MathUtil.rotate(trigos[i], stp.inpts); for (double[] p : rotated_outpoly) { // each vertex of new strip for (PackedPoly fixed : packedPolys) { - for (double[] v : fixed.outps) { // each vertex of each fixed strip + for (double[] v : fixed.outpts) { // each vertex of each fixed strip double[] trans = MathUtil.sub(v, p); double[][] trans_rot_outpoly = MathUtil.move(trans, rotated_outpoly); if (isFeasible(trans_rot_outpoly)) { @@ -344,9 +344,9 @@ private static final boolean overlapFast(final double[][] poly1, final double[] // 3. test edge intersections for (int i = 0; i < poly1.length; i++) { - for (int j = 0; j < strip.inps.length; j++) { - if (MathUtil.intersectionFast(poly1[i], poly1[(i + 1) % poly1.length], strip.inps[j], - strip.inps[(j + 1) % strip.inps.length])) { + for (int j = 0; j < strip.inpts.length; j++) { + if (MathUtil.intersectionFast(poly1[i], poly1[(i + 1) % poly1.length], strip.inpts[j], + strip.inpts[(j + 1) % strip.inpts.length])) { return true; } } diff --git a/src/main/java/whitegreen/dalsoo/PackedPoly.java b/src/main/java/whitegreen/dalsoo/PackedPoly.java index 2f541ce..2648092 100644 --- a/src/main/java/whitegreen/dalsoo/PackedPoly.java +++ b/src/main/java/whitegreen/dalsoo/PackedPoly.java @@ -9,8 +9,9 @@ */ public class PackedPoly implements Comparable { - public double[][] outps; // offset & add edge points , as referent point of placement, clock-wise - public final double[][] inps; // original polygon, for 1. convex, 2. intersection + public double[][] outpts; // offset & add edge points , as referent point of placement, clock-wise + /** Coordinates of this poly's original polygon */ + public final double[][] inpts; // original polygon, for 1. convex, 2. intersection public final double inarea; public double[] trigo; // cos & sin public double[] position; @@ -23,22 +24,22 @@ public class PackedPoly implements Comparable { } double area = MathUtil.area(original_poly); if (0 < area) { - inps = MathUtil.clone(original_poly); + inpts = MathUtil.clone(original_poly); } else { - inps = new double[original_poly.length][]; - for (int i = 0; i < inps.length; i++) { - inps[i] = original_poly[inps.length - 1 - i].clone(); + inpts = new double[original_poly.length][]; + for (int i = 0; i < inpts.length; i++) { + inpts[i] = original_poly[inpts.length - 1 - i].clone(); } } inarea = Math.abs(area); - outps = MathUtil.buffer(inps, spacing); // clockwise + outpts = MathUtil.buffer(inpts, spacing); // clockwise if (segmentMaxLength != null && segmentMaxLength > 0) { ArrayList list = new ArrayList<>(); - for (int i = 0; i < outps.length; i++) { - double[] pa = outps[i]; - double[] pb = outps[(i + 1) % outps.length]; + for (int i = 0; i < outpts.length; i++) { + double[] pa = outpts[i]; + double[] pb = outpts[(i + 1) % outpts.length]; list.add(pa); double dis = MathUtil.dist(pa, pb); if (segmentMaxLength < dis) { @@ -49,9 +50,9 @@ public class PackedPoly implements Comparable { } } } // for - outps = new double[list.size()][]; - for (int i = 0; i < outps.length; i++) { - outps[i] = list.get(i); + outpts = new double[list.size()][]; + for (int i = 0; i < outpts.length; i++) { + outpts[i] = list.get(i); } } // if } @@ -61,17 +62,17 @@ void fix_rotate_move(double[] cossin, double[] dv) { // finalize position = dv.clone(); double cos = trigo[0]; double sin = trigo[1]; - for (int i = 0; i < inps.length; i++) { - double[] p = inps[i]; + for (int i = 0; i < inpts.length; i++) { + double[] p = inpts[i]; double x = cos * p[0] - sin * p[1]; double y = sin * p[0] + cos * p[1]; - inps[i] = new double[] { dv[0] + x, dv[1] + y }; + inpts[i] = new double[] { dv[0] + x, dv[1] + y }; } - for (int i = 0; i < outps.length; i++) { - double[] p = outps[i]; + for (int i = 0; i < outpts.length; i++) { + double[] p = outpts[i]; double x = cos * p[0] - sin * p[1]; double y = sin * p[0] + cos * p[1]; - outps[i] = new double[] { dv[0] + x, dv[1] + y }; + outpts[i] = new double[] { dv[0] + x, dv[1] + y }; } } @@ -83,8 +84,8 @@ void fix_rotate_move(double[] cossin, double[] dv) { // finalize * overlap detection against future polygons. */ void place() { - bb = MathUtil.boundBox(inps); - centroid = MathUtil.center(inps); + bb = MathUtil.boundBox(inpts); + centroid = MathUtil.center(inpts); } @Override From e42325cda1105c9a02b7061285cbf9f5e8b6d59b Mon Sep 17 00:00:00 2001 From: Michael Carleton Date: Sat, 7 Jan 2023 15:18:52 +0000 Subject: [PATCH 7/9] update applet --- .../java/whitegreen/dalsoo/DemoApplet.java | 80 +++++++++---------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/test/java/whitegreen/dalsoo/DemoApplet.java b/src/test/java/whitegreen/dalsoo/DemoApplet.java index cb6d644..ec72e5b 100644 --- a/src/test/java/whitegreen/dalsoo/DemoApplet.java +++ b/src/test/java/whitegreen/dalsoo/DemoApplet.java @@ -58,8 +58,8 @@ public static void main(String[] args) { // input private double[][][] randompolys; // the input polygons - private final float WID = 2400 * 4; // width of the standard rectangular sheet - private final float HEI = 1200 * 4; + private final float WID = 2400 * 4 + 500; // width of the standard rectangular sheet + private final float HEI = 1200 * 4 + 250; private final double margin = 3.0; // when 0, polys will pack horizontally, 1= vertically private final double preferX = 0; // 0.501 or 1 @@ -67,8 +67,8 @@ public static void main(String[] args) { // parameters private final double segment_max_length = 4000.0; // 250,400,800, use to break long edges if necessary, relative to the scale // of the polgyons - private final int rotSteps = 10; // 18,24,36,48, rotation steps - private boolean useAbey = true; + private final int rotSteps = 48; // 18,24,36,48, rotation steps + private boolean useAbey = !true; private ArrayList packs = new ArrayList<>(); // true: rotation steps depend on polygons, R. P. Abeysooriya 2018 // false: rotation steps are a prior, D. Dalalah, 2014 @@ -90,16 +90,16 @@ public void setup() { long t0 = System.currentTimeMillis(); int seed = 4346; ran = new Random(0); - randompolys = randomPolygons(320);// prepare the input polygons + randompolys = randomPolygons(200);// prepare the input polygons Double segment_len = useAbey ? null : segment_max_length; DalsooPack pack = new DalsooPack(randompolys, margin, segment_len, rotSteps, WID, HEI, preferX); - pack.packOneBin(useAbey, false); + pack.packOneBin(useAbey, !true); packs.add(pack); while (!packs.get(packs.size() - 1).isEmpty()) { pack = packs.get(packs.size() - 1).clone(); - pack.packOneBin(useAbey, false); + pack.packOneBin(useAbey, !false); packs.add(pack); } @@ -186,40 +186,40 @@ public void draw() { float sc = 0.15f; // display method 1 -// for (int i = 0; i < randompolys.length; i++) { -// int pack_id = result_pack_id[i]; -// pushMatrix(); -//// translate((pack_id % 3) * 380, (pack_id / 3) * 200); -// -// noFill(); -// rect(0, 0, sc * WID, sc * HEI); -// fill(0, 255, 0); -// double[][] poly = randompolys[i]; -// poly = M.rotate(result_cos_sin[i], poly); -// poly = M.move(result_position[i], poly); -// draw(poly, sc); -// -// popMatrix(); -// } -// display method 2 - for (int i = 0; i < 5; i++) { - for (int j = 0; j < 3; j++) { - int id = i * 3 + j; - if (id >= packs.size()) { - return; - } - DalsooPack pack = packs.get(id); - pushMatrix(); - translate(j * (sc * WID), i * (sc * height)); // (j * 270, i * 150 - noFill(); - rect(0, 0, sc * WID, sc * HEI); - fill(0, 255, 0); - for (PackedPoly strip : pack.packedPolys) { - draw(strip.inps, sc); - } - popMatrix(); - } + for (int i = 0; i < randompolys.length; i++) { + int pack_id = result_pack_id[i]; + pushMatrix(); + translate((pack_id % 3) * 380, (pack_id / 3) * 200); + + noFill(); + rect(0, 0, sc * WID, sc * HEI); + fill(0, 255, 0); + double[][] poly = randompolys[i]; + poly = MathUtil.rotate(result_cos_sin[i], poly); + poly = MathUtil.move(result_position[i], poly); + draw(poly, sc); + + popMatrix(); } +// display method 2 +// for (int i = 0; i < 5; i++) { +// for (int j = 0; j < 3; j++) { +// int id = i * 3 + j; +// if (id >= packs.size()) { +// return; +// } +// DalsooPack pack = packs.get(id); +// pushMatrix(); +// translate(j * (sc * WID), i * (sc * height)); // (j * 270, i * 150 +// noFill(); +// rect(0, 0, sc * WID, sc * HEI); +// fill(0, 255, 0); +// for (PackedPoly strip : pack.packedPolys) { +// draw(strip.inps, sc); +// } +// popMatrix(); +// } +// } } From 2b898deed79becc9b42933c717f0311a4373432f Mon Sep 17 00:00:00 2001 From: Michael Carleton Date: Sat, 4 Feb 2023 18:38:02 +0000 Subject: [PATCH 8/9] assorted refactor --- src/main/java/whitegreen/dalsoo/Convex.java | 49 ++++--- .../java/whitegreen/dalsoo/DalsooPack.java | 136 ++++++++++-------- src/main/java/whitegreen/dalsoo/MathUtil.java | 17 ++- .../java/whitegreen/dalsoo/PackedPoly.java | 12 +- .../java/whitegreen/dalsoo/DemoApplet.java | 95 ++++++------ 5 files changed, 167 insertions(+), 142 deletions(-) diff --git a/src/main/java/whitegreen/dalsoo/Convex.java b/src/main/java/whitegreen/dalsoo/Convex.java index c1714d8..4a08a7d 100644 --- a/src/main/java/whitegreen/dalsoo/Convex.java +++ b/src/main/java/whitegreen/dalsoo/Convex.java @@ -1,30 +1,24 @@ package whitegreen.dalsoo; import java.util.ArrayList; +import java.util.List; -//Hao Hua, Southeast University, whitegreen@163.com - +/** + * @author Hao Hua, Southeast University, whitegreen@163.com + */ class Convex { - public ArrayList convex; // convex is clockwise - private static final double area_zero = 1E-6; // for mm + private static final double ZERO_AREA = 1E-6; // for mm + + List convex; // convex is clockwise - @Override - public Convex clone() { - ArrayList list = new ArrayList<>(); - list.addAll(convex); - Convex con = new Convex(); - con.convex = list; - return con; + Convex() { } - public Convex() { - } - public Convex(PackedPoly strip) { double[][] points = strip.inpts; double area = strip.inarea; - if (Math.abs(area) < area_zero) { + if (Math.abs(area) < ZERO_AREA) { throw new RuntimeException(); } convex = new ArrayList<>(); @@ -42,6 +36,15 @@ public Convex(PackedPoly strip) { } } + @Override + public Convex clone() { + List list = new ArrayList<>(); + list.addAll(convex); + Convex con = new Convex(); + con.convex = list; + return con; + } + public void increment_hull(double[] np) { // convex is clockwise if (MathUtil.inside(np, convex)) { return; @@ -72,16 +75,16 @@ public void increment_hull(double[] np) { // convex is clockwise } } if (0 > T1st) { - System.out.println(np[0] + "*" + np[1]); - for (double[] p : convex) { - System.out.println("new double[]{" + p[0] + "," + p[1] + "}"); - } - for (boolean b : visible) { - System.out.println(b); - } +// System.out.println(np[0] + "*" + np[1]); +// for (double[] p : convex) { +// System.out.println("new double[]{" + p[0] + "," + p[1] + "}"); +// } +// for (boolean b : visible) { +// System.out.println(b); +// } throw new RuntimeException(); } - ArrayList list = new ArrayList<>(size); + List list = new ArrayList<>(size); list.add(convex.get(T1st)); list.add(np); for (int i = 0; i < size; i++) { diff --git a/src/main/java/whitegreen/dalsoo/DalsooPack.java b/src/main/java/whitegreen/dalsoo/DalsooPack.java index 9d19a9c..5a641ca 100644 --- a/src/main/java/whitegreen/dalsoo/DalsooPack.java +++ b/src/main/java/whitegreen/dalsoo/DalsooPack.java @@ -22,29 +22,30 @@ */ public final class DalsooPack { + private static final double AREA_SC = 1E-6; + public List packedPolys = new ArrayList<>(); List pendingPolys = new ArrayList<>(); Convex cntConvex; - + /** Sin and cos values for each rotation step. */ private final double[][] trigos; private final int rotSteps; /** bin dimensions */ - private final double width, height; - private static final double areasc = 1E-6; + private final double binWidth, binHeight; private final double preferX; DalsooPack(double[][] trigos, int rotSteps, double width, double height, double preferX) { this.trigos = trigos; this.rotSteps = rotSteps; - this.width = width; - this.height = height; + this.binWidth = width; + this.binHeight = height; this.preferX = preferX; } /** - * Creates an packing. Call {@link #packOneBin(boolean, boolean)} to start - * packing. + * Creates an packing. Call {@link #packOneBin(boolean, boolean) packOneBin()} + * to start packing. * * @param polys array of polygons [p1, p2]; for each polygon, its * vertices are expressed in [x, y] coordinate pairs: @@ -71,8 +72,8 @@ public DalsooPack(double[][][] polys, double spacing, Double segment_max_length, } for (int i = 0; i < polys.length; i++) { double[][] poly = polys[i]; - PackedPoly strip = new PackedPoly(i, poly, spacing, segment_max_length); - pendingPolys.add(strip); + PackedPoly p = new PackedPoly(i, poly, spacing, segment_max_length); + pendingPolys.add(p); } this.preferX = hSkew; @@ -82,23 +83,37 @@ public DalsooPack(double[][][] polys, double spacing, Double segment_max_length, double theta = i * 2 * PI / rotSteps; trigos[i] = new double[] { FastMath.cos(theta), FastMath.sin(theta) }; } - this.width = width; - this.height = height; + this.binWidth = width; + this.binHeight = height; } /** * Packs all polygons, possibly across multiple bins. * - * @param abey + * @param abey whether to use + * @return */ - public void packAll(boolean abey) { - + public List packAll(boolean abey) { + /* + * The pack essentially forks itself with the remaining polygons to model new + * bins. + */ + List packedBins = new ArrayList<>(); + DalsooPack pack = this; + do { + pack.packOneBin(abey, false); + packedBins.add(pack); + pack = pack.clone(); + } while (!packedBins.get(packedBins.size() - 1).isEmpty()); + + return packedBins; } /** * * @param abey - * @param largestFirst sort the polygons by area and pack + * @param largestFirst whether to sort the polygons by area (largest first) + * before packing */ public void packOneBin(boolean abey, boolean largestFirst) { if (largestFirst) { @@ -114,22 +129,22 @@ public void packOneBin(boolean abey, boolean largestFirst) { packPolyDalalah(size - 1 - i); } } - + pendingPolys.removeIf(Objects::isNull); } private void packFirstPoly() { int rotid = 0; - double minArea = 1000000000; + double minArea = Double.MAX_VALUE; int sid = pendingPolys.size() - 1; // ***************************************** last one PackedPoly first = pendingPolys.get(sid); for (int i = 0; i < rotSteps; i++) { double[][] tp = MathUtil.rotate(trigos[i], first.outpts); double[] bd = MathUtil.boundBox(tp); // minx, maxx, miny, maxy - if (bd[1] - bd[0] > width || bd[3] - bd[2] > height) { + if (bd[1] - bd[0] > binWidth || bd[3] - bd[2] > binHeight) { continue; } - double area = areasc * (bd[1] - bd[0]) * (bd[3] - bd[2]); + double area = AREA_SC * (bd[1] - bd[0]) * (bd[3] - bd[2]); double[] center = MathUtil.mean(tp); double len = preferX * (center[0] - bd[0]) + (1 - preferX) * (center[1] - bd[2]); area *= len; @@ -147,13 +162,13 @@ private void packFirstPoly() { } private boolean packPolyAbey(int sid) { - PackedPoly stp = pendingPolys.get(sid); - double min = 1000000000; + PackedPoly poly = pendingPolys.get(sid); + double minArea = Double.MAX_VALUE; double[] min_cossin = null; double[] min_trans = null; Convex min_con = null; - double[][] opl = stp.outpts; - for (int i = 0; i < opl.length; i++) { // each vertex of new strip + double[][] opl = poly.outpts; + for (int i = 0; i < opl.length; i++) { // each vertex of new poly double[] p = opl[i]; double[] d0 = MathUtil.sub(opl[(i - 1 + opl.length) % opl.length], p); double[] d2 = MathUtil.sub(opl[(i + 1) % opl.length], p); @@ -166,7 +181,7 @@ private boolean packPolyAbey(int sid) { for (PackedPoly fixed : packedPolys) { double[][] fopl = fixed.outpts; - for (int j = 0; j < fopl.length; j++) { // each vertex of each fixed strip + for (int j = 0; j < fopl.length; j++) { // each vertex of each fixed poly double[] v = fopl[j]; double[] t0 = MathUtil.sub(fopl[(j - 1 + fopl.length) % fopl.length], v); double[] t2 = MathUtil.sub(fopl[(j + 1) % fopl.length], v); @@ -189,18 +204,18 @@ private boolean packPolyAbey(int sid) { double[] trans = MathUtil.sub(v, rot_opl[i]); // ***************** double[][] trans_rot_outpoly = MathUtil.move(trans, rot_opl); if (isFeasible(trans_rot_outpoly)) { - double[][] trans_rot_inpoly = MathUtil.move(trans, MathUtil.rotate(cossin, stp.inpts)); + double[][] trans_rot_inpoly = MathUtil.move(trans, MathUtil.rotate(cossin, poly.inpts)); Convex tmpcon = cntConvex.clone(); for (double[] trp : trans_rot_inpoly) { tmpcon.increment_hull(trp); } - double conarea = areasc * MathUtil.areaAbs(tmpcon.convex); + double conarea = AREA_SC * MathUtil.areaAbs(tmpcon.convex); double[] center = MathUtil.mean(trans_rot_inpoly); double area; area = conarea * (preferX * Math.abs(center[0]) + (1 - preferX) * Math.abs(center[1])); - if (min > area) { - min = area; + if (minArea > area) { + minArea = area; min_cossin = cossin; min_trans = trans; min_con = tmpcon; @@ -209,30 +224,30 @@ private boolean packPolyAbey(int sid) { } // for h } } - } // for each vertex of new strip + } // for each vertex of new poly if (null == min_cossin) { // no solution, stop return false; } - stp.fix_rotate_move(min_cossin, min_trans); + poly.fix_rotate_move(min_cossin, min_trans); pendingPolys.set(sid, null); // done, mark as null - placePackedPoly(stp); + placePackedPoly(poly); cntConvex = min_con; return true; } private boolean packPolyDalalah(int sid) { PackedPoly stp = pendingPolys.get(sid); - double min = 1000000000; + double minArea = Double.MAX_VALUE; int min_rotid = -1; double[] min_trans = null; Convex min_con = null; - for (int i = 0; i < rotSteps; i++) {// each angle of new strip + for (int i = 0; i < rotSteps; i++) {// each angle of new poly double[][] rotated_outpoly = MathUtil.rotate(trigos[i], stp.outpts); double[][] rotated_inpoly = MathUtil.rotate(trigos[i], stp.inpts); - for (double[] p : rotated_outpoly) { // each vertex of new strip + for (double[] p : rotated_outpoly) { // each vertex of new poly for (PackedPoly fixed : packedPolys) { - for (double[] v : fixed.outpts) { // each vertex of each fixed strip + for (double[] v : fixed.outpts) { // each vertex of each fixed poly double[] trans = MathUtil.sub(v, p); double[][] trans_rot_outpoly = MathUtil.move(trans, rotated_outpoly); if (isFeasible(trans_rot_outpoly)) { @@ -242,11 +257,11 @@ private boolean packPolyDalalah(int sid) { tmpcon.increment_hull(trp); } - double conarea = areasc * MathUtil.areaAbs(tmpcon.convex); + double conarea = AREA_SC * MathUtil.areaAbs(tmpcon.convex); double[] center = MathUtil.mean(trans_rot_outpoly);// trans_rot_outpoly double area = conarea * (preferX * Math.abs(center[0]) + Math.abs(center[1])); - if (min > area) { - min = area; + if (minArea > area) { + minArea = area; min_rotid = i; min_trans = trans; min_con = tmpcon; @@ -254,8 +269,8 @@ private boolean packPolyDalalah(int sid) { } } } - } // for each vertex of new strip - } // for each angle of new strip + } // for each vertex of new poly + } // for each angle of new poly if (0 > min_rotid) { // no solution, stop return false; } @@ -272,7 +287,7 @@ private boolean packPolyDalalah(int sid) { */ private boolean isFeasible(double[][] poly) { for (double[] p : poly) { - if (p[0] < 0 || p[0] > width || p[1] < 0 || p[1] > height) { + if (p[0] < 0 || p[0] > binWidth || p[1] < 0 || p[1] > binHeight) { // out of bounds -- infeasible! return false; } @@ -320,33 +335,34 @@ private static final boolean overlap(final double[][] poly1, final double[][] po /** * Determines whether potential poly overlaps with placed poly. * - * @param poly1 vertices of poly 1 - * @param poly1BB bounding box of poly 1 - * @param poly1Area area of poly 1 - * @param poly2 vertices of poly 2 + * @param candidate vertices of poly 1 + * @param candidateBB bounding box of poly 1 + * @param poly1Area area of poly 1 + * @param poly2 vertices of poly 2 * @return */ - private static final boolean overlapFast(final double[][] poly1, final double[] poly1BB, final PackedPoly strip) { + private static final boolean overlapFast(final double[][] candidate, final double[] candidateBB, + final PackedPoly placedPoly) { // 1. test bounding boxes - if (!MathUtil.intersect_boundBoxes(poly1BB, strip.bb)) { + if (!MathUtil.intersect_boundBoxes(candidateBB, placedPoly.bb)) { return false; } // 2. test the centroid against candidate poly /* * NOTE this isn't completely robust (a robust method would test every point of - * strip against candidate) but would catch almost all occurrences (so is worth - * the speed-up overall). + * placed poly against candidate) but will catch almost all occurrences (so is + * worth the speed-up overall). */ - if (MathUtil.inside(strip.centroid, poly1)) { + if (MathUtil.inside(placedPoly.centroid, candidate)) { return true; } // 3. test edge intersections - for (int i = 0; i < poly1.length; i++) { - for (int j = 0; j < strip.inpts.length; j++) { - if (MathUtil.intersectionFast(poly1[i], poly1[(i + 1) % poly1.length], strip.inpts[j], - strip.inpts[(j + 1) % strip.inpts.length])) { + for (int i = 0; i < candidate.length; i++) { + for (int j = 0; j < placedPoly.inpts.length; j++) { + if (MathUtil.intersectionFast(candidate[i], candidate[(i + 1) % candidate.length], placedPoly.inpts[j], + placedPoly.inpts[(j + 1) % placedPoly.inpts.length])) { return true; } } @@ -355,15 +371,15 @@ private static final boolean overlapFast(final double[][] poly1, final double[] } - private void placePackedPoly(PackedPoly strip) { - strip.place(); - packedPolys.add(strip); + private void placePackedPoly(PackedPoly poly) { + poly.place(); + packedPolys.add(poly); } public double getEmptyArea() { double sum = 0; - for (PackedPoly strip : pendingPolys) { - sum += strip.inarea; + for (PackedPoly poly : pendingPolys) { + sum += poly.inarea; } return sum; } @@ -397,7 +413,7 @@ public double[][] getPackingPositions() { @Override public DalsooPack clone() { - DalsooPack np = new DalsooPack(trigos, rotSteps, width, height, preferX); + DalsooPack np = new DalsooPack(trigos, rotSteps, binWidth, binHeight, preferX); np.pendingPolys = pendingPolys; np.cntConvex = cntConvex; return np; diff --git a/src/main/java/whitegreen/dalsoo/MathUtil.java b/src/main/java/whitegreen/dalsoo/MathUtil.java index f5a71db..38fb116 100644 --- a/src/main/java/whitegreen/dalsoo/MathUtil.java +++ b/src/main/java/whitegreen/dalsoo/MathUtil.java @@ -1,6 +1,7 @@ package whitegreen.dalsoo; import java.util.ArrayList; +import java.util.List; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.GeometryFactory; @@ -10,8 +11,12 @@ import net.jafama.FastMath; -//Hao Hua, Southeast University, whitegreen@163.com - +/** + * Math utilities. + * + * @author Hao Hua, Southeast University, whitegreen@163.com + * + */ public final class MathUtil { private static final double denominator_lim = 1e-10; @@ -466,9 +471,9 @@ public static double[][] buffer(final double[][] poly, final double distance) { } return ps; } - + private static final GeometryFactory GEOM_FACT = new GeometryFactory(); - + private static Polygon toPolygon(double[][] poly) { Coordinate[] coords = new Coordinate[poly.length + 1]; for (int i = 0; i < coords.length - 1; i++) { @@ -590,7 +595,7 @@ public static double area(final double[][] ps) { // signed return 0.5f * sum; } - public static double areaAbs(ArrayList ps) { // signed + public static double areaAbs(List ps) { // signed double sum = 0; int size = ps.size(); for (int i = 0; i < size; i++) { @@ -667,7 +672,7 @@ public static boolean inside(double[] p, double[][] vs) { return oddNodes; } - public static boolean inside(double[] p, ArrayList vs) { + public static boolean inside(double[] p, List vs) { int size = vs.size(); int i, j = size - 1; boolean oddNodes = false; diff --git a/src/main/java/whitegreen/dalsoo/PackedPoly.java b/src/main/java/whitegreen/dalsoo/PackedPoly.java index 2648092..0641472 100644 --- a/src/main/java/whitegreen/dalsoo/PackedPoly.java +++ b/src/main/java/whitegreen/dalsoo/PackedPoly.java @@ -9,13 +9,16 @@ */ public class PackedPoly implements Comparable { - public double[][] outpts; // offset & add edge points , as referent point of placement, clock-wise + public double[][] outpts; // offset & add edge points, as referent point of placement, clock-wise /** Coordinates of this poly's original polygon */ public final double[][] inpts; // original polygon, for 1. convex, 2. intersection public final double inarea; public double[] trigo; // cos & sin public double[] position; public final int id; + + double[] bb; // bounding box (cached when placed) + double[] centroid; // (cached when placed) PackedPoly(int id, double[][] original_poly, double spacing, Double segmentMaxLength) { this.id = id; @@ -49,12 +52,12 @@ public class PackedPoly implements Comparable { list.add(MathUtil.between(s, pa, pb)); } } - } // for + } outpts = new double[list.size()][]; for (int i = 0; i < outpts.length; i++) { outpts[i] = list.get(i); } - } // if + } } void fix_rotate_move(double[] cossin, double[] dv) { // finalize @@ -76,9 +79,6 @@ void fix_rotate_move(double[] cossin, double[] dv) { // finalize } } - double[] bb; - double[] centroid; - /** * Call when placed in the bin. Will pre-compute and save values used for * overlap detection against future polygons. diff --git a/src/test/java/whitegreen/dalsoo/DemoApplet.java b/src/test/java/whitegreen/dalsoo/DemoApplet.java index ec72e5b..22c73f0 100644 --- a/src/test/java/whitegreen/dalsoo/DemoApplet.java +++ b/src/test/java/whitegreen/dalsoo/DemoApplet.java @@ -1,6 +1,7 @@ package whitegreen.dalsoo; import java.util.ArrayList; +import java.util.List; import java.util.Random; import net.jafama.FastMath; @@ -68,10 +69,10 @@ public static void main(String[] args) { private final double segment_max_length = 4000.0; // 250,400,800, use to break long edges if necessary, relative to the scale // of the polgyons private final int rotSteps = 48; // 18,24,36,48, rotation steps - private boolean useAbey = !true; - private ArrayList packs = new ArrayList<>(); // true: rotation steps depend on polygons, R. P. Abeysooriya 2018 // false: rotation steps are a prior, D. Dalalah, 2014 + private boolean useAbey = true; + private List packs = new ArrayList<>(); // output private int[] result_pack_id; // result_pack_id[9]=2 means the 9th polygon is on the 2nd sheet. @@ -118,6 +119,51 @@ public void setup() { System.out.println((System.currentTimeMillis() - t0) / 1000f); } + @Override + public void draw() { + background(255); + smooth(); + translate(40, 10); + float sc = 0.15f; + + // display method 1 + for (int i = 0; i < randompolys.length; i++) { + int pack_id = result_pack_id[i]; + pushMatrix(); + translate((pack_id % 3) * 380, (pack_id / 3) * 200); + + noFill(); + rect(0, 0, sc * WID, sc * HEI); + fill(0, 255, 0); + double[][] poly = randompolys[i]; + poly = MathUtil.rotate(result_cos_sin[i], poly); + poly = MathUtil.move(result_position[i], poly); + draw(poly, sc); + + popMatrix(); + } + // display method 2 + // for (int i = 0; i < 5; i++) { + // for (int j = 0; j < 3; j++) { + // int id = i * 3 + j; + // if (id >= packs.size()) { + // return; + // } + // DalsooPack pack = packs.get(id); + // pushMatrix(); + // translate(j * (sc * WID), i * (sc * height)); // (j * 270, i * 150 + // noFill(); + // rect(0, 0, sc * WID, sc * HEI); + // fill(0, 255, 0); + // for (PackedPoly strip : pack.packedPolys) { + // draw(strip.inps, sc); + // } + // popMatrix(); + // } + // } + + } + private void report() { result_pack_id = new int[randompolys.length]; result_cos_sin = new double[randompolys.length][]; @@ -178,51 +224,6 @@ private double[][] shake(double s, double[][] ps) { return arr; } - @Override - public void draw() { - background(255); - smooth(); - translate(40, 10); - float sc = 0.15f; - - // display method 1 - for (int i = 0; i < randompolys.length; i++) { - int pack_id = result_pack_id[i]; - pushMatrix(); - translate((pack_id % 3) * 380, (pack_id / 3) * 200); - - noFill(); - rect(0, 0, sc * WID, sc * HEI); - fill(0, 255, 0); - double[][] poly = randompolys[i]; - poly = MathUtil.rotate(result_cos_sin[i], poly); - poly = MathUtil.move(result_position[i], poly); - draw(poly, sc); - - popMatrix(); - } -// display method 2 -// for (int i = 0; i < 5; i++) { -// for (int j = 0; j < 3; j++) { -// int id = i * 3 + j; -// if (id >= packs.size()) { -// return; -// } -// DalsooPack pack = packs.get(id); -// pushMatrix(); -// translate(j * (sc * WID), i * (sc * height)); // (j * 270, i * 150 -// noFill(); -// rect(0, 0, sc * WID, sc * HEI); -// fill(0, 255, 0); -// for (PackedPoly strip : pack.packedPolys) { -// draw(strip.inps, sc); -// } -// popMatrix(); -// } -// } - - } - private void draw(double[][] ps, float sc) { beginShape(); for (double[] p : ps) { From 37a8fe103f07b560a15fa8349a47e671125dad7e Mon Sep 17 00:00:00 2001 From: Michael Carleton Date: Sun, 5 Feb 2023 13:25:53 +0000 Subject: [PATCH 9/9] separate bin and dalsoopack classes add getPackedPolys() method --- src/main/java/whitegreen/dalsoo/Bin.java | 403 ++++++++++++++++++ .../java/whitegreen/dalsoo/DalsooPack.java | 403 ++---------------- src/main/java/whitegreen/dalsoo/MathUtil.java | 10 +- .../java/whitegreen/dalsoo/PackedPoly.java | 22 +- .../java/whitegreen/dalsoo/DemoApplet.java | 106 +---- 5 files changed, 488 insertions(+), 456 deletions(-) create mode 100644 src/main/java/whitegreen/dalsoo/Bin.java diff --git a/src/main/java/whitegreen/dalsoo/Bin.java b/src/main/java/whitegreen/dalsoo/Bin.java new file mode 100644 index 0000000..456b115 --- /dev/null +++ b/src/main/java/whitegreen/dalsoo/Bin.java @@ -0,0 +1,403 @@ +package whitegreen.dalsoo; + +import static java.lang.Math.PI; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import net.jafama.FastMath; + +/** + * A rectangular "bin" in which shapes are packed. + * + * @author Hao Hua, Southeast University, whitegreen@163.com + * @author Michael Carleton + * + */ +public final class Bin { + + private static final double AREA_SC = 1E-6; + + private List packedPolys = new ArrayList<>(); + private List pendingPolys = new ArrayList<>(); + private Convex cntConvex; + + /** Sin and cos values for each rotation step. */ + private final double[][] trigos; + private final int rotSteps; + /** bin dimensions */ + private final double binWidth, binHeight; + private final double preferX; + + private Bin(double[][] trigos, int rotSteps, double width, double height, double preferX) { + this.trigos = trigos; + this.rotSteps = rotSteps; + this.binWidth = width; + this.binHeight = height; + this.preferX = preferX; + } + + /** + * Creates an packing. Call {@link #pack(boolean, boolean) packOneBin()} to + * start packing. + * + * @param polys array of polygons [p1, p2]; for each polygon, its + * vertices are expressed in [x, y] coordinate pairs: + * [[p1x, p1y], [p2x, p2y]...]. Polygons should be + * simple, having no holes and no self-intersection. + * @param spacing boundary spacing between packed objects. + * @param segment_max_length + * @param rotSteps number of unique rotation variants of each polygon. + * a larger number results in higher-quality packing + * but longer runtime (not used in abey packing). + * @param width width of each bin + * @param height height of each bin + * @param hSkew horizontal skew [0...1]. Determines to what extent + * shapes are packed horizontally (vs vertically). + * i.e. When =1.0, shapes will start packing against + * the y axis, and fill left-to-right (horizontal); + * When =0.0, shapes will pack from the x-axis and + * fill top-to-bottom (vertical). + */ + Bin(double[][][] polys, double spacing, Double segment_max_length, int rotSteps, double width, double height, double hSkew) { + if (0 > hSkew || 1 < hSkew) { + throw new IllegalArgumentException("skew must be between 0 and 1 (inclusive)"); + } + for (int i = 0; i < polys.length; i++) { + double[][] poly = polys[i]; + PackedPoly p = new PackedPoly(i, poly, spacing, segment_max_length); + pendingPolys.add(p); + } + this.preferX = hSkew; + + this.rotSteps = rotSteps; + trigos = new double[rotSteps][]; + for (int i = 0; i < rotSteps; i++) { + double theta = i * 2 * PI / rotSteps; + trigos[i] = new double[] { FastMath.cos(theta), FastMath.sin(theta) }; + } + this.binWidth = width; + this.binHeight = height; + } + + /** + * + * @param abey + * @param largestFirst whether to sort the polygons by area (largest first) + * before packing + */ + void pack(boolean abey, boolean largestFirst) { + if (largestFirst) { + Collections.sort(pendingPolys); // sort by area, smallest first + } + packFirstPoly(); + int size = pendingPolys.size(); + for (int i = 0; i < size; i++) { + // place next largest polygon + if (abey) { + packPolyAbey(size - 1 - i); + } else { + packPolyDalalah(size - 1 - i); + } + } + + pendingPolys.removeIf(Objects::isNull); + } + + private void packFirstPoly() { + int rotid = 0; + double minArea = Double.MAX_VALUE; + int sid = pendingPolys.size() - 1; // ***************************************** last one + PackedPoly first = pendingPolys.get(sid); + for (int i = 0; i < rotSteps; i++) { + double[][] tp = MathUtil.rotate(trigos[i], first.outpts); + double[] bd = MathUtil.boundBox(tp); // minx, maxx, miny, maxy + if (bd[1] - bd[0] > binWidth || bd[3] - bd[2] > binHeight) { + continue; + } + double area = AREA_SC * (bd[1] - bd[0]) * (bd[3] - bd[2]); + double[] center = MathUtil.mean(tp); + double len = preferX * (center[0] - bd[0]) + (1 - preferX) * (center[1] - bd[2]); + area *= len; + if (minArea > area) { + minArea = area; + rotid = i; + } + } + double[][] tp = MathUtil.rotate(trigos[rotid], first.outpts); + double[] bd = MathUtil.boundBox(tp); + first.fix_rotate_move(trigos[rotid], new double[] { -bd[0], -bd[2] }); + pendingPolys.remove(sid); + placePackedPoly(first); + cntConvex = new Convex(first); + } + + private boolean packPolyAbey(int sid) { + PackedPoly poly = pendingPolys.get(sid); + double minArea = Double.MAX_VALUE; + double[] min_cossin = null; + double[] min_trans = null; + Convex min_con = null; + double[][] opl = poly.outpts; + for (int i = 0; i < opl.length; i++) { // each vertex of new poly + double[] p = opl[i]; + double[] d0 = MathUtil.sub(opl[(i - 1 + opl.length) % opl.length], p); + double[] d2 = MathUtil.sub(opl[(i + 1) % opl.length], p); + double mag0 = MathUtil.mag(d0); + double mag2 = MathUtil.mag(d2); + double cb0 = d0[0] / mag0; + double sb0 = d0[1] / mag0; + double cb2 = d2[0] / mag2; + double sb2 = d2[1] / mag2; + + for (PackedPoly fixed : packedPolys) { + double[][] fopl = fixed.outpts; + for (int j = 0; j < fopl.length; j++) { // each vertex of each fixed poly + double[] v = fopl[j]; + double[] t0 = MathUtil.sub(fopl[(j - 1 + fopl.length) % fopl.length], v); + double[] t2 = MathUtil.sub(fopl[(j + 1) % fopl.length], v); + double m0 = MathUtil.mag(t0); + double m2 = MathUtil.mag(t2); + double ca0 = t0[0] / m0; + double sa0 = t0[1] / m0; + double ca2 = t2[0] / m2; + double sa2 = t2[1] / m2; + + for (int h = 0; h < 2; h++) { // two angles + double[] cossin; + if (0 == h) { + cossin = new double[] { ca0 * cb2 + sa0 * sb2, sa0 * cb2 - ca0 * sb2 }; // a0 - b2 + } else { + cossin = new double[] { ca2 * cb0 + sa2 * sb0, sa2 * cb0 - ca2 * sb0 };// a2 - b0 + } + + double[][] rot_opl = MathUtil.rotate(cossin, opl); + double[] trans = MathUtil.sub(v, rot_opl[i]); // ***************** + double[][] trans_rot_outpoly = MathUtil.translate(trans, rot_opl); + if (isFeasible(trans_rot_outpoly)) { + double[][] trans_rot_inpoly = MathUtil.translate(trans, MathUtil.rotate(cossin, poly.inpts)); + Convex tmpcon = cntConvex.clone(); + for (double[] trp : trans_rot_inpoly) { + tmpcon.increment_hull(trp); + } + + double conarea = AREA_SC * MathUtil.areaAbs(tmpcon.convex); + double[] center = MathUtil.mean(trans_rot_inpoly); + double area; + area = conarea * (preferX * Math.abs(center[0]) + (1 - preferX) * Math.abs(center[1])); + if (minArea > area) { + minArea = area; + min_cossin = cossin; + min_trans = trans; + min_con = tmpcon; + } + } + } + } + } + } // for each vertex of new poly + if (null == min_cossin) { // no solution, stop + return false; + } + poly.fix_rotate_move(min_cossin, min_trans); + pendingPolys.set(sid, null); // done, mark as null + placePackedPoly(poly); + cntConvex = min_con; + return true; + } + + private boolean packPolyDalalah(int sid) { + PackedPoly stp = pendingPolys.get(sid); + double minArea = Double.MAX_VALUE; + int min_rotid = -1; + double[] min_trans = null; + Convex min_con = null; + for (int i = 0; i < rotSteps; i++) {// each angle of new poly + double[][] rotated_outpoly = MathUtil.rotate(trigos[i], stp.outpts); + double[][] rotated_inpoly = MathUtil.rotate(trigos[i], stp.inpts); + + for (double[] p : rotated_outpoly) { // each vertex of new poly + for (PackedPoly fixed : packedPolys) { + for (double[] v : fixed.outpts) { // each vertex of each fixed poly + double[] trans = MathUtil.sub(v, p); + double[][] trans_rot_outpoly = MathUtil.translate(trans, rotated_outpoly); + if (isFeasible(trans_rot_outpoly)) { + double[][] trans_rot_inpoly = MathUtil.translate(trans, rotated_inpoly); + Convex tmpcon = cntConvex.clone(); + for (double[] trp : trans_rot_inpoly) { + tmpcon.increment_hull(trp); + } + + double conarea = AREA_SC * MathUtil.areaAbs(tmpcon.convex); + double[] center = MathUtil.mean(trans_rot_outpoly);// trans_rot_outpoly + double area = conarea * (preferX * Math.abs(center[0]) + Math.abs(center[1])); + if (minArea > area) { + minArea = area; + min_rotid = i; + min_trans = trans; + min_con = tmpcon; + } + } + } + } + } // for each vertex of new poly + } // for each angle of new poly + if (0 > min_rotid) { // no solution, stop + return false; + } + stp.fix_rotate_move(trigos[min_rotid], min_trans); + // movs.remove(sid); + pendingPolys.set(sid, null); + placePackedPoly(stp); + cntConvex = min_con; + return true; + } + + /** + * Determines whether the potential polygon can be placed. + */ + private boolean isFeasible(double[][] poly) { + for (double[] p : poly) { + if (p[0] < 0 || p[0] > binWidth || p[1] < 0 || p[1] > binHeight) { + // out of bounds -- infeasible! + return false; + } + } + final double[] bb = MathUtil.boundBox(poly); + + for (PackedPoly fixed : packedPolys) { + if (overlapFast(poly, bb, fixed)) { + return false; + } + } + return true; + } + + /** + * @deprecated + */ + private static final boolean overlap(final double[][] poly1, final double[][] poly2) { + if (!MathUtil.intersect_boundBox(poly1, poly2)) { + return false; + } + double[][] sml, big; + if (MathUtil.areaAbs(poly1) < MathUtil.areaAbs(poly2)) { + sml = poly1; + big = poly2; + } else { + sml = poly2; + big = poly1; + } + for (double[] p : sml) { + if (MathUtil.inside(p, big)) { + return true; + } + } + for (int i = 0; i < sml.length; i++) { + for (int j = 0; j < big.length; j++) { + if (MathUtil.intersection(sml[i], sml[(i + 1) % sml.length], big[j], big[(j + 1) % big.length])) { + return true; + } + } + } + return false; + } + + /** + * Determines whether potential poly overlaps with placed poly. + * + * @param candidate vertices of poly 1 + * @param candidateBB bounding box of poly 1 + * @param poly1Area area of poly 1 + * @param poly2 vertices of poly 2 + * @return + */ + private static final boolean overlapFast(final double[][] candidate, final double[] candidateBB, + final PackedPoly placedPoly) { + + // 1. test bounding boxes + if (!MathUtil.intersect_boundBoxes(candidateBB, placedPoly.bb)) { + return false; + } + // 2. test the centroid against candidate poly + /* + * NOTE this isn't completely robust (a robust method would test every point of + * placed poly against candidate) but will catch almost all occurrences (so is + * worth the speed-up overall). + */ + if (MathUtil.inside(placedPoly.centroid, candidate)) { + return true; + } + + // 3. test edge intersections + for (int i = 0; i < candidate.length; i++) { + for (int j = 0; j < placedPoly.inpts.length; j++) { + if (MathUtil.intersectionFast(candidate[i], candidate[(i + 1) % candidate.length], placedPoly.inpts[j], + placedPoly.inpts[(j + 1) % placedPoly.inpts.length])) { + return true; + } + } + } + return false; + + } + + private void placePackedPoly(PackedPoly poly) { + poly.place(); + packedPolys.add(poly); + } + + public List getPackedPolygons() { + return packedPolys; + } + + public double getEmptyArea() { + double sum = 0; + for (PackedPoly poly : pendingPolys) { + sum += poly.inarea; + } + return sum; + } + + public int[] getPackingIds() { + int size = packedPolys.size(); + int[] ids = new int[size]; + for (int i = 0; i < size; i++) { + ids[i] = packedPolys.get(i).id; + } + return ids; + } + + public double[][] getPackingRotations() { + int size = packedPolys.size(); + double[][] rots = new double[size][]; + for (int i = 0; i < size; i++) { + rots[i] = packedPolys.get(i).trigo; + } + return rots; + } + + public double[][] getPackingPositions() { + int size = packedPolys.size(); + double[][] ps = new double[size][]; + for (int i = 0; i < size; i++) { + ps[i] = packedPolys.get(i).position; + } + return ps; + } + + @Override + public Bin clone() { + Bin np = new Bin(trigos, rotSteps, binWidth, binHeight, preferX); + np.pendingPolys = pendingPolys; + np.cntConvex = cntConvex; + return np; + } + + public boolean isEmpty() { + return pendingPolys.isEmpty(); + } + +} diff --git a/src/main/java/whitegreen/dalsoo/DalsooPack.java b/src/main/java/whitegreen/dalsoo/DalsooPack.java index 5a641ca..029ed31 100644 --- a/src/main/java/whitegreen/dalsoo/DalsooPack.java +++ b/src/main/java/whitegreen/dalsoo/DalsooPack.java @@ -1,13 +1,7 @@ package whitegreen.dalsoo; -import static java.lang.Math.PI; - import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.Objects; - -import net.jafama.FastMath; /** * Bin-packs irregular shapes sequentially. @@ -20,32 +14,15 @@ * @author Michael Carleton * */ -public final class DalsooPack { - - private static final double AREA_SC = 1E-6; +public class DalsooPack { - public List packedPolys = new ArrayList<>(); - List pendingPolys = new ArrayList<>(); - Convex cntConvex; - - /** Sin and cos values for each rotation step. */ - private final double[][] trigos; - private final int rotSteps; - /** bin dimensions */ + List bins; + private final Bin initial; private final double binWidth, binHeight; - private final double preferX; - - DalsooPack(double[][] trigos, int rotSteps, double width, double height, double preferX) { - this.trigos = trigos; - this.rotSteps = rotSteps; - this.binWidth = width; - this.binHeight = height; - this.preferX = preferX; - } /** - * Creates an packing. Call {@link #packOneBin(boolean, boolean) packOneBin()} - * to start packing. + * Creates an packing. Call {@link #pack(boolean, boolean) packOneBin()} to + * start packing. * * @param polys array of polygons [p1, p2]; for each polygon, its * vertices are expressed in [x, y] coordinate pairs: @@ -67,360 +44,66 @@ public final class DalsooPack { */ public DalsooPack(double[][][] polys, double spacing, Double segment_max_length, int rotSteps, double width, double height, double hSkew) { - if (0 > hSkew || 1 < hSkew) { - throw new IllegalArgumentException("skew must be between 0 and 1 (inclusive)"); - } - for (int i = 0; i < polys.length; i++) { - double[][] poly = polys[i]; - PackedPoly p = new PackedPoly(i, poly, spacing, segment_max_length); - pendingPolys.add(p); - } - this.preferX = hSkew; - - this.rotSteps = rotSteps; - trigos = new double[rotSteps][]; - for (int i = 0; i < rotSteps; i++) { - double theta = i * 2 * PI / rotSteps; - trigos[i] = new double[] { FastMath.cos(theta), FastMath.sin(theta) }; - } + initial = new Bin(polys, spacing, segment_max_length, rotSteps, width, height, hSkew); this.binWidth = width; this.binHeight = height; - } - - /** - * Packs all polygons, possibly across multiple bins. - * - * @param abey whether to use - * @return - */ - public List packAll(boolean abey) { - /* - * The pack essentially forks itself with the remaining polygons to model new - * bins. - */ - List packedBins = new ArrayList<>(); - DalsooPack pack = this; - do { - pack.packOneBin(abey, false); - packedBins.add(pack); - pack = pack.clone(); - } while (!packedBins.get(packedBins.size() - 1).isEmpty()); - return packedBins; + bins = new ArrayList<>(); } /** + * Packs one bin with any remaining unpacked polygons. This operation does + * nothing if there are no more polygons to pack. * - * @param abey - * @param largestFirst whether to sort the polygons by area (largest first) - * before packing - */ - public void packOneBin(boolean abey, boolean largestFirst) { - if (largestFirst) { - Collections.sort(pendingPolys); // sort by area, smallest first - } - packFirstPoly(); - int size = pendingPolys.size(); - for (int i = 0; i < size; i++) { - // place next largest polygon - if (abey) { - packPolyAbey(size - 1 - i); - } else { - packPolyDalalah(size - 1 - i); - } - } - - pendingPolys.removeIf(Objects::isNull); - } - - private void packFirstPoly() { - int rotid = 0; - double minArea = Double.MAX_VALUE; - int sid = pendingPolys.size() - 1; // ***************************************** last one - PackedPoly first = pendingPolys.get(sid); - for (int i = 0; i < rotSteps; i++) { - double[][] tp = MathUtil.rotate(trigos[i], first.outpts); - double[] bd = MathUtil.boundBox(tp); // minx, maxx, miny, maxy - if (bd[1] - bd[0] > binWidth || bd[3] - bd[2] > binHeight) { - continue; - } - double area = AREA_SC * (bd[1] - bd[0]) * (bd[3] - bd[2]); - double[] center = MathUtil.mean(tp); - double len = preferX * (center[0] - bd[0]) + (1 - preferX) * (center[1] - bd[2]); - area *= len; - if (minArea > area) { - minArea = area; - rotid = i; - } - } - double[][] tp = MathUtil.rotate(trigos[rotid], first.outpts); - double[] bd = MathUtil.boundBox(tp); - first.fix_rotate_move(trigos[rotid], new double[] { -bd[0], -bd[2] }); - pendingPolys.remove(sid); - placePackedPoly(first); - cntConvex = new Convex(first); - } - - private boolean packPolyAbey(int sid) { - PackedPoly poly = pendingPolys.get(sid); - double minArea = Double.MAX_VALUE; - double[] min_cossin = null; - double[] min_trans = null; - Convex min_con = null; - double[][] opl = poly.outpts; - for (int i = 0; i < opl.length; i++) { // each vertex of new poly - double[] p = opl[i]; - double[] d0 = MathUtil.sub(opl[(i - 1 + opl.length) % opl.length], p); - double[] d2 = MathUtil.sub(opl[(i + 1) % opl.length], p); - double mag0 = MathUtil.mag(d0); - double mag2 = MathUtil.mag(d2); - double cb0 = d0[0] / mag0; - double sb0 = d0[1] / mag0; - double cb2 = d2[0] / mag2; - double sb2 = d2[1] / mag2; - - for (PackedPoly fixed : packedPolys) { - double[][] fopl = fixed.outpts; - for (int j = 0; j < fopl.length; j++) { // each vertex of each fixed poly - double[] v = fopl[j]; - double[] t0 = MathUtil.sub(fopl[(j - 1 + fopl.length) % fopl.length], v); - double[] t2 = MathUtil.sub(fopl[(j + 1) % fopl.length], v); - double m0 = MathUtil.mag(t0); - double m2 = MathUtil.mag(t2); - double ca0 = t0[0] / m0; - double sa0 = t0[1] / m0; - double ca2 = t2[0] / m2; - double sa2 = t2[1] / m2; - - for (int h = 0; h < 2; h++) { // two angles - double[] cossin; - if (0 == h) { - cossin = new double[] { ca0 * cb2 + sa0 * sb2, sa0 * cb2 - ca0 * sb2 }; // a0 - b2 - } else { - cossin = new double[] { ca2 * cb0 + sa2 * sb0, sa2 * cb0 - ca2 * sb0 };// a2 - b0 - } - - double[][] rot_opl = MathUtil.rotate(cossin, opl); - double[] trans = MathUtil.sub(v, rot_opl[i]); // ***************** - double[][] trans_rot_outpoly = MathUtil.move(trans, rot_opl); - if (isFeasible(trans_rot_outpoly)) { - double[][] trans_rot_inpoly = MathUtil.move(trans, MathUtil.rotate(cossin, poly.inpts)); - Convex tmpcon = cntConvex.clone(); - for (double[] trp : trans_rot_inpoly) { - tmpcon.increment_hull(trp); - } - - double conarea = AREA_SC * MathUtil.areaAbs(tmpcon.convex); - double[] center = MathUtil.mean(trans_rot_inpoly); - double area; - area = conarea * (preferX * Math.abs(center[0]) + (1 - preferX) * Math.abs(center[1])); - if (minArea > area) { - minArea = area; - min_cossin = cossin; - min_trans = trans; - min_con = tmpcon; - } - } - } // for h - } - } - } // for each vertex of new poly - if (null == min_cossin) { // no solution, stop - return false; - } - poly.fix_rotate_move(min_cossin, min_trans); - pendingPolys.set(sid, null); // done, mark as null - placePackedPoly(poly); - cntConvex = min_con; - return true; - } - - private boolean packPolyDalalah(int sid) { - PackedPoly stp = pendingPolys.get(sid); - double minArea = Double.MAX_VALUE; - int min_rotid = -1; - double[] min_trans = null; - Convex min_con = null; - for (int i = 0; i < rotSteps; i++) {// each angle of new poly - double[][] rotated_outpoly = MathUtil.rotate(trigos[i], stp.outpts); - double[][] rotated_inpoly = MathUtil.rotate(trigos[i], stp.inpts); - - for (double[] p : rotated_outpoly) { // each vertex of new poly - for (PackedPoly fixed : packedPolys) { - for (double[] v : fixed.outpts) { // each vertex of each fixed poly - double[] trans = MathUtil.sub(v, p); - double[][] trans_rot_outpoly = MathUtil.move(trans, rotated_outpoly); - if (isFeasible(trans_rot_outpoly)) { - double[][] trans_rot_inpoly = MathUtil.move(trans, rotated_inpoly); - Convex tmpcon = cntConvex.clone(); - for (double[] trp : trans_rot_inpoly) { - tmpcon.increment_hull(trp); - } - - double conarea = AREA_SC * MathUtil.areaAbs(tmpcon.convex); - double[] center = MathUtil.mean(trans_rot_outpoly);// trans_rot_outpoly - double area = conarea * (preferX * Math.abs(center[0]) + Math.abs(center[1])); - if (minArea > area) { - minArea = area; - min_rotid = i; - min_trans = trans; - min_con = tmpcon; - } - } - } - } - } // for each vertex of new poly - } // for each angle of new poly - if (0 > min_rotid) { // no solution, stop - return false; - } - stp.fix_rotate_move(trigos[min_rotid], min_trans); - // movs.remove(sid); - pendingPolys.set(sid, null); - placePackedPoly(stp); - cntConvex = min_con; - return true; - } - - /** - * Determines whether the potential polygon can be placed. + * @param abey whether to use the abey packing method + * @param largestFirst whether to pack polygons according to their area, + * largest-first */ - private boolean isFeasible(double[][] poly) { - for (double[] p : poly) { - if (p[0] < 0 || p[0] > binWidth || p[1] < 0 || p[1] > binHeight) { - // out of bounds -- infeasible! - return false; - } - } - final double[] bb = MathUtil.boundBox(poly); - - for (PackedPoly fixed : packedPolys) { - if (overlapFast(poly, bb, fixed)) { - return false; - } - } - return true; - } - - /** - * @deprecated - */ - private static final boolean overlap(final double[][] poly1, final double[][] poly2) { - if (!MathUtil.intersect_boundBox(poly1, poly2)) { - return false; - } - double[][] sml, big; - if (MathUtil.areaAbs(poly1) < MathUtil.areaAbs(poly2)) { - sml = poly1; - big = poly2; + public void packNextBin(boolean abey, boolean largestFirst) { + Bin pack; + if (bins.isEmpty()) { + pack = initial; } else { - sml = poly2; - big = poly1; - } - for (double[] p : sml) { - if (MathUtil.inside(p, big)) { - return true; - } + pack = bins.get(bins.size() - 1).clone(); } - for (int i = 0; i < sml.length; i++) { - for (int j = 0; j < big.length; j++) { - if (MathUtil.intersection(sml[i], sml[(i + 1) % sml.length], big[j], big[(j + 1) % big.length])) { - return true; - } - } - } - return false; + pack.pack(abey, largestFirst); + bins.add(pack); } /** - * Determines whether potential poly overlaps with placed poly. + * Packs all polygons, possibly over multiple bins. * - * @param candidate vertices of poly 1 - * @param candidateBB bounding box of poly 1 - * @param poly1Area area of poly 1 - * @param poly2 vertices of poly 2 - * @return + * @param abey whether to use the abey packing method + * @param largestFirst whether to pack polygons according to their area, + * largest-first */ - private static final boolean overlapFast(final double[][] candidate, final double[] candidateBB, - final PackedPoly placedPoly) { - - // 1. test bounding boxes - if (!MathUtil.intersect_boundBoxes(candidateBB, placedPoly.bb)) { - return false; + public void packAll(boolean abey, boolean largestFirst) { + while (bins.isEmpty() || !bins.get(bins.size() - 1).isEmpty()) { + packNextBin(abey, largestFirst); } - // 2. test the centroid against candidate poly - /* - * NOTE this isn't completely robust (a robust method would test every point of - * placed poly against candidate) but will catch almost all occurrences (so is - * worth the speed-up overall). - */ - if (MathUtil.inside(placedPoly.centroid, candidate)) { - return true; - } - - // 3. test edge intersections - for (int i = 0; i < candidate.length; i++) { - for (int j = 0; j < placedPoly.inpts.length; j++) { - if (MathUtil.intersectionFast(candidate[i], candidate[(i + 1) % candidate.length], placedPoly.inpts[j], - placedPoly.inpts[(j + 1) % placedPoly.inpts.length])) { - return true; - } - } - } - return false; - - } - - private void placePackedPoly(PackedPoly poly) { - poly.place(); - packedPolys.add(poly); - } - - public double getEmptyArea() { - double sum = 0; - for (PackedPoly poly : pendingPolys) { - sum += poly.inarea; - } - return sum; - } - - public int[] getPackingIds() { - int size = packedPolys.size(); - int[] ids = new int[size]; - for (int i = 0; i < size; i++) { - ids[i] = packedPolys.get(i).id; - } - return ids; } - - public double[][] getPackingRotations() { - int size = packedPolys.size(); - double[][] rots = new double[size][]; - for (int i = 0; i < size; i++) { - rots[i] = packedPolys.get(i).trigo; - } - return rots; + + public List getPackedPolys(int maxHorizontalBins) { + return getPackedPolys(maxHorizontalBins, 0); } - public double[][] getPackingPositions() { - int size = packedPolys.size(); - double[][] ps = new double[size][]; - for (int i = 0; i < size; i++) { - ps[i] = packedPolys.get(i).position; + public List getPackedPolys(int maxHorizontalBins, double binSpacing) { + List polys = new ArrayList<>(); + for (int i = 0; i < bins.size(); i++) { + int column = i % maxHorizontalBins; + int row = i / maxHorizontalBins; + double xOffset = column * (binWidth + binSpacing); + double yOffset = row * (binHeight + binSpacing); + final double[] vector = { xOffset, yOffset }; + bins.get(i).getPackedPolygons().forEach(p -> { + polys.add(MathUtil.translate(vector, p.getPackedCoordinates())); + }); } - return ps; - } - - @Override - public DalsooPack clone() { - DalsooPack np = new DalsooPack(trigos, rotSteps, binWidth, binHeight, preferX); - np.pendingPolys = pendingPolys; - np.cntConvex = cntConvex; - return np; + return polys; } - public boolean isEmpty() { - return pendingPolys.isEmpty(); + public List getPackedBins() { + return bins; } } diff --git a/src/main/java/whitegreen/dalsoo/MathUtil.java b/src/main/java/whitegreen/dalsoo/MathUtil.java index 38fb116..19ad40a 100644 --- a/src/main/java/whitegreen/dalsoo/MathUtil.java +++ b/src/main/java/whitegreen/dalsoo/MathUtil.java @@ -12,7 +12,7 @@ import net.jafama.FastMath; /** - * Math utilities. + * Various utility functions for mathematical and geometric operations. * * @author Hao Hua, Southeast University, whitegreen@163.com * @@ -394,7 +394,13 @@ public static double[] rotate(double[] trigo, double[] p) { return new double[] { x, y }; } - public static double[][] move(double[] v, double[][] ps) { + /** + * + * @param v translation vector + * @param ps polygon + * @return + */ + public static double[][] translate(double[] v, double[][] ps) { double[][] arr = new double[ps.length][]; for (int i = 0; i < ps.length; i++) { arr[i] = add(ps[i], v); diff --git a/src/main/java/whitegreen/dalsoo/PackedPoly.java b/src/main/java/whitegreen/dalsoo/PackedPoly.java index 0641472..3d37e2d 100644 --- a/src/main/java/whitegreen/dalsoo/PackedPoly.java +++ b/src/main/java/whitegreen/dalsoo/PackedPoly.java @@ -9,19 +9,22 @@ */ public class PackedPoly implements Comparable { - public double[][] outpts; // offset & add edge points, as referent point of placement, clock-wise + public double[][] originalPoly; + private double[][] packedPoly; + double[][] outpts; // offset & add edge points, as referent point of placement, clock-wise /** Coordinates of this poly's original polygon */ - public final double[][] inpts; // original polygon, for 1. convex, 2. intersection - public final double inarea; + final double[][] inpts; // original polygon, for 1. convex, 2. intersection + final double inarea; public double[] trigo; // cos & sin public double[] position; public final int id; - + double[] bb; // bounding box (cached when placed) double[] centroid; // (cached when placed) PackedPoly(int id, double[][] original_poly, double spacing, Double segmentMaxLength) { this.id = id; + this.originalPoly = original_poly; if (spacing < 0) { throw new IllegalArgumentException("spacing must be >=0"); } @@ -60,6 +63,15 @@ public class PackedPoly implements Comparable { } } + /** + * Get the coordinates of this polygon within the packing arrangement. + * + * @return + */ + public double[][] getPackedCoordinates() { + return packedPoly; + } + void fix_rotate_move(double[] cossin, double[] dv) { // finalize trigo = cossin.clone(); position = dv.clone(); @@ -86,6 +98,8 @@ void fix_rotate_move(double[] cossin, double[] dv) { // finalize void place() { bb = MathUtil.boundBox(inpts); centroid = MathUtil.center(inpts); + packedPoly = MathUtil.rotate(trigo, originalPoly); + packedPoly = MathUtil.translate(position, packedPoly); } @Override diff --git a/src/test/java/whitegreen/dalsoo/DemoApplet.java b/src/test/java/whitegreen/dalsoo/DemoApplet.java index 22c73f0..0b3e11a 100644 --- a/src/test/java/whitegreen/dalsoo/DemoApplet.java +++ b/src/test/java/whitegreen/dalsoo/DemoApplet.java @@ -59,8 +59,6 @@ public static void main(String[] args) { // input private double[][][] randompolys; // the input polygons - private final float WID = 2400 * 4 + 500; // width of the standard rectangular sheet - private final float HEI = 1200 * 4 + 250; private final double margin = 3.0; // when 0, polys will pack horizontally, 1= vertically private final double preferX = 0; // 0.501 or 1 @@ -72,14 +70,8 @@ public static void main(String[] args) { // true: rotation steps depend on polygons, R. P. Abeysooriya 2018 // false: rotation steps are a prior, D. Dalalah, 2014 private boolean useAbey = true; - private List packs = new ArrayList<>(); - // output - private int[] result_pack_id; // result_pack_id[9]=2 means the 9th polygon is on the 2nd sheet. - private double[][] result_cos_sin; // result_cos_sin[9]={0.5, 0.866} means the 9th polygon is rotated 60 degree - // w.r.t its reference point - private double[][] result_position; // result_cos_sin[9] denotes the x,y-coordinate of the 9th polygon w.r.t its - // reference point + DalsooPack pack; @Override public void settings() { @@ -88,94 +80,28 @@ public void settings() { @Override public void setup() { - long t0 = System.currentTimeMillis(); - int seed = 4346; - ran = new Random(0); + smooth(); + fill(0, 255, 0); + + ran = new Random(); randompolys = randomPolygons(200);// prepare the input polygons Double segment_len = useAbey ? null : segment_max_length; - DalsooPack pack = new DalsooPack(randompolys, margin, segment_len, rotSteps, WID, HEI, preferX); - pack.packOneBin(useAbey, !true); - packs.add(pack); - - while (!packs.get(packs.size() - 1).isEmpty()) { - pack = packs.get(packs.size() - 1).clone(); - pack.packOneBin(useAbey, !false); - packs.add(pack); - } - -// for (int i = 0; i < 100; i++) { // packing one sheet after another, 100 is estimated -// int size = packs.size(); -// if (packs.get(size - 1).isEmpty()) { -// println(size + " sheets"); -// break; -// } -// pack = packs.get(size - 1).clone(); -// pack.packOneSheet(useAbey); -// packs.add(pack); -// } - report(); - - System.out.println((System.currentTimeMillis() - t0) / 1000f); + pack = new DalsooPack(randompolys, margin, segment_len, rotSteps, width, height, preferX); + pack.packAll(useAbey, !true); } @Override - public void draw() { - background(255); - smooth(); - translate(40, 10); - float sc = 0.15f; - - // display method 1 - for (int i = 0; i < randompolys.length; i++) { - int pack_id = result_pack_id[i]; - pushMatrix(); - translate((pack_id % 3) * 380, (pack_id / 3) * 200); - - noFill(); - rect(0, 0, sc * WID, sc * HEI); - fill(0, 255, 0); - double[][] poly = randompolys[i]; - poly = MathUtil.rotate(result_cos_sin[i], poly); - poly = MathUtil.move(result_position[i], poly); - draw(poly, sc); - - popMatrix(); - } - // display method 2 - // for (int i = 0; i < 5; i++) { - // for (int j = 0; j < 3; j++) { - // int id = i * 3 + j; - // if (id >= packs.size()) { - // return; - // } - // DalsooPack pack = packs.get(id); - // pushMatrix(); - // translate(j * (sc * WID), i * (sc * height)); // (j * 270, i * 150 - // noFill(); - // rect(0, 0, sc * WID, sc * HEI); - // fill(0, 255, 0); - // for (PackedPoly strip : pack.packedPolys) { - // draw(strip.inps, sc); - // } - // popMatrix(); - // } - // } - - } + public void draw() { + background(255); + float binSpacing = 40; + float sc = 0.15f; + translate(binSpacing, 10); + + pack.getPackedPolys(6, binSpacing).forEach(p -> { + draw(p, sc); + }); - private void report() { - result_pack_id = new int[randompolys.length]; - result_cos_sin = new double[randompolys.length][]; - result_position = new double[randompolys.length][]; - for (int i = 0; i < packs.size(); i++) { - DalsooPack pack = packs.get(i); - for (PackedPoly strip : pack.packedPolys) { - result_pack_id[strip.id] = i; - result_cos_sin[strip.id] = strip.trigo; - result_position[strip.id] = strip.position; - } - } } private double[][][] randomPolygons(int num) {

    85d(xW! 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

Ni}&S~gt4?We6&G}^&Hsdt=pt~#U% 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�b6yAn0D4HcgV-zy9?_c?b$rZs1QuA)b zcy|R6n-gb0v74+B`#1hflOJorqx?%r8W(Pa9Xn`AAE9OnV}>nTG|+U#92-g0EtkZUFPki@DMoj)$k(Tktl>#bm~ z83gqX1v8D@=%4Wxx6wO$xsUx2UjitB-3D}S^LCzx{Nb26}c+Nz=sYz7T10uuJ@|r)CFhX1t)Jrj-syE7|z52 z8_6gao(~=#$v79(L);(ZG-r@F4#p6iF-k2PyNK1X(Z;z>a))AFevj4|5H{uK5+kT( zFFiS`Og4{d%$*tv4;aumIv{Ji8`kn-M@n^cGA(^8sYFl4R$I93Ao~H9sfHw+ffAcc zuj`q~Os4?j52IgESuy7DZ&6$dMpdsxtR{y`-g>8VMv5Gvo{sLaKFZRWKfu@Pq{j%7 z9Ci>SaeIuTny3=)iU{}n+T4!2GfWz2wA9e8*IDn7;+xhSYYA?v^4KNk=^o3tB@BuL zXMdHLhx^yiTo<%;$1MeOvl8F~G&3dN|h+#(h9F8 zn0Ti&2*MFMsNkGY%@k3o4EN()oM9mpimzl2;xxI$8RyJ`Q%kYPZ^MQfneeIUMkKQi zsfYOR#bk!RoJ6!q1cstFjJa6y!t5oGR}w5lLHeF06#6sSOkGy z%5nzZI|t{vu&hlP)m zZiPhCDh(>f_v{!f%)ae3FCx-^N4zZsa+yaMhy&IZUp}=7z#6y6x*}w|5t0D)DCu z=ZBWvez^{&A?b8~>Ad?*2gCAhto_F%e~O8Imz{q44kn_5Ff&6`D#7vVX_t4>yr0cX z(QE?$bs7y8Y^i31trf_vGam31V5!J-hk#D7Hac7sc`>1I6%oF~pVa3hDUV8>R4OPp zIEbc_C`%Depghe8eOi^7=&!uIVqaWarJM$$$$0oXSW4B1r#X#(ZpBMg9u* z9_v}K>xI&d3mgm`gSzX#Cm90}nezRC8DlPJMvI@{)H#InD7vTEHuf9cif`B?(|XRk zk5>vUDEr}UbJtq|Iq&;jwX0PD|A>&lgUDQZF040azpeqzku|P>d65D=YZtAQNxm^80qZUu0i~Uyl!@*| z)Q^6VG9|}Fyix{*2hC|SPKs{Qvga26vXPn(P1kye0^35VMVeNH4YWA_>Om zBWQ6WabfrcqT*2#+lUq0_`)g9dXRoO?6n*rR*q_JmO(?+O>UegQ=nV@a);fFYLqe4 zRC84f#JxapTmL}C=!F;}0!gLIooq#1kGzM}a6Wb#+h8oFq3OVO<^`9ne=MqjrLtU~ zx5)Gi%^4ARWRxW=#f(NgDi`+C0@W<1D#`Xa2$T&xb>=7YI{a{x1(TM2IZ&sC(~fz0 z-=ub6<_fK&w0GyvN2YJl?(wgb2YgRyX+v^400*f6LnF5FC(w^8zb#7``)1Ze5obts6-KFvd zjZrBKi{f0AO9f$3xfF`yG^xcIW85TRic9P^lke0(*2Tf~JkzLsQn+3j=cutHyGzIy z(?@V_574`~mI#zTzKn!p@K(+ss#viP(BZ47sil;akVA{aU?X_EQJAo0%!}0QriP5D zQDuaauTW95(S$jvg6$Q83%M~WJaN-BiSg6dA>ye9G>{xP2pRh;;}jM0bR&Op!` zF`8wckY?CsG$)^+0@n0s%m2>1*zg%LD`;6#7IsZx#i4x(V=b^B!;Qf-7{OX~KR_J* z=jtnHK8B6_5Y~p(Xs);vx|wLWCbSSC9JHd2*o0`l2}NZJ0c9qGT0(s<#1`)q$&8)qaQMQ%yz|i?aW)`ld>|hDJhvp zuwtk%VGO}Q>^&9uRB~~qNsK6RROoP3Y9|$Fd@AR$p8s~?v~N=y{@D(O3EP@NBh1n& zFJj-lPUhh=1~Q9W3cA2z=K1q+r$35XOV%RX5)A-01^+O#xX6qXSEkSkng|`?$*H7h#EA*@ z!(gAilqwJNCSKozy@Mn_e5nj_2L~pc*E%RFX$F?vgT-k^X3qlSEp7EoQX$CP0wK?4 zZRp8@fX{qw_|$^TMu_dwxV=%tl|k3Iy;;VUzlKH8#4?Mjg>FW5!~UeI7Gau@L(x(( z_rNXXDWmz&dK5&F4$(`;S!jg5JE)wtj*Iwl7=1yd3J6p0pH)NK_v04)iN=vz^6%MgZ`j`y&cp>>|-TYz2*f* zvuBIPG1e@5i&VN;b+YDY47q!AjnPu>1i~l>OJuMYdUv_JGe7$GR%KDZ4p}yK7rI>P zZh#e4Wlw^`Sb|5f)Kv)ipN!5%lFdu%|JWbH$*Dk=YjVf+8ue?Ra59hag%L=tOq7^i z&_9S*FADhk`qZ(WrhYBFbKYb5rClyzNhxGuY3|}uI-2CeyXrx)qoblhZkg~bE?cN@ zx{-H6DG#VA53CP+803dc3)_C`Nv!gK!{n5k|6?)iA~K~YDx~pA=+@==SIHe1O;x)y zQYp8{02th!X4xzGoPrSZfC%;g#HtglB!>VP$t=Us#q9I{u_pRucPVI^$gl-B@lzTH zc+kIOfNH!WiIfyXS<4MX-pB@!xu^fv z-1DhLrlLv7^QlV;WUfyp6nWdGzj9W=!oPtDRXBIB=`MNFyWW@y+KTXeMl7hmTXoLSWD` zwZSQ{IoN;ZQmMg-p$7v*E5sE++)~rpfFoVcA}og5uoFncHPSvieQfkt9T0B|FWik7 zu(PO$WqHtNVGW3GyfqAD2Z^jsU>d*ycdiDZYKAe4V26lp92Rb8N2sVS%wOcj!KsD@ zTA}x0FPZ?BGC|Tb=eDgXMIEYhCmC(-+FIn+@(&%eTw5|nY*)qEB#;aTfS=z2Hthb-_l9e znT=?riN>vqDx9P6)yv!uGAKplhzmTHh~`5k3Z@}y;5p^0Tg+19$cLv?=p~1!gnn*9 zuceP6tR>%so1V9+n=HHJI6%-vRsVAzM#Aih*Z+z)pQu3R2X%hTCH9hoVJaqEV$OahnViQsuBmZT2rM&#g z1T)AV!L|vrRl;Xo^uinxTJDX?AZ5xHL6>ti3FVKk2_v zi&y@r(VXoQ4X#B0M!;HZr&>7@QaJNIHrM+RR0UfA?0}-s&N7I7pxnPP+rJvB8}A^S zo>lYUt-5V$9iQ8zQShqdEmbPkC)&XK%gt!P#&lCcrX(g|w% z=$X8Nt7v8~n$ZPq>PmU*j5&TzKRTzQWM(gt(S>jN$dJ6!sbqE~ma!4U;zhV_aDo2b zEq(nW9=FBm$>LQ=+4w)fYKhi&t861b`#xqhW?bs~l5Br2#W;_0gkK@{BNy+Dj|;)w z2@lEXd|Dr*ueWwC2*3VDY;m@xP4_AVT?;FMKxYe>p0w+e|756b#!#RTy(!qDdM?r zq2HyJB6u^{KQU7nheU}=jJb4RLp0gF6RwcB6I|cXBtfi%fRKLKJWPE3pBia5=*BC7 z$P8hx`A2x;tpJpkfQbDWCY%6bKaq)Q?o@v7qCs}`fXP~LMhkdx3;cwwK=R7ZvKFrS z)d-*sW#5=9OSa*Yf7H3+`lRjcbJN&dxLmHd%`KZz(myDC1|;95L2Mq4XT8Mb#uY4P zXCXjP3_7bh5OJU)gLX(D^Q0!M!&O_C2-UCbtY$X7RowUw=*v}CwAw_`8Xu<*zN=jQ znjIW>tAxL499SM7 zOyHvh)Jh0&jQ~{Z5s-aT=r9~Nj7=EF>I*mRjy(M=ntdY$*i$JOX6Vbv1utE0+_CYZ z(6yKesyu&jXx4*SyAX3|?E)|WH!hgHTRHDKyE3*errzylFfJD_Rk%BK)@aRsh4BoT ztUzs1P)rC}E|XJCg#B|UOs5l&7U?{y)Y!?}$YDz!;u`*{WCI%hmBCXPWVR*LDdWx& zEMP2=C!?jU)a&etdZ|0>Z8_VU4BLCSvUn5wn$Pr7u%&Jh&*C80qCZB6q0_!JLA5Yd zQA`ub|7I&|J3xT^{ho)8afxBsLD9S!VgruNFbMiHz|K|p$>X?tnh^qo`s?o6r=lET z^zzkg{7dysobsJP)a5Vsw%+WNeEeKHbkXooDBYr$Ll@{~Lv2{xdDgbfo7wa9=2-9M(EB5ORhSRYMBSCa#|4j8 zt`8=z_0|-{+Ebn7W0x=;%|Wo2S0K4CScdzPPQb%kw5yF7DA9;cP3Vs^K7v~n;F>WjIZ*HwwqGSA=)Pjm2CP`~8NlV8| zw*7C|#+4FVLj$yAkpO-n^&B_Nz~CTn=A%|p3uviV2=&@*Rk2lEseKi_{FZ$T`?29E zIF=o}Jge{`-?ilEYI@^q;P>&_>t7E`3Uod+{iZ%6Vp^Y(K8-on=tvr8(|}^kSDfvf2FFPL~3u&!{VyRbt=cKFu;59`sO+X4mGUa&2?EB;w9KXo&bctT&NXE874+N zO+Lg%g^+V5z48Tw;B$BmkxY|?P$F3Hgv2!9>Yv63+v~=70ppRrv*Q*Q6rWhsC-w!; z<0#oTB->tzcmqE;iRCfR_l)^Rwve+~ zdMI^$FSK5`5QS$VW;|X8!dCBu+aUTnS7CRP=@CCmx~Nh+NtwJ08MltPA2}|_f962x zG^HUo>=;=r{6aQzCKMNdww}4OU59(>8{T}cS~q(17BNO9Ih36|k;8vC5@E7d zcBTQ?EU<85CIMZj>R(C~@qc*JBI5z6KGGDB!l6&%OOf!Q?$F?DCKEflt49_>eP02X zU#$!qJFqE58LN)*?R#Q&lQ0F3HL76mTR3W$f@GO%ya*?DFOk&x%m=h)5;|e(E|yWF z#aTgDB-g%SuHAviBmhw2u?Rs0bEtdQ(0=4;rcu{h;@xO}!)ZyZi|9b(Y!J=k=up(U zsv&IHQtrKNmLsaR1umRR7m9v6bCmTXS@G&@5C!g`>u6T=UoItm*7DHaJF*fn*?q47 z))g#soUGkRLzSF%n^4v`v78s1YL#&g9@u62X<^qe)`$z|)P}Ge({m|vF0W~=K7OZI z(;n^-%M$0m!#SqfjFc7dZsScS^6eZm<-k+`vu#MDbQHIm_GI}b)IgK8##yuUg~*OF z#DGgd7S4ItmlYxO@y}=VxAa)m9qeb(w_p&PM?BeYoQsp~YAIAkU0B9A%3qKe;V|1r zEIMUV**DoYU9L3T`OOckSVNkNIqk}WFKPkvT7)bbmDF43*wKhU7VX|jo0XiLjRa?S z&FN-G;&rSU{Fs~F3FcqkT*Fa}Bknf`SQoI(4Oj&}<-%>Xyn(IXqr2{k-sz}Et%#Mu zL)xC{b#f|vyRSM7j4|xN3;Kzm0EBd z=e6CaS8Rp_TvtCcDZZJfMNLfm*5yDFZ}YBij0D`*(zypz{#B;!4twj?dvhDK2(s^N zc?1JYCn34yMp{pG`A!`ZnqSwbO@tdUc?vz}ULx?v(9flfKUsd+&b^BLE3eXfOGTNt zf?M-DcXHqR3sZ8(?QjGS#bYm2a>ozn^ofia3is#^(0mgMA@1>%VD41pu-I79xO8ZP zWX7-DmfOIydhra}k%8=C1pVjjlOI=WzYfz`G+l-7OO2di9tiP{_H;{0>&GxD^}7+^1k31uAZSI7DwkvMRFK=klIyp8*Vx?A`7 z02j&!`SK`AFxFmiJ=V(4p6sJ5;r>bd-xg2q*%kiG!&B_hYbWJ2R5_}7@O%WT@aZ5n z@$cQ}cy32=$y@+yPW$R`Ndznc zRPdvm=-9sk;qqeP@&e%U;EjEp4ZurAUJv^%({nGgAUU7SMj~eA2=44}Rlg_{9{wjN zR}lJFdnOwA!su2|!X7>aM%|+=OBxlGddf~I$?{DYTaC{I*7gBfv?Hrqj4BOi9OsnR zo6tGI8NpHMheUOlmFg64rbr@=)H`uU~JT&(Hg1a4RYA_55cf4~Dqb|eP2bU} z*RMX@sjSw7d@KJP5x$x`@|k48ySil_5jm*7mz6<0aIvCuoK zTY$fZrt!f(lBF0M+fC_PtxC?D2yCYAF(IB@AXU4PQ&g{${R1Q=q8U<9YC1c)-)R)n zgYK+-^1*o(3%*!lUAymA{a0hocu8dR17ntu1WuL62(AP})bj5H(pK8rto-Ktq;Y0uOHGrZ#(W=L5i_2(p#j!Z7(=&pSS^tEmVhsE2*}BPjtFhUI>@h zU0_~5j3aU*{6lR&9U}N;FM-D%xmhcf^6z><8#RcSM<40o)tu5}8wQ@o9z9z>2J8d3 z?1dV(LfHfufFJy$HzRpZU%B1ixgrx3*Js^uyoQk&B(rJ9SUtmS0Wu5l<$9X$^Mc`do7$t_Vd-3Q-fm8=ljCoF(buF!V5iyYuFk)tR{&&>m{KdbN=EyvRI?t zJ!0=9eQ(3AqY-f9(_<7xF{WI>jrFoi)G`j8{Jxa36tYEMQ~{=oHdSBy(1-J$2+1S3Afq=aW_% za4^)B1jk^gim9OO1G{qTR)pV6MWhO&rG?c;5x9u+(p%-MLPtVkY-Ys^@}>hn=EY+z zKw&41=$P~nTs-|+GM|j3f>4*bNIlghSbfhk{{4^!SrIxfhD(y4cX4P0e=gd!La-AZP-+d;l z{poLpmjak#rvJ1$>r*bL^Hq6tDli3tQoHrUy?ZWNEm7L(-)QozoVqG9unpYW*^FpopITP^KGwAVx;|akw3Uv%* zH0X`@hc*VqkcC~YW7_Wh=T8`m=nxLByjug~(MbhxO)E_?`kU#0NRzAX`C0kzPCtb} zftK$(;jLEXZ8j+82Yn;)(JGl4Z20lW(zUi{>7$N$0ly!BjrF-UGUpJYGbA#eqD8ab#!#jXBdIvO>5LY_u*&1Fa6ONGPQ-(`0orl^h$LKe=)55D zKG?7jnFHHCblEP+yCLOP3>YCDM)=Y^AjHc3P#U3fy*W2_0PT3IlcC`O6o zqWrPgLjS+BMj*m730g0e6HfxQ_iqE7#E8n4UN|ymibMeJFxX))bASgEmty2y57VW1 zts4?3d88_hbG3d%gRiJ>NaB@lvrm&&qMs1nOFOcqR1v-qijs>ZZ}YLN17LJ-Sw3B2 zREHT0Gw2w>I34HchvTBGcI?yORh-5lz>oTym&p~SqO`M&By`et;d7ng%#iC zx(3e;OYV(ALhue1ek6y3_r~Xp8{kbvG}h>)V~%585eu6nee5I-jH;aLoZf2%#BJ^H z`fh#jR)`~`l%An+O+Td`;isad9i`}r#?CDTS9!@)*e9O}rk{<~KG7naNO3I%F!EXU zx?Y!_9sv>YME|Wl+_gwrzMD|eNo`f?v(bKV%wl{X{OmG^iXyG8g-h!}h14p4EpCh- zDStgkUoL-5X(Rx)5_Q&gEA*H-bo$y>`10|uJ>c?uLq%sMHn~S@7MK7gX)BT4Z~URhh-vf!MmOC^47$g zW2{Pl7nheGmv;da*GPFQl^ zxB!w6lIy*!&36xT>Qo#2W8ini*2(xqu|bcnf<6{9HN)zY3zzkFQeE8G##dEgi_%u* z>PD%opMdG>%(3G9o05`}J0T!b9`i+nQ)sIYfTos#9h2th=(6K=OninT-#q|~w$vDFSA?G*HjEh; z<(U^P^d-Jera(X+YT(5Pt1nIPr#_7FvlAe)*5C47Q*%5nXzxXuYM_DU7ew=4Jo&wP zK$c(VNGR)l=@6rGiBZ*8eqA!DL5r{8@;gX+fdJ`r%y2K;1;3-6=y?a?y8cRX>?R?0 za>A^+DdnS#k~Zp5#9r&rC!7W>`c0JjP)WwIo&>V((`t|KM~e)ZqJ;^P{oFuPT(gtn zDBenq0IiLQRzZEA33200Y!G2c41)x~8~^w(y7xQTan#8VUuir<5&}Nt4-YYg!9vPE z7wGrLOo9$UR40`3BjJ#Y$BdqTENGNuC2BuWKDz?_YFo}~-I^tigjocx+(d7{KjaoJ zHI@k-tJ_7;z9_syoiLj0pD{ibi9*RExQeX4X9Vx&6h&SuDckTcWR}H8DvK$Rud>o~ zR5oB`-P2azoIwoXU%6O45#kqN0!t8kz=p1r(RyeV?`r~Wy1{Rs)zR834NlKW3wL3?9->L(p3*bF{kW)h=0kK;=JZv^RX0)IB>afWo!ugbL{g+ z7NM5s8HCT5^w6BOm09F3dn1? z@(+D0z}h92$qL|gQm7_F%C1FpE#;Hh|J0??&NN)t)TxEuG`3|k11|~@GmGNseNm+S zC{1u_;}EhMROT-3W1{(&M2vVhcajBl8xF1t=sgH+#{_`Xe*OqAKB~cS2_AU^v+uA} zhx!BFp9-4OU+|UBh;^A?P}a{1!2T~t^V_@~yiZu0L&zOvx-AqF2V2D;ogj#F_)JHy zp*P;pt2>*0{uzo36^@AOP38J$erD)1&?2f$PtIa*OmEY~}I3^@LvZ^nJ&zu^*h5=_n#79H-2fE8eSwr_~y0L8p4E#|d zbtv#&vF}c?7=>XXx32Set4hwh{~eCccsjZXq{eNQzI2X7bRIY6j+qlZ&!1XPw#x6r z!Z%C4$g1K5_BqvQ-cX|zhuH;uXWk8PZtbrd$-acUi1IP7bDCHKLUfPKQtK271j8p( zBJyAZ3%1qkfGQz?P>BHe>=5_Sp1tk6l@J&9UC>)c!$FG5-l4eien_)!D|QM`GDg2Ap(wfG{qDVBg(tOBw^BT}C+#x8Q73$U(`0Mi+%nD2oH% z4r*F7iv#u%?5OXfkNjHG0hZ#!pO`k4tU#6HmUTBR;ft4}%=rOK$l zfL#W$#tbyD*~Y~I9v8LBSga3%1AXEMe5oG1PrZetEmsX(!H5zCP8-;2Zjrx%wy@f(Rd^4s^Q?-+1S>(A{W?X7KcZP#mMTkmTY zTbh2@Kn+XUK%J(BZS{-&?S<79s4r^w99KDq&gUjSs*U^knukkWy|YY~3vIVnB;sbB z@c31FQOQe;RAIs!k2rAp(LP(_;}BU=_P44B{?8AC?FTnjF>v&!+rX5R`rF`b{Jsw+2k z*uxh+r;sUUU$A->;w5~fdVb;oNlM#m(6&Ls-3d||Z5;?NuQp-0BtiSRZ@I#L%P?;f zgJA{-|LPE-xWKz5M~6KNA-O}~`9m4?5Wy>Ag1%Ov6X3gpi1kNT5K4T#yp4TrPBMcC zJ8Hwc!J*Iql2h`ds6LdPzn3rNNAoWS%&^7DhzW6sB$6xm?Rf#Db|G}W08V$<<365V zm`&*JZM`3mkH0))Fap0SQm4kpRB0p3k6CeLGSTcBC@agtX z0P(ZAYO(pw{5EVI^D{~|q4&#I^CQ`|5}H=ewCcltru>ZT6InbM7)mfS)F=w*MEN?1 zkeD4AQB=57dA?I{IF2bYB7zc&?11u(k z;{rz@VeJWC?=Ke(RU?9BTRacxRNZM5S5~GkDdf0IB^#QWy@a&qZDzqg*EU{YMO|x z5TPQDqP(I97{^=smj)eR)05J#D=A>xnJ)aUYgz#r3klCfMnaO*d`?^TVTLlnokv{& zC(HB~MUA%rVX1(1=a#!{$14=A2ARd+_o1a$UYKA)HUz5F?jawR2#x~hFQQ8?r`-d@ zwODcCNdIhNGa?^IigGoWas4qHd@5L*2!L#d`00Xd7?~oYSr+LUF2{ya+SqTLg7*Tx zHQ|ujB%Q9#sV&qoi-Utr4qUeYEycdbZ=Bs^wV4%DUK2a@#w@?nE1Gso=(EN|{)>W= z;`0651$(00yXej-c2@p1MqCy=8$k{Sxv~tS(;Smi9OvG;-E6@SV;IH>+e~42IZ6e( zaSTUXNXs_lOJA&*)yF1X0ioF*sm&g=rWIE-8kXX@V*Yd{|M_CL6XD z>!^>$7;8P~1;-e`YZvWrJ1ptmhXv1wYrOs27|+`ZK*?%<*!u4xEv7l|9-Wl@t=Q@u zvmycdD$%z{fJ2>DbJVKSJpx^jaWn==u$XTXWtVSvVGO?~om_I@sNTq~f4 zVnjzNx|QU=bYeZ2)9hoX38L;PQ?Zl?&8Ppoh|X{bWrp>{N)r;;bE4v`@kbuE!Lrwd zW{s&djAh0=#Jw{}U?#L4!mHjEl09P_f<#9#;GuHZ*K7i2KTc8SAH6T91*U=0@=oi2 z=!1a`fBvW@?3u(b9M?*!>Uw@jMYsh!EWW5??=OCS|H^?&q-l^8$sVs|F$d$y=GUi( z)bs!{kCla{nv9~~D*QOC4}do2(+=l8IGg?q7Fr1>4A)6#D^F%3f}?vA+yLoN~Z%}DivMfGisWN%rUd-hx zj}%L9v?0sV4n$C0{*;0{Nd|e3s8*-|RI{bum-oM5cuq{$&y_Bh;ImD&LzOs5i>2$T zT9)Xmh3KB658*}8f26R!R%hscGsVpFe(PMv( z##Ow=5E*=?MZ@J3vNooMS(^fmwSj|Qay&QI!+By)C>^W!{@8QHGOG%V7|vmu(uBW@ zZgz-qK{{t82qlb>*f!r&qBr6F6B0Ah zw3sd)Gtyj>?#fEA*nykX)EM*DlptPx^nRe^l(t5tVZh8e>WG$(dk%n^gx?8@qtlqS z4N<_&bp^-N)Z<~a<-lCF-lk^>S&PKo-r6@}sFT?-Wl6cR)rsA?CigBL&cOoHhdEQ^ zUFzpxiQ!3$Q4}dLo)&Cv51%ynpj?J_9+O@43-n>iodo&*q#JrzQPM<9;smO3{Ke>V z4=tk9mngVVEXbf8*o^`@)E4;dcJt4C$6|3L4LfoT@<4Y~p}z;v)qIV&Cb{9k? zH<1P#?%&WcDXY3Sr1P*`$r}DTy4K!^eaYf%&2wT3O5{Fa@W5K605^=)&Vq;E<}LB6 z<^Fnw+k1#m=N6#77~e_dk4HbK^Ct*@y;2ZYAC|goS)g+R&JT6!!Y#*qN8{>4EqSPb z5I!Y)7N$kCg$5-%q|aUjJD1&;CPY;iM)mxDK@LiRAtS_k5ZnN26IJjktbk@&;zGX^ z7e+@Dv_6{eTP^f~d~)=Kw|GB$cqMwTa^EHFl$j07L4+tp6;}oKHmX2eqd+t{!4|uI z8njlxjo8A}_ zS|7P;4E?*RpWD+uPd4qfKE(#qt+lwYw%p(y-H=X+5LGxAdH4GTuRx$WQBz8JeguVg z4e`c@PU5AV!u&>aS*Kg!WsOLPb{t7l!OsmJ`O}&a-wVa?DNxM-$c0B4t0QM+KAazq z0FbprnDp&o`4nbvAw#%4VFLx)n4KsZq)s#S75Bu`< zTA2giAlg>($BNS@Lhz_fq1{cj#Va}V@K&^kwKyV#GNCfwAecd7up2d)nd=slS)N3( zD`|`_O0D~DlUc}q)^nAGZ4vNSd*lzdah!9Np#T~r3FN`JQ$V~one}yjRUc&oL>{*z z(Mqk+;!m+8L#FJzx36riyqx^Obj$oKe)2~Cr!J^VCj!c6(TO*37Ft@vkNgOwM(jt? zJc0?@fkBriGAk!V@FyAcb>ZN({ooy6`E^s_0a4Yg$W5w#`kUb9hdxs-&MLmL{`{hM zxIsl%6s&G#LqJtOkdPS;01c;K`CSUp&ji98%?k~;Rl($4+OHUZMUf2_dZmUHTgIdt zja8Bh7D`z3T7@CA5-MsvHfure{eqW;WtvgFUwSlFdk*rZ{TN?ZdbL{#<>8C#&3r0# zyXNti7e+st0-gDNEZ;&Z`+X}sn3~U-!z9Z&zup7AiLEwN*_q&;^=QDrIbb9R5xMEf z7+-WeS-a3Oaazjgg%{VI@ATKOxX=3~erTSo@V%0hRrbH&w&A}J?}sE%8B0O|9(+w4 zm3-=bdJq*#0&;FlR!@ZmhC#CaH(XQUbF!&sjn+-f@O4>D%wwJmsKEoQ~_8Xp$cEv)~X$>iBV zm(^$eg0|0O?4vxKxGsL7dAI0>7?GV(w}ao0Cu(yNj-9;}mR}9(#8(#)s){OjQ8sa| zwW6i_WDn=~T8_wUrXcSmk{Nx@M`>wf5@(fOKCQ-@GCL{3g0E}N3o@SXRqZ4Ttr~XG zhFgg_iNETZ*2Hl5kVuf?BQytCoH5$j^OTOX@1M~jNHe9kg!Jr%aDfIN=4kiCG{(AR|v$!&%^-12JFJ8)9IR(V)r$i6TS4zxa^2 zt^Xb7Fe_|_`_8&;>>WZqeXC#Z@TqQ=7bI(nFn^I3W+q*rU;d8LedQf{lgTgOX;Obj z<&G0z@`)fZX?(4Nl*LqLxzfir1@qbzNc12X#d{@Yy(Z_I|vAq$zOl$!H53!IX zVWD8&3;s&edf)dJQD+m3F7>lAZCPbj0p41lq-q$7Rsg(;6<>2z_yEGu_7_Q23)C6g z0mMygg$n!beU(M_qug>YDxC;b4l(Jnm=6d9K9SY35-!|j4N+caXC;+9WQD&gB;PV9 zOAy~eXCRnjD(-%;B-AfQ3yEw5b)l;`GDN{d$P%J;aoUPBex+Jp!;fncuIi8Pm=T8!tcafRx-7W3%X+00 zlNzt~XmWFxbWQ)OXSQXOVGN&zNtKVDm7){dV+|=*F}_z$m5=LNqszfAOd~(fhMDd= z>_RE;fjQq^P{hiH9qRJ{asUXq!7&9}4ao1I8G`%zXaEAo_(#|bahh#P)k10!I8AWO z^cq%*hF0($BnfL+Vc<(dBP!X%r0ivN1n|-zp5Ld~6lf!vsEhgi^Ek<1AIM}cN@Oqf z5N!Xwt{p`-62JcpZLMhN^S%6KIiGJ^CNz^B41vB_DUNc3WA_A)gqcBMKA4PCJn;?}n6Lg|p@;%3k-VjrbZY$Gp!$QQ zBFekbb(prW`tf|ye;%+_M5(bG&Avo}dUzJWaf#6mI)s9M%>w3M2nV@B!F%@260r<_ z`}DVOe!I|f{udNHH>XgLu({#gqxk8YKmI9fNP({+-YKH32xz{F1(6GE4!n;^r&{)* zO4w*6?o9hO(oT)CWq9L-tY<{Z*D#)Vdbg6}t92?(cW{qUngllT+|)dX7GFXqS_8r7}q)TOyr6+z%1XSi|iFAz&8cv10Uv|km%Lt>uz;RN(1)($td$8U%ybWhj5lh#dG>b{tNb=!Tvpw z^CXeen-4_aX@FAlM6cIAu+Um<*S$4xn=yVnht1{v@3 z3X{W9MMY;e2D*jX1_U0Gm=v#KE0Sb#{>Bvrn3^A^5Hjgdi5k<2>@7{21J=ctxc*b> zQnM#PJl*cEPd!nFp7-o`F)1>#s~r5=Ajz&hA`1Tu(k0Bvj-5fMmoV8nEKZo0SH*6- zvfA*@OK!#d9&REHD-^CDlS#ynC)VT+9Z6W55N^xuu- z{m&87*)Y5~QNmalU-O1~XJ0fF@%?+H*-{_fd&@i|pVjoYyJ#XjXWtmUb;^xa-@H3J zvuJ*DqsIZw30vqJPj`Zrb#I$?@OaFcVAq`x2k|x-&*0hs-yJa~25MgXfrIVr$hkOr1as@ZOF@0|GA5OiOYL(SGxaBxiQ2EcT9C-8$}g5Y zc`LWf(lWa)68*v2?&vT}_&~b9INZTYf=k!h$LQU-uc1pGWSx07`M$f!Ji>V?V2c}$ z`**~lm?*N6&%S82kn~WtH3%sxP=FJex_i&Jf zsS)}vH6Aa_7l{^1a2{%SB4!6haqbvvt72Z;Un{g4B0@^cpM*jkOk;+fx=f}WqLR@K z0ooTRsx`6E$8{V?JcIl5zbXW!}Oq-Ftx|57`PJCWFG~}HBYv7!kmvWaE&=;f!=83?iKkq=D z6wNblit0H#{U{0mp{c6_`~=|QPF=Xo=D|OI0ToBbTnM%@PNIT0Yzt;&h^a&Qcew-o z6n=C&it!I-mLp|Q>~$rI9bErs2$C=e5!T9e(%-oY9{-d$FgHUCUGWbx{?r^(<>0`} z#RJZGN9#ft&d9KNcgUJ+1OcCX^qTPMoA5S03r(A1aBV7o_+Fa~DC_@KZHmdShGFk6 zT?N~Ga?U9+Xb&Dc>>!9ox-`9!B1C?aQHhV-#!)G%qzxW}uRDhKi(c}H8nO@$A%~QE zj}A|EM!q1<{jK=cmh#Y-xC*SC>7K$nO-fT2vp>vMmh3G}b6pEuSC?I!Qa|XCw*}=Lzp?q#vII3KMOJ=$oyKLUp`A|d&OY?1 zAm{lAS9XB;4zoO3_^p`yL`xL+#ms8%Uf#5J-d^tX>Q-OWNR$ z5#DPlPq4xjttcfC(fp4C0mgA*9utYeStB@B@x36Wk!zf1jVKJ63d*oK1O@uS^9pdf zX@=aqBMv$1ms$&O$(dv?HAx*o%DDJy@_O@{xBjW-6Xa+riO zE7n50@1PcF(x3K|bJO~x4aHo?Ez@f^y&;}Q>(X&{3*(iMo%g7>X%xUS?c?68QnFVG zd2A#gB;h|Y`yZ+I(-pf6RZ(Iy{}VYWjNT6SXYl|ylnHOH?QD?$n>^cE58SxAooOo* zaY-B2pj-{QvMR(OP7ORxJIbK+H~x8poj>1VOx=<;+?AHhwwE>ayUj+GsaC5cvUSGd zymn1yChrt~N@@24xqRW|!6VN)%Q0Ktq;w@Ec7==5Pjo;Peyh1NxsoGxd z{Ix33i`_UcoGP+MVl>CnfB8C@M~M zER84)wT5Ww2W`D#kcM65=lllq)REY+neaM3Rg^kVRI*NWZqaEdaZ*4?CqAZE7nP~9 zW)w-=i*V>qGqz!eV{4h)M$2-K$CTM0V)3Sa932}0dD#x;sx!G(xDc!6!pxsqR!QQH%>RNbgF(k1X7F>rp3?aal*-TA<$O~SokP-$X z4*}bCM1aW&rRW>%?DUsH?jA=sZML)qR6L4++Q>DhONtk;dI_81DlppoR(j0rJ$;r7 z?P0kf%$O=wl?1j(Q3JcHSzmv~WHpz_6e}KWOk@-HU~s?QL&2<#vgd?8e6NaSPG*=L zi)BtUoIx4w7%~VDGMJoE2(VK}>9AHD#0ap|&oT<15juLxe-r*wiMGdBJgI`O8&;xP zw^+?YNvaLIWm6m`UMIOjL|b%+q~(6syuTxpHRRGp@r23-~W z#LX`m!*%A!F=iVWnB(w9Tx81n?-uFbEz`eS3(zL-F9}P-r(l95VFdcMgw!5VdY<_I z(u7pZvtqGAiDN{kWIepWWc^-G^fa4di8Gh1TB;U->vZ|rv==P|)h`k{DU6Slv)>RT zNNJe$l`6}lg^NA$Rbg4UoiuvlIGvvA;<%kKiY1(`%02TR4KC&Jrr63V<1F~d3=`wz z?I-OfPP6k7GC*IW5r|HDd1!j-Z#o@z4$_bLIEMa zy|1s!g1T6U)Ah1FBkBdcUA=Lx6{u+T^al1;;MNM~dqgeYq0dEB%cQA!fvX{E8^* z8$l*KAGwc$3fLl5og)z~Oi*Ft`6o*o%eKTV7TMH|Y`)duoGs?ZfZ6NZ13(FE*T2xg#QHL+YL8W9emyP0b^q@> zn}<5CGQY_vr>_(4^}@io>oK4$s$Eif#mDuVI2a>a=M$Bpn^T%At=nrZ3P!W zrzWNo&_$f>1bYNRy|zkHj)o^!km_#?<5i>+B!G_W^=4$*;Z!dKF$(Wl=+2m~v~7+` z-4^1I$SiN+oq&8wa*jsc2P*E%TA*>kW{SSLhlXdt6k%Hmd02fDztLcThEc!TU_sXI zOA2%6v-k=yjj(4q^xJ9iVp$Mk z9|>&+=sSdvcd3#PQkd~()(w0W>O8RK-dDq)=`Fu}d1?&3eDSKrzJmuQjKxP;8t#)I zhEjOC1r&r0G7W7IJL84s;tgcHe{H^hb;H=mcbSp2XoX*}47zeP^*Wt}yA{aJ4@sNJ zRQZ4}{@ts4)Y#sxS2Q8$&$|l9ptNSG`e}8#6wm0I!!hOWi`_-3CdO-c+ z2kW%29_;(A9N=H9_s(RYu^=K4S-lYrCs})XVkXUyf}u#ryIBlB?@>OsqAjE}v#_4{ z(luw`;|bcA3bnA68(9E+IG{()lyc z7%8nZfK;428t_Sg6o#6mv_lXoxvzAL=CO`?>5f;H|I_)B9skurPWKwZwpVK}!DUX= zBrJ^nQVunf{}Al+mi$0JR_;?qe^=Zr!L*Rd@jIk=K zymC*K!(bdgeq5OT_(A;tqcXCHG8o$!Iy-N8L%X1hEnasmY%JvbmA`G^{Y3-~hDsJp z4+dwLCPw5RSk(Zvl7uOY(kK`h9v;4TSytu`n+1XH2pSk0iA#0b7E8N3*%q_M!f?lR z8lCyIdFq=Z5ze~xO_Bb*%hOlru-mBU_GIb%g7TngL1Jd2RT@nH=qI8Kqpk`;Cc}%{`9Ky80q-V|P;(fe;;oAh1$| z-4v=XX>2AR;?IRn!E?r(rfLITAE8p#H!@K(!e3M@8K~_!Q%0k$#nxt_wzmz8{1e&G zmn8gPN*;r1U1@zbQ$!=1tw1LcW+fbBY$>bW z^D=lWN`efJQ?wcnw;^}DlHxtk9~H_b83ST84gp#O&0k}(iiF4?4EVLCCHH>_yQbjG zqHZ~v*yb18wrwY0Y}>YN+qP|MVoz*MCZ0Gq|6lj%zTB$Qz1My?kLT2?y;pbBL``3u zVxX%py`q{er=bDo7^)B*x5X}EQ)g^9C!5aK&C~ppT-jpnXb-7ge>46-L5=|yE{;i$ z!8I8&8k?AERunZQDv8)kn5w$yR&>^Q8QH4D3L`e}vqqHW!E6sy?6V&YLxrq&c_pd( zPUn=p-W8!7z++|#I{$k`Bwj1PlQesX2}@**6LaSd$^;62J!a3b$Tko`|0I_cmi$ua zMuA5)WM0Y;juL0Z@K%MfIfD?g%eNbb<3uH@EUa;KQgM9@DZ9ICdi8WIB_%{D%WJLJ z^||I)3e()0llT~0n-7UKEnQ#)oMbVEKg<}L+S%GZ-YFKt-v_i1_7&AQDrF!Piwe_GRb{H`w@6db{=xz3s39w3kt-UBRBlRY*^y8wi-1sZ)MFKHg~6Q3 zYiVB4+Qj`H4nY#WtH*n@s0cak!CZmjYxdI>li&iV8V5sTh`6$gGO0p8va>eebeRdA z7edR~V3Rw~0og5M<27v>4cVH{su@T=b4AAZCZaM-*-CpPca~b&b)YUS&e=?>&8YCo zn)6ya3YrHLxU`@gYHM|>?v8?rzOag%<^)!vJu4koBunSsPPtQ$<-z z7j17zTUm*Psb*J_w1}6jFP0X%RgG+YO)b4O*2vb5r3j7lrLmo^xTPC$6}i!G&vy8K zf<(UvtSBkzsx9Hz+8Va5TMZciiZoXy9e+RAd4C`#d8jAc<%y8d74MqZZI}=H)teI8 zi)F(@?i()RsNWocbkFNbob{}w-tYkMkAqS1sw`=%>j47ZQ(z}YjsOHEEq2z`HF^p> z$zTdw4;VW`g5>1kM{^s_tL1RGeWJO|8{9Qp^NF8xxB~XWuot+T@X|b*^8M}mWFDDi z!*C7@a2w zfcH4~zjsCtcZ#lT46k}=D~^DjQxc-wKW0Y$P5W~3l zZ3N4~!hqgF@{!!hj_6w-D+(sTaWz?s6G#zM?5v4-+AuRF)e%Kxkx@8w7S$m|DcJgo zI!!)odNqf}AQ?2Bp#~tUIi90pB8h$e9%VRK!}+>nmdF;annm@b=r zV{rtj8LnM144DocfxfP~rf4{t#3tv|3U(8?>s2x&6WT=T8VKhCM^eh%Z&W){dO zAa;-B)pAqJm0qZmS35GMj6P7A5GMzn_FH3+aw+m0jo!orJ;zP z984wHA!pN1d=>LU&u@vc;}wFfMe-!iMf?pm9ek`Qjg1pjNq~~rP>j?mY0iNiRtL-F_6$aH0D$0RNSeTk?Ai$hZnE=MJt1CkS~6BA!v zJRRRfM*iLi_1_I3UCkzSt+(yCQ4>jgX*of~x z4SYId%gUJcjapK%a%hsGFSKPjiGL<=Zw$|)JN9>ny08g@L~Vy>cq~uiyPY6g_mF0p zj*^@bTenTyL3GMAxm4DpSZQHdSS3Dd{^1bwwO<@$Vv-enjir`Iv{zFd@{B}#Maa(# zVpF_{wnb;MxdUs$H*IbS$5AT$HS+4zjMQ0Puv$2gv}oAI{3pQ$-bA)6d`WTKIRjZ} z-hWK!BQ!d{zWBa?5!De_yl=IUKwJKWN~Cs zQ!oSqA4q?nIUU^I|Mlo^Z&HvSEZ)(ecWsTx?JQG_ScVm4Uvc z)Fn&5hY+FZ>9z5wtJ`mkjSShcBUgGBPYP)z{Ax}l?iuUuj2{`@NN^Lip3%Ey;;eB! zP2R26hn1Z~K;Ie8><`?bw!5yU@gQy&o(IPWfIoyHMMz{0^w~c{1n#x)s;|oEdi`Bj zgMxnkleJj4JLGt#yWJg;(V2`V*E^lk$x_5>OPInk`D*_)4;~!s4 zZD4Z_)f)K2)E0s6m@*{R!a!rhgUz1+Uh{Zi5VAZ7RT+$Y5KIJ6{VDy!67)D=M2;l8 zUcAYa32%R+sYslnJGaJd(IHckw{VTzD8frk-3)mH^#?Ckrho; zRww^FMsSW-Mc5@5F6av5ijHBg^;B&c z)XylD`@F7h&E${81CrIinPqALt+{v@KQx+>gW5Dt)W`RVJ&AL!cY|(?U(V65(q^q( z;rVnIm6U014aMjw(c^);Xen`!T|KQ)7^g!{UJ=Cd?_DgaM$yVjCndY!CLz{1!m&jB zJAE~A0|7j0>qRK>+-oTJ!%_(Q)i#Yee^T_Slzn;)JuBo1et-TM*WzhV73Hcn=7RKa z?J40l;;d@yt0)U}%Tu9VFo}lfnJj{Yc4iBIY>l;BveITf%x;mhtFhviJJm3XRoAqL zY}GSOBwN)yFk*(2=aYfQP1xZj>@^j9z3{66q^}#10ES7~!!FFKnN+n8u|*q`u=OV4 z>UDlSrT=suok?x$z}+=DvkIH&j)J(}oHtTJFS^Xaq3#9za14frPOyjqAbYut;5Ab@ zA=Fax6nBQiF#fWN%trS5Ra+~kucW#pY-#Q4D&l2q>jha`;}={sO5PZ1&)Rl#)V_Y8 z<_P%H#r-F#=%1fYHa1XQ`!uFu#4V&zcOK4t;(~)P7v<1pHeuSzDw~>GAuox1(=uB3 z0O4tXH!<<}NZB%ICaFGxI31&$qxiaMbh`#OZ0Me7dQwTj^~!0v5m3Y^f@TI~h@ud| zk0;hFT8+b~>Z&}a!$zwPKMf3VLiei}LIge+!U&|?^mTbPnc~IZHI1T9MN{*Jo*z(Y z^Zp6@Bhulwjv=wtkV`p+ftgBMUr`QLp0bT>f25?%J7>mMS3C(VIU0RHrt;2@o50Q% zRs|V){FZ;M zo+5>+XaazpbETO{hFw2g3AJvp0+chewjroC`h#0SZRf28O3dGuKJFNEh@V8pK$qzY z;)^P1V7N^dY=#L#_f*g+q97i~ct-{2=Zbg5d7XYoU0wMO_=D2?6F~swiWmPIUI=z% z8`f-jk_h{84qc2oHX`B;h}lLwgywKG^g#Q7U+GwcFuw|~1e04q9AItdrFkP%q8I~&Rsk_mfnh)-K;&X$AP7=eCGjFcu+*c}0)>XbeI z&m*ODC`B{|ZD)em{v|z$vBMUQNxcUg!ki$0Sxfy`SW9BXFG(6wM@HA`*N1~%+btIB zb$IG>JD2uv#8Y=Yd34JWr_DngEoC|rLA;0Xdjm?=AqNfc;zF*VN+x_2Yu>VxWHU!? zZka16uug-Q#a$1wLr@2h58Y+Y-L?51%=tWhuwDb-5!~|~T)-ZRd)&Q6NkNl>+mzpW zMcQEebi_N%{STc=jA^p#aBFVz3n`T!SHuv13EBFSQ?BT>j<#9%@h3uhtrqPN4BeH( z>L|oc@w!0RJ*{G+Ofwx0g*qyO{aSFmQ_ckHElhcOd9_g5hUl!6Q0&MgDbLu0SjE2F z(*3x`Vf&@OfJI+fMFOkmkGn;4^Xx&mac!t0zgvcXw;9%9Ooik^?#InK_lfkzi`hgy zu$#Jjs9af=@Q=hlB1;K;{Mc&6zWY9!PY_$-tL*#)D_?e+bwiGnuRP7^6*8a(&hGAf zn$gVc3ni04l!ilwy%7Yw5nH+}d@6!X2G^iHxc>s-9Pldq8!mx$oCf$?W~#wu)oU~J z1EceCE|>XE;qvm`aB?(QfDCb(vsWxOzJCickE*rspYv8vMHj!d3A0Mw!2TLoN-^WTuB-KA z(Y)X3c4QlG3wq>}yW(xW;Mo4Ir6gw|QDgC- z_LwE|A3V5cg}s5@!JiD~!Eqql>pT1*-naq(hIp#e?Y>IIZEKXI0ASlqc*vYlixB=- zih&B9d>cTHN77AXz6jMf3FM1{*R!qSl?F}Accl`x#f2W>HR7 z>5rz*8eD$;`IDK~cPZVGl)|b7t0|DAsQ_-S#bMxTQ}m>O*}O8dfdNUHvpNaWowb!vI+bc zr=cJQsIOrxE>|MAG&@< zdm2%1!0e0dz2!7JSX-B{@TfWq^A+>I`qrD;Fd;%lkZ~&Jga?m^&!DRxC^n*oM@rnV z-cp}L&N1pQIfSG|8MnaUR>zJxZt~8oq#cOX!g*Uia%x%+R&Hw1&exSWvCPif4YRbq zRrQqZYsJw(|aaDG(PsX`nzePyLxmTCCD;30b@r(OAH z)Y(Ts^N`-4`~~~?fs=l@duTK~fHOSCO%ia5{n0Rp6J zs1$t}OWw2Ify;r_en>XPzh%)A(9gs_Fdaj1>vTR&V~SLt6ntal386dCmR| z{;LhYiC<-Trnsc^GwO}^Z{{DVSH1e6Dqmlf*!RdUs0Z2^i6B_26I&j6O!1+IcvC5T zr4enGQbP`bu*PY#=}1;)gQlXi{+S2k?u+K&;dI3A0r97hT$?S=k=k#mb%=uf2vI^P zfql+inxhQQ$IVfaGanpe8>G3>2g7#aI_|0h`UOGLKY-_gt|<6H=5v13SW``YA&4us z5kH6aB&+YSPVsTtcWYv2;TfEHw=Cq4*37Dbd}&tA!*+JYi5S=6>{k{3JPv$N-`RF3 zIv&ZnqXxp6Bs5Sblpz3*UzjOqHnRjbm<^Pv5g0h%Gb%ldM4B4&>Y_q<5np`3(d&?M676?N%Ao9X zA|dG11ocNUGr!b&{SbEkZS-pgd<%3-jz1oV0A_si4SqkKQR=yO4ujIC*!F1@*b+pJNckA8HA;Md|}H(J*I$6}g0L zK}8d%*{U4CZMY28_%g4SDhY}r7tH&5!DYfE!4)8hPo#x7v8(u)=o9O9o?{}PT)VlC z$(%*IxzT@_5W4oL!$e=qiIA(z$kU0JFB!G6ujiobw*`~Q=zUP_(N=I^#qWI}^~~>m zPiji}(zDOVZ_lo4(aA(q@a;%1q?L{+7n|q&-BI2oXqtKqR$5MGPA~7v@)2#- z5m`CKDZK(e8CN*<%jB?;{U(gm8YboQad|XqFRy49##Xp2$Qu{$^3Vk5>*E% zR<97Tt&^gysZ(`VM^R~&`CUP#sJjR=L{jEMIpD!fLZ9;D_sczx9;@K0ElQwf0_m#| zLn3H-6j1_A*pOr*Wbvp&2K8NGz$Zo|vZBc2{iuZo!`QH?(N7x`)O~p-=*Z)6yQnY>~_q!VF9%7NwNCf#l=C7i73uKbf7o#c-l9Omy(Mk=Pi_uUcybu3Y z4TiR;=ux{yp({+l=>386t@i@q4vKojzme1fSjW_7AsxBz6U|>}YZeO!+;o(6Yp;r# zH0+k;k=d7-L2yA$}&@T=$@TmK zTt~K;VGyw6q#S2QLZRUiyR+b6s43JpqD-Ud>xBAIVe%8kIW3fjZ=nGhs8OAJG1qwS z0xPQH*`#{hCONkjhq#Vq)=p~ixh~g#7d@_vccv7Uz&)8eO63r%xQTYfi*CgGwuH%( zYGK^Q%q>Slv8+F=zLK>)R`t(!O=Z?}l)vJ1YXZ?WN8gAvy^)xy{3jO>=80^AD>sEQ%K3iE zusU6D9x7Jj1)2SUUN7K-Ub9jdq}yC_h<5|aTg(e>ujDP`gWR=}pt|=(@ZG%kh zuBtl*kxjOASY;v{=R}EERWw0t@XCa9d!^QKnJ3HQ`KQ+fLWGoQGcUQp(YYlR&p>*T zc}Xk+ma&Q?^(YS!l`YLPRnTx#E-w0f4r0lcaNxEDf>e_`$fferx~h1r64B6r?m#;| zXr>O8`GZC$HhK9;V)+bgL-94rtwF)w;z$CRBsiU_MI@ zBd^fe`w@?)-JeD5F~3s?`cD7c`j4;xFP!zy+`Piuk1*@}0jxjYo|129W|sb;rkkgV zRld;Et^I?Zo9YeXZ#b*gy94l>?GC7ezoGlp-;kdy1qKf{=Snd82b{HddZdo?T|yLG z;QQ8~=aGwDWhw^|{A?rm72tiWyp@EeQ;y9m6gBS68MvtfpXjR%5S?s-(y8dX z;%1gtG;@eYBk@;mYRu!`ksU->=rIVdK~F+GCDh3E6`jNkpNrL z7st5N>|begb8~A*@uma=)h#{GYG?U)tOO(0L5}K2V6jyP1&@S!<Wk%5g&1D{;PWg`0P?jgF*x^XA?gd4 z^{OGwKekV$`m~@h4iYlGM6pNdiz2^RZVxWUdXuhxYVbdd? zAItOTxn4Fmj`EL0~mhDmkp2=^!2Bb>Pflqtf!sy#r2311uN z#u+rbYZoLNMGe;zO$b{yFz3M`q?97(7yb_kO|I-iWlJOhQP=_QFImJF__X1cOgR-q zUEqfY!M@Qxw+GT+3Q7dK@Si>bMN9%)pq&@*qbg+rpadqk7lybP171E6okN)o5dWCe zO&HXW)Nz+;14>8GbB$`kLp$_GU8*Vhxd)i=Izwzds=du`v`s|* zNgs~c+3B$I$4`yA`cUx?;SR}usJeNEFzrWphkQS1-b#DYP+jo97yaiq>kc!~f8q?Y zjjN!!&oaIT|JBO0g4J_`>5m@ZZvIo+AFR#_>HJ z)U`n>C>RQ?(eWUm>v60$HEeV@j@7NJKLCDPrmjYnG-V1ptCO-ckI%=7;a)Z2F3R!QQhe;mUN(WMzBF(J%=-Q4 zV;Aj%nyU1R?Lv`#csLb0#eYL&9&{Tbr+z=Ebx7>OzddwI>Rtz8K6vi~eHq>}rx+gJ z_W!_)iW5~h$2HrRDzj0Be?tT^;Pi4YC_ZKx`(RjD_zzgxM1<}Puar2Tgt72%)qqJ{Y+w)|vSU~ZhhmbrJr z>dQ@eu0;yB8(TJF!Y3=%D+^LNL73hvGM4NO)(7REv-<{Fe~^m@%=7tvG{^9c9iFYr zR5>y5?PL7wM~{ifVJI(Qsr*8UNpXP5J|q=@?ws)N1F3V$1^Xj+UYc5_#6GKjlxU?4 zYm_;iYo(f&C0G&liyLheB2w|g;?yFqzMFK_)KCn&4>gi6>;t^0vx0O#wP_*FUNKe& zGofqUi)2QvBL2BOM=8bfimMqXp=MlLdF9X7$W{~saH%!^)HmD$9|#GPxPAk z{xF$GdxP#zx=?uk@b1UIdj+3}9`av#aZB+xX`c)p3SUyTi&hdDJLGu(*v~uKrN(cu z-IL=E4Zo>78%^S(7igb^L4;8Gbq@>P{ID`E~3KFY+J(xA2|BCco? zGl=;o@-UGpJ7gCcJH%Dbx*8`P5`aOkaylAzM9JrN1|kBrUJ((71JsdAD7omDMHD-B zn`%QR5e8@@t||Xt@l1XOpI({J`l!@)&y%m2s60#=osrg|2*I3#A%Ytooo7D!cVwOC zVI8o8pN*k2EY40Nf3Sy1iM_gA&B5gU6&XGKL6F-V30pNsR(u%Z|QCPK-?l2USX4SI?rt>R2NaHXmvf07qNZW)yfArxb7nVJmv zij!Zl$cGM#>w7GnLH@x><8qC1ESAxTsOu;4Ho*219sGNMr5vMtI1%7%aX=z^z58@4cuG%6za-XemH4*E98 zfhX}xU(>rw^gz>HM;t2F>-mok3gFr71;gssXKa5pv{4DqVd_DvPQdR?=Bk)IM`Bl1TC1yMp2lZ+@7l zIdZ5opXhd9XFdxNrEm1EjB$+cb-KeVRT3JZMsI|dZ-+9H;ftidCw;~I*DQ$&yFEuN zN9*L0R-lkN%lx2T+6?Dg=8{%8_n%$pqGnj1Dm1c)zX~++fx2$vrz>X78p@^X7h+@G zy?}|6<`?GUz8;wnUvtkF|NGmRoc3N!!9qCA*Pb-L7|*V~l77-n>IBAF_O`&1%;TGf zW}ox%ROg!jm*1bcf4xG*pl>qa8eTU)W7v?4b$;;0w9fB#B-HGAQL?jBGNtm+dKys& zI#X?^=F8FqLW9#ekE$L-R*s;mK)Xt*8c`!xypxIuzet6#9#epSIWztkw{)>N*03W^Vc%zn4W;$BR zbZ%3B8{u_A$<%wE@WKkB=(~S1YH(1@ZZPBiT>kD`!v$NK$zj5CszrAp0HAJ!R^D&E zwKqr#Ms~r;l~e|aM^`O98ER*z z^Dd{2FN^mk(o9$phSK(Kl#AU75>YOA8e@-p9Ckshhi1xUbd2lkFy+|o0}hAmSf*PD zhf-mvv3QKb>(Hl)!tKi)sMIlP7L0Bp(T<2ZMps1Y-I(my{|40#{W^YmAh}^94)%%z za9I(Os%?W$EBsP!>H+Zs-eZ6Fj4$45Z?WE&Ja7j&L$Yp3#jzC(gKk;Bv-T2x^Th;1 z;R|=@SOIK#Wv>5m@kYNguFH+%7RwOA4 z8QrBCAWY%8J3;gitKoPNj4lJ2Y+6z(j-S2Q>^+v)TJ39hTNF9Gh7lZ3cy{2he}SnXXi zwB(FSUX(7la&%??vr$Gt{-^nzIW0c!UIJ!iy~(~q4?Bn7V0 zLjxa$@oPwKx33VBLy8GTzc7$72A8W%!xT|025{L#oE$3G3>q@pWO7w$*x6*I2I*IW z-j;nBY*3B~jdkJ=hwzy2US^O@6JlO+(3_YmjD1)H?;?S#-bCL2!uHt^UE{_K4}(uv z-y!3Ua@-WZY%5CFjCqU3iz+=6gh!N{l}cX`$?x#nrk`Lceq`l)NI-?7Epo?GX~Pl# z+Vyh<{b}=;$tSjkgxgFzcH8TnEswxhIzhGLB2#3I#+FraT#RmBQK2~G!NU;y0);>t zL|3ij;Cg|t;=?q>v^6TOvm)F?{035ZAg8nUTd@!iR`WT#UwA8%MR{q8-O>A)WGPHH z9x!OaihLzQKumeEWw7(7Z;AavFS+vD?qOtQ%Dma{co=ILmx|a#$ zfzO4J2pseXmm05KFaf9^&erEGsBB0sNTP`rL@diaT#;#>;Ix63lxTDb3i+ublY6WG z=MNcwQ^FH=EU6tKjFVAPm?n}Ddm?*LoY?y}b;uGPr;O|!F8d23w^sj~0e^1|Dn#p3 zL!M*_E0!=jl&@Yx-qMBHVUMYsmthsE0>};2B2xyaiJb&;g}^*! z)Yl3A1iH5&#Y}J#6M+oU=0d@z@C{Y^1keHvgb*CAj9Gn*nq-lEW>1_g%6o%!Tm-}k z9}nrcu+t+f4^8=?wIl4CxEwhDB$YiGF7&=c@SEHm2!W~dn`B;CIWE-0WnS=rNU=w4O~<&xou=qiWF4o8%u-Pa~I1dO1bdBe22d(&dZ- zb;#1D%#`S~M{qi|bYyRUPO)CT%3|0Qxkn8jNb2GGiYP~Y1*8+cLQ)C$L3iR! zoG}u*7MKrc!>KI3Ao*^Ekc4_iH0`h7ZXJap1(C>8gMBgKI+R*ANF=G%@DUhH(w&?9 z4((XAI)4P$NyjSYc_HhDNx()26g$KN$0| zR~&n&hpBHXk-^X~QRA>Wl)<>mqGdtD`>Mx%2M%ZtY6OmTL3D<3UFjRJz zL`nO*=+^{>l1E;OlyHg8zmPI_1oW0u#PAa*33Rmln8mx&Cim~fKaUoVF1q0CRK64= z4dR-C*>x9qySi@1Ec9zaRXtFz%9&!v4%9p-tH^oYSo@vf$aUUG@6n+2D)C*8<1qn) zU-WR~&Whj#xMPy90GNV`rx~5e7sX$CqxNQ~i;rCyfp$?5x@I0dvo}rs*m_SKB4jLCK~XyD>>@e)BlPdu{MYC^0+pfl zcF%Oyw)qBVWLCYDyHRD#Sgb+s+on2-5HBljmA3-tg#{!QW+@a!N;w3mEzEckyz-1? zQMd{=z*`{X=#lk`^%==v2TqjyyO6;C{b6N9<&=VhRir!}6?2gzafaZ(ALEF(XzXB| zev$=(#Dr7<&>6S`V6+GZKhe4-BIe0>D|mS;o(15Uw}gaPGR|UPv<6ApXt7Gi#Ht3GY&;=p6KfTT-9=J+qKC4(3pKBa z?z_^5vfn6sItlDj5eE=n2(Qu*l_HuEpQb@?LTrMI?+7zD!uRQ3pm5XsgAtF5Z!&#y zX0C`V(iIF+d{7RLRE{e1#?W5i@`&U21Yc+~H%}dUc%xK~?mfzUKu#wx9TR<^qmQPM z)4fLZRuyT>I=>5}F7HZpTCr$sFp+%bWwBY>4EFGv& zbFMZ7?U?yD2gOmUxZxn6Ij2wo!m*9&m`%-%dos#*uo#4>PEe1^kNR|J2`TZb_8=V* zgrFVpeMm4+QY15n%!34IrGsep=+LXcBfbQNA?-r8hbK`C+@D3_&^O*jj2`)#Io%E2 zvNhWDY0Z{FlqSUd{bl9-{b@f&7xD$nf2=?%`u>ML0w~?O$P}H4Kgf`|13yvD86vZ$ z@r(-9u=2JSs#z9pB2XjqZx&W1Kg0jsxke=U6HY&on@qG%RQ1XU-D@+-^?^nobt}r7 zO5z7YyzuK#eM!c>`dXy=$2ItL^I11(6G}m%msI|x0sk7yvu04XWZ!A5X~=o9dXKww z^E*C9oM;&eP-+j=cd@%7C`dMXGS|75yxf&(?w;z1%3&6bN_G_3@f>M~H0Y zj%qmEu2h&xVF~*Sd|y!xj&=*$-?Mt=IT$rQ@yI9sQVzUAqD}rSjGQui0nL3SpelR` zl>ZR0?C%Tly~FenZ5xgzAF?hBaF>JkV|9hg!g)&QH_%_Y^56>5+^PI^K#;0h&Mx!d z?)*V}oW-{CTAO`o9%*%qXVWq48@z@|Uoc-7DgVd7qUfkRQr;G@+*w;cs9H)z-UC}s zBi9)5By-c`U4(#4_bC-&j2&qNZi?(xrlM@uhwgR5;p~HlLBQA+gtzzic*@O@-h`8g zM~0D3X}PAf-xjI5$t#n+8NKe?ucJOL{HgVw3^(<1#XMKyz9@%2n6kd<=K|W7Q@(T` z9_(-^wDD@y2-&8+Sc?{NEql9{96}!V(J1FgWO~4yJzG8O`sGiiOJbCdMxRsj*8yhR zn`|b=`IunjG6HhsXqI0;Xj!|35;Nh@&D<+kRQ9Y`(4R6aZ(=s0*_+xoJF4*S}bdbXnDBe@T-xN?~^dp0wX!#Km;^0ZyLqvJQW>LPbH zz#1J!u7`XH+UTl}&|d_tn-H@f3m{n|`0qlUDqC`ntP-FBxKXp^N6aXVhI8yFkd4oj z?X~?-{m_Z%RfK-t)f0Y9LFg`cHfgp9Id|<4&Ny=Qzpnuwt7acC5~}E5(Sf~VDl68y zz}_Aj;D;?{Rac5h)0O}GBTv+255Zc6lRqRy`1{)9r%RJ}KWa7xc~ti1$cf0ttb&G# zgZ4E@qpQ%9aL~ih$H6OtylRwjm_;Bk!9-1jz!@Bl-I~}hiG<=k8TY`=eh0>VCs5W~ z#$(miN{vm5N^a5e6EBydw%nu!1Z9R?l1+W+hcj@b1hjV-MDvea*6C+bM5!KBBo9yY zy>Joc3n)X{xQF#KC|F0v$V9!#L2j>_eN@n0!20&Ny7A0(4d@^P7YV5owo|~oqm&5Qt(f>*Qq1n}^VE5W zv2(n;&6CIYiQeCJUNpbpax5hYd8VSBJu2~K0Bu3ZXns>;3_JtyanyCwhykH0KiVO;#ue zcrZ6ly}h=R5UBM#ne?GL8maJgmU>Chtng_~^yhCL^B!Qk<9lpoo4-rl_k8Wz&iz zQCtjDYo%W(=&`WJa_&HgU*xf(&zys7YujsGKo@2Y%B8KLVYe%dYQ?YF>Ud=kf8ntao0UoA z!}4b(k|YasVZ}NUjhhk@nupa@RFZ+%)rV$YFQ2#XMYH>h+0(|qEr8&z_wMWJ>&NZ1 z*1xNbX7l!Mn58@49TB+y1rPWX7l7pqzIqMoYKj^gtJ*C6n7Y8Bew8EGRaEY;sj6`t zz=9a8hpvlQb3WzP@PR8v-2Pz*Bl3Lsv(>9BN8fVyn%dDbDwIu+3n9SAN{ zOJN;pLb>v~nHYPGY9cQg4x^W-sH(#tQ4ycj<@FqTE;dIu#zVy-jjOA+wV|%G%~DbB zZ4xFtwJE8p)9R|RblINLn)zEXQN#9#J_0dSgtT;tQ{BVNL(7?g>D(~X1#u)AM4YF! zrl_L)i%@rTELBx~4X7q=ZI*x&pQi(??m~-_nAOl!-cejs1&$F)?MGi;W{I!T*N%yo zwn)U(4JS_DIBLjfirJ!?mW_2$8_EJrkEg_EXfWmn$gM7-no?I(UA;D@!XRc?JNdYI z@O>32nh+9k{>aP{Egp2Ga9W>)j2e^2064lmt`0I;p&WiV@e*x-OelpMK@v)!C=+Hw zY4ZABooysb%s#-RLK*=p#{xBgHIsyy4aMbhdF-h9&E>PiEu-H}1_r`oM$~K6=G~ZO zt1~rD7PZ*_%!q~RDr2==kD4?AuMwm%YtGdQ1YO)+Hg7(vWX z%=b4O@W}S4TNmbcvY;3eNS-?{HWJhzj+38=PHTRegEOCc@1q)t2zbB>}mwNoA&5B;ZhaYML7w$g#3@6}r+n zO(!wAT-H}xpZuzOBA^YIqs?aW*{rJo=PY*P)7dOO=c@x~mGKxcvTSDGO)#`kN7ONS z{6nb_l$=WA-^GiLS}{4?es>^eB}~TSu{nI6t42U+CK%LlDVx!J%nbOJmtC}tm6E7Y$RA3Ca<&w#HP&IpBSC7q^hTSuO)sIAwC123%!FEw|U zbduypR-N?X2Kssbc2s+saDDu`Xov}VqM;=^}OeItU<%S!pdh#p+jxB07gv9eMhj=9kw}W-^yPC>ciVQL2 zU~_hoFQ=rdPE!c&8S4^HkgGC&Ky}QA-tW^=9~xmc5hWMM=w?8bfv4{aenlQY4Ul&v zShROALX&GJNF>_Q%RUxV>tvh=@#tj0LW6z$3LQ<5nP;O<@lcG0Elsc%q7$=oC>#s6 zb1Ga2wsSOuU)FNq6?5xsz=&(#LtxDd$LA}uay7)u5uL}!l!r_%=+;^Pkqq569?D|C zd{<|Q9jkUdXoTe4=TJbKGcbCFU1)MDmoe{*fPNbQizrNPqy|jopd*mMni+(^qmcS|?Pu*3#LL&W(f%Ok>cCeY;ODlvRIdZ1wRhT#mi%NQZynh81NgTRYsSxQZ9to*hH+>Jz<`m4@5d! z-BUb?J?Da8VHyrql}sbyDNY=z_#>P}9Sg1_`HyfdGy#&VbFb>8p#U}#KjlI=;3QGA zR2)9MY6?JOBaDt5qMIfqf>lwkrK?oS3SY?6K?`t_N=3;Ui#+Z!pu}&Ir@xd9C12qv z5Vp`z>1ir#DybPV(p^w`LDUi(@Ow!4kq@#OiWiogiWgTath78d;nn2;lVjDW2gm(I zF^Xz{yc#}r7EO<+AJ$^moXzA#V{@hdltEG+KRu)y~xQk+QWbLsvhpNotDS-fxae zRQ;@JP&7Tjg~YmXs4VL42Vf{n(}vQDwV$f_;`=gDm96s%%8j(DwG>^>n3`HfO^xFm ztcI%o^ayk^TuDiy(*_I>2`nH87_E+DoS5TL9IOgChj%@unWn}G8$~~%a=F;GNRKr% zcAQf43Y+ig<{3f zM|z$(@~o$ZWmyrvVF$vjb?Ka!sm3WTFw7oiR!Fr@MqHGNA~t&M>9~0Mx`)>=aVOkZ zQl*>-oaDq@LyFD@BxWfb`9ep5R3W{cph+fp*4h+|>S2U2kJLK%eUq8Ed5H8}q13F_ z%|-1FoXEQeoAlh_S+Pu=lTLk~L7yq-yy;nrIIPq&OZwtUx58<9BTO0rj}@0vgZb$R zZN~ipPo&eB`JS>Nde;qd>KWZi@`iN4AAS;%p*K+2{HOHk>ZsL5YtW!o1`zf)puV~p(F_cd@*sBGG&wa~*;W)yL7Udg4iN8MB& z>@ejO>)^WAO#e0ZI@0HIe6W1YycF}k={)@a;*F4rIgjRKyel1u(0glO|F9Qj%U4rf zIj|a7OfBH>hU$EvCOm!t^PVzNz@O^GiCpdb>3Y0$g^iXKwem=&dTr<#p3oAkgpm`H z+4CZNEv;Io@37HK8Uoj71FsqH*f-NJY*~NMLAAx{L~ZHTXohpS>EzEjAFgo}`5>VC zgs>HF#gJ74W~Y|h?n1ixPv@zRxhPf+-j!yV_G{jhV8MVwj0L@#wCEGeJcA-Qzw^qO ztXiqavBH{aA2!`rs*D^UNj@Eo(Cw`P;UIxq4Qc4`s5Q{w+>&K36!tkErS{ zCG&I8RG=weF@LXw_lSB#eOYypf&ML3+9|P1m+7o-+4FtluhWgBs_D|oCJZX4duIU{ z*b_Y6?CSGl)LD0DA^M;C3r}}XbX@iOw$6_3IPh~= z$FJji$ES;bdjL-DZ=e2e!7;TzfBN24=a|9a-YIDU0r@1>HbaLQAoVntCE>ba@kvr0bC!qg-$5X0yvz zacpgBY?jQ?5>NVU!8qcX9KQdX53wJO)UC!fXk_?_E?>t_qOIqsX;kYt#bCitarvn< zTxgv=RU`O%YysOr5Ss3riN}JU>GHGq+1Sh~^sLmB2)GPMb9Tq`W!)M zuHQhXhdseBMorEyQSRb|o(m>WPd2&yGNp^Od>vEOw2ZcskQ1epzQyHN@U1wYD5w<; z^>x)~wJCj$uhx;Ds-!DjeifCJ8dp-?$|kQcUP2>UN{_NqdDM0QdDIAe6g|HujEgGX z;_~Zg0VNxcYaqMEZ*cjIp3+usA-aS7W;C;Gn}g5|^tjFCyNDv-wQS_f@uP_94wvud zt=>8yHYToTPqd*yvOO-pli%ezkQ1U?^xQBPGuxhkPV!6h0lP%u496~0vAOBKF!O#unWKVANg7N~+T zG?eeT{C%3mX>p1rPB6;k1D>13KX&;iM3`{^p+D|+iN7~#m-?Vv=0SRAjF*+rql_Nq z^q^CdX2La>Qol)R>M2@}QBl>s~C&2z(0Dgri7zj3Q_>L8A$p zPSA9MN(d?;sFa{mg38nm;Tq~n{c80jxKzQV3NBM{8NoO_Gp7|7m(oa;DX^qojTC`p z)Fk8vqkY$=x?|#Z2$g@P4TI?CihMy*g&t*e1v3s?QAD`{;y z#%x?l50b=H)S*?>p;c?uQa~AGQC@{)MtMbTU5#3C)HThjpwk7jysELO_&A!iRjbu= zje26<zijvtZ~IMN~B$IJrV(Br*wqy+Dayq#cgNUZSp!6 zD2LtB!$)PVbj5L^A-a8hU~^ZyVg*+swAK~Jixa5f4RwubIq8k;pB@yEi%hT*MxuBbr2HQ`@Z@T^OGwa4DOyU=Qi_&Qv<#!kl_gcx73H()(6u6;Ep~)}(rTl-NwS^|wI#GN61!c|N)##WD2i8=kmoD*xZ+OoB{JHjPDl4xAA$zz ztD5VYw74G*3c`>KM3oLJaXwU3 zqvdJDWp{nGIU)$^&m3WU09q39q${2hPb&|t7QMcbs@kYWJwc8c=vloD^f({A6!E+( zUZ7)Nv#hRh^6XiJdeIdxDHO^qqKNcD>d33;zp1S!@jCirv;bhVpW9GUUbV9EXdhDZ zr-E2I*N5g&$LdxtT}BF9$(qvdRkb+&qM6jO_F;=ln$;}2d zNfnGCnsj=E>5)s1&h+R;4V#4xBcot8s$-GAxG7aYXMmzMKVLojt0#H#wfz;Qzryq{ z_^T$X-FV{FVplF9b{L8sgei4pnJo9XM_Yeu4#}PQs@4IjCiN^(br-0*3sh?g6n=oh z4^a343Qrp%&eG_9{YET2sG&&Xib2@b@TJ)E_{mZN-sya1~9e=-{hGaF# z%0zr@k(qGYJu`7B{s#6*>XLDVWYjQlrNsJ^D1wt)mg1CR5Et4bGvG(2OC^)c`LQ~ zOj0N~te>l%^VAbDd@aqtwKV_M;z)8@baGlra#~t)T8VO6 zUUKrgJWfUL?igsem(@`_wz_f)e?;!{7LW2OS8gW;2K8A$+?6}iyKqD9QC&SP8q|$2 zQK|Ov<+UzbL8^ku>s)y~O&m+#!XcVETp5}r`XZmP*1PK`*Q#rNa!n1bnJ^%`E>}l` z5@ks4aG_Y8#mZI}W_i#a7v^}-T`tV_pnF_629o9dC)2XfSX--WsH7lS^*z2XR-@YZ zovXLN$5Fc7Yi<#p6sM{jqP)Z6j}S_jgK&!uC;aSe4fqtU5E zD=lAf8d8{?Kb(DD?g`U4wgsnpOjQj_B_2LzXA_x9$ZUHs9NKT%T+a<^v^<`-A~ z>SM+e=66^A;bTT2#sC+3DOoYN3%xx^y3mJi5HQ1Zp`&4`rEm1$!*E<9K)9s#_iUoq zpLA~>T3kkZp4ZM~;i}e1c8#FAhJfxU#Zz4)O+KI&<|y@vW$mwZ+GYMdOtV^Fx^#|< z-mt{wm61hn_%TIM>xRx{(W*97|WL&Hy{w=z*&l<1lYaa{?J|UP8L4L`@`8O{EkqrD!Qe1K!00 z^oHrsJ?@0MFZp`V1t&CJX{?}$4W`=nvA|ZLqe4j+GF05v@kE`T1j#B4>M%uzsX9#4 zVY&`OI?Pb{vmgwa7|WvTsn7wTY>ZQS4&XB~FY?dz(;ZaVC)!yY<3OoxX< zo(g;FFrx9jbUS+Mu#XC}pl@7z`eB$K7w?Z@L0o(Qh6Cf`gD@`haJCNT z={&gedhN^jJ3O`2|H z99=U)t6;TCU!&>P!tp9RLDQeuuHBOE=Be>HS)~KrUQ*#{uwI3ytMLW8ucyK@RCp4O z-kER~mUK48dSXa_hPVUH*`Z|VDJ&Rg15rfIQUAU-yTWfaBrX$c1D6DD7;#S*HVJ< z2waDh*T=y(MsQ_ndGO5yn?a1-ibdTPG4F%hTVZ#^q87BpT5x9!ygSynIjF#Z9gaPi zhpO>vRCm|mAm4$)z8h7+lQ^|L#HsiNPLD5PCKIrTIk221!wMFJW|ji0SSqY%*>JA; z2V9(-0aqr6;d(6ZJSF6cD{wE|r#QA3?)NyxX}~0+=0&nwVP7Pt6&{L2cEdhd-U^Qr z^bkQ$MB3nK{5=~9+Qf|)FuV^owZe;0;AJtq1v(@Bi@CaU#Ta?nkE|CgH)!wJ{|;s_ zJ%+y;17D|dkx6gr@NFHwqr>-f_<;^TikK99f{gqOi~mgi8v&1zUNt7miBaY{%co*-x;L5QWP znN3hSLL9~KFcv~cAm!ivNoV8C^(GxLg?O^8m1PjOGEi1nmIs-wEC+#(n_*7m9@b@E zuyY#gmd3iL!2Ug~M=Q%iY-C=v1f_@=ChNal%0%|>=ZbjZGh9+S#Tjc8@91?aAKW%sELJ~k7}^DwJNH|rj={~ zE7Hcw5lq<(K?IlLuL>0oOF^KTfI5;?BuH#y4J51xCKITX7^XKz+=PTSwmOnP!3l&~ zhjhEyo$O?aoQ4T*8#_JLw~6Q}0ow`*>`F*w+aZHp10C3P(23m$-PkSI&)Z-C+l77I z4Wn5r9L?Hb8ruVN*u$`ZJqBg$ag@C$p^iNj*VlT#uQ6@C0)0D5>w}Fx%O0><^>!l- z(4!EhfQA!)d1^@8*aet;NvxqA$RMy+!C|lAK)ity<4tVbJJ6fG8&`23U9qIwh`Qpl z)%y(qML4jR5f?5$Xu?N%ZM3m15#-#JkuJ2 z4(TMRkG2!o>^aGZD zW%m$tKRq6dHMtO7cHr4y@UD==dq4(13_9{&*yP^OpZ9@6-Ves`e3-xoz*IgEiqY!K z<%8q8;wv4P#~#sLc@#y^>&khkaENMDq!+bdH_AE+{$5$W9a3nVci+h#-^cz=rgk^| z*l7jC;duziC9NJcVS5!H$mWsQ=FyPG$3Pc84*Kx%Fqlt(k$hrY+eZ0q8^y-3y{c`` zvgdT$CgL<#FDyp7bw}xX{s3QvPX~+7P^ESD=={=bI$Tu}WYgg)NirQA>2gbOP8b*_ zP`N$AsPtYwu;_UZ;PX|{13gl|=mfv$1YI;iuOTE9^g2SQo#@m=>+m*@#f)qD*hS&4 zR`w=Ew}3+`zuN_oJdxZ2=eEn8hrwM}LYIgjppAWl!S|1X8;$?$iK41}3I@MLX@6^Df5g-N z*2WppqD5zIQKGgsF5`(XZh7J^T6w_hq|fCIxFQ6;6l}f>g1j2SyasZ3E#&e>=*d?? zK5vFWd<~4|YhgTJ2aEWru$*szMt%mI!q0>=Iob<;HeAlnfgOA!T+1(joB4&Xn_mR? z@r&VMehECoH^B>hGrY#Pz^yjZ}^q)Bi{kP@v9l**Th7Tao;v`)Cx3BB;D22 zuAJeC4C|IXyoF^)cJsvCf}t`?21BG1ck^JD6#2_NI4w)c{N<%yBqK{2ek7}O24>0d zA~|tcI>l${8lRd2v~K#b@aopQXRblIcYT#$_2CpJix#mLt6^`3aY9hJgxl z5sFa%7UrvXt!jCEBpe^fbZ3wknzQ4Nk79$o377T2uSY#_1FGAbAcfxy5q=Bmtea66 z+ycWfJPPq6_^qhJZi8d_E~vtAIfln!*ns#(emkt{D zk6b%Ihx4E`cD=HdF&r8AT}RU7##KNsq9hZgo3O*Bf}CCi6XL#(SvN${~m zUx=z9M3rnSBxda=LrU)pSqv}(h?yepCKabX-sFET%UL&If5*zeo#DhF4>KfdwyH@a* zT{At%^gAharBAoO>Vrx+RK8fLx&*FDFtJrnw!pyuf=xIus7NW-I>h>u3Kybd5PSrd z@W-KoKLIuTDV!)zz*_zSoXB5+Q~9fK7Jm~iPkm$jl z5r?r?#Nq5+#Q#e~*jJ)2`%&~`zlwZri2giT6!0uDfOivpdA=y*1H>>sR2<2Ni{X5n zIEqijaE=(s7l_fkTpX8Vo49g42; z=(fJLE%Q)~&^x{3V~T{00(uM2QzXmqw*!A8Jbe5QUdJ#Hha2um))D^1NcEE3qU|4(l&U&hOmFU?P?G>jy@3tro(_oUA4ztA!D8aBw z%z|n$7aGMpI9@D-Q^c`wzE})fFuqfi!8Kwj+$5I4Zm|OH7S-^$sD*!E{0-3nZ;NL5 zP^^M4#2WZX9M6PU#S+9imLyJPA#obZ6{n+XbOsxY@KNGyoG$0FapEE+qV;MWG+vA7 zB=qCG?ckYOq&PG}KaE=r5skaa$L;cQAHrc8_ZhCBJb?>oF=MO)^w4yY-u=*S=s<5b z3NFds3^S3d&0Amq1`o>Z&`bM{aLFECERfsDqJ$!x)|7{D5 zCVV00xS4Fo@JLRs*uxikajD|cj~gm(U_4gD;|DCP#U^xVw?LY>0y>GU&|PeUJ{S%Y z+hK&*0b?;N7T3UBaV?H#3oH}Y!ExexSS@bAvAhw^#I%dWEsE#E)rROLzWaU&UyP$b z2NGevMDgfIT%&lQM?K^>EaH8U*WE05=92Io}v0Gm#2QU~?j@B2- z0}N((&ea#n1q_D$Se9~{mX{V8UOXp0W2bf*ySB^NBbw3l;(75Id$r5hw_V2m(TtWC z9~hr;aJ!5{+hsg5n$Zs1Pz=l~aw?JM4Yz=A;Bt~R9;MH}RaJunEvLJUV^I7YO>IB^$__uWv7VI77i zV0faq6HXHM;@rItS}?p0!&VI2#657QxF6^3K6nSicQO1D!>`0%_*y&&`^7^nT|CNq zh{w>hJ`D1-YEON;Y8mzoap<8<9*+7ATL$E;W+q}m*L{ifRoVBmLp`s zooI?H5VGKFn9eH^vO&@tHF_m_qo?{|1}&gUmEF6 z8|1s`$9^ji+0%R&rI6Q5qh@y6KlGUWUWOE6_{427|>L$k4Z7 zx_CQo2|dG~C^NWsrjd!$<2a}#WkT;}X=PH59i|hZ>#*JiwN}760l73Ms7<-3254$z z;S#Bhuhc%x2Q9Fc$m$OuBhkrE<7-OKDKtoGG;D^9D_~@Z=E=UDP!uw+fB_*A{)cu# zL;?Gjg^VSI7VUtAEU!S>cN%T~gh(FK^R=Muzc9v+;dDYJ-UCOx4@u$!$Q2(#4}|l@ zCn#{AqM&_-Joy|JihrR(`2yC9FHxC%1y^Bui}+UYsuBX!cb`|+MFj*QPe2m1Hz6Pw z*SPgcKnh@`#*Kjm8aExL;R-hs#b6<>b&p5Lg!PcEl#hiR7e2?!^rppYw8oZh8$W@7 zHhwY%nxQvl6GMY3`EC3(LK|)TbYl1w(e&uJsGMhPhGKu!w~}xeOQc0z5+&Ult;o7nEt#R0k6uDaoaYp`9t)YKSZzTA?gp?^>B=a z4SG1z>BTlZH#cAk(T_pq1(11Ho zI`Y5)dt-7cxN;hV<#gyOXJX%qVThcCeVZM(_cPMY3@)ww*2l}dNvbux$1s8y-KBv{SK+gOwK1c$u7V#9Y;_OK}E6$cFVf-O6VAt z8j`zI{hJGoNXS57+b%C@(>4gGlx;DB?2timzoqI_KrVuSTnr((1UkwR$djeeQa*(k+k`mSGda6b!A(B8-GBbc@19kIFQD z4Y@03SbCrnM&D(5*ams_5SY*KQJCETN2X)zAoZ9!pQn?S-$OqwM`7oRzAA$4aqj0Hw47SQAV5fW% zu9r{4t@0UYlh49^@;P`|z5q|jf4~d!C3sD~4DZTU;8Xc3d@bLA-{qUkkZ-X>`34Kh zw^?`jPc~4#!^R*yUcSqw$`9Cl`5`NnAF<^K*T|3ADe@C`q5PEXK=^9;8M{S(!CK|N z*#q)x_JsU~J&*8<@>}+a{Eq!3zvs66mM6#`c&hxFca*>I!{o2LFT(xhZ+xu$ozIqk z@Ct;N$^E>+5PXec@QsGaw_&*5u=#Cn zp3pJ;38l-s@EQC`rOOZJllW80(eA^?@~4%fJ%}I4pHYtXLY~3@t{m;9Jb^!pkOOPj z&-^)r0&p_>hCh!`0-V7<=Pw}S!g=fiPG>raa4CC>)0s{ZY-KO=mk>&Zo$NXOGKN98 zo;|@|K_~@oWe@RJ5lV$Nb}y&1pES6SwQ@T9Nr#8oE&L6HLhux8;cp_80WYxa{4IpS zs07d?-ge)``zg!N(3k%YoIOQn zP!R?dVNel9ToDEpVW@lt6%hr)8dUybh1bltH^YMe#dG}6b*B;{&ddDczJt6>btlL` zFVjFT)5wQRqX2S^0npnR2*Zp)Fw+DZqOO@Nk-#x(TGp2)O%!sqeai^fZr(kPOfuIjmt?BgAv{!?mD<>|tEm0Io zQD}%lGm^$Xq+2;rcToF%jx3bxP3HTCF|?u4xp8O{aUpXHBzg`1s0D5bndVh+UC1=H z!?cjx0?FBhR!*UvTj=28F=QYjr_jpQ2sc+HW*0hQe$ks8~P%fXM-^2fN30q0<#bW=2+-r zEQ0RFVmRC=fg+<6g{BOK8x=6kSc<|^1;-dQP+~N~Qe!pL7$-o3aU!fV*1>AyBv@yh z0;d_L!Up3sILlZM=No6hMaG$Msc{xuZk!7{jg4@VaUR@dTn>AYFAv~S_+eu!JZW4B z&m#9;Fm}L8#!h&{xE9_vTHsydI{3i25xz8Tf}f0=88>z@*SLekf_0}mlq}H~#>A*t zAf&|tAx|s>3-C`-J4!H_#Xm#H0EbEbxmua71c(1itxPxg&_$?^J!mzU%Coj{2^EDd zh3*D^itJXZ7Ig2 z7n5Gh@M3ga+s2-!eQ{Zi;)~0SH))yiCRG~>6bwzsN(iPRJ!(Idfx^-mh)g47nntE+ zWI7?!H8NczLxc=zWJn`32$`Xg85$WTWLP7^8ktGROpVO+kS5|x4`q573o(|5u{;bq z>3wVuW9yWo3k8Pr*WI&Y9N2X*dXG)J)nM}xJjZD_a zAR&Vq8PrIJkd8(=8W|vDKqCVhnLx+{jZDzUEJ9{!WR^yDAY=!P?4Xg^gv{2+Y>mtz zWR6DWXk;!Sb2TzoBRdkZqegbr$j*f9tdX5HvI`-*Xk-_S>`KV48rfANI}x&zMt0K3 zZV59&ft!3q`F9wAit=vAFz!K1dN1S|_d`Ep9}G4ggd>fIU<@v$CmD~Sa(oeV3XXNVrX888I4z?pN>j==9!(2h-k06gF~cpY@){NcU-! z$)~l%NAY=@+6=jiwA5V(?C+TlxMl#d%mm0YUFd5j!I5S%Og4is(@cd$W*RIv)1leS zfD_FyoNH#m6=p76V|I)?*SXgBb*}Y&oojtx=UQ#lvS5hXAHgwz5dRTP5qVfMqdR@p z{m9`XQSA@Hw(s0a+H~(#-d^_JdjpdR*-NF|$$yIUYK5KR2zg|}IPavjP^z02Xo3eS zYY{REvX!+6$$}g@WKobt8HB1V9Tzgz8>~>$);8TLc%lcHhDSW_OBH9fz@(5_Xth9* z%4ik{uLKJLbl^={D0PC2CPP9wZzm_oHjZq8AbCdtc?7|7m+ptD zDz^N7SkXqCem~48%8K^G!nz90Xl+k;>kziiU!_pVv_>Jrh9Z_Yyvij<2YLt|%8vO7iOM z@6zi3lOR+u}!+iZPhWYwq4D$`Z80H(4*(tOCip(yV{Z=d;GC1?_%swkJ zduH~+$dJr#nS)kj_Q)K7kztvGlP$l`xVYPVQao!uC0;Q1h&Rn=#k=Nn;urG;@w@qw445y=ObmON zugX004cXV+BnO)6MIE0E_wJivR2LWcoxrQuaoiT zop`bcVp|e;Uk>aw#JPMbdq<=ol*nt?10q$VK@vZe-6YZx3i8X?Wg>)7D!+-HDl!mC z=MS(N5k@G3zs%-}OoTG|FYun~M+Xss>qHjfvc*wwvFLzMt{4aBifn{Bi79Zp$U&%! zm<8)ZE<)YJ0$3$FBGf~aLcQpO(BYyAszhgmdWw1|6*K$Av8#AhXQdpLW9N4Sb82pL&V*XDS9F_Ofu+>t;IG= z3p$Ek2xSAOFK%h4=r_+PVwuYAfvytpW`;pGX1@ZOi|$7 zwnu1yciSGJf!=L`bOwMuMcGR7JJ0t12)bq0hT2X{rZ3y8r?V( z!_+=Br|-XMckv$703A`|R7E!c)Ot*<_j7T*uhv}ZK1?XT$W|-nB5#dc6i{oYq6D>k zEOOO?u_#e35sQ*?w|#!k`J4V@Y@RB3{%P2z8DG?>=vWKcBLN~6Lw;e zap6EE$!}UXMHdrJTdoUu? z!^apNriI_0P?V8CXLPF7ayv{!@MW)c%|&T`WK45Wx*r+WTol4Ok(+7Dk)i3!OOdIe z<)ua8a5!PpHin+y{C1sG1;x6lii&l#D1=?26D{g-W;ioJU8YJ4XVw-G8UswDAoOQ7 zlDqba?t{4<{TaUx9@}&uC||4-l)t$sBTVlde1LrQirEp)*ocUa5V7%2G3f#|qK6vC zF0rA>j15iZ!9#;hOkIxbF3Rj}#t%~FavTyXevlN#jvpk#kP6!dDPfa>0PUAu3BMxA z>#7(+cG5AaVktUi zfys%4JA|{tIqfocAaX)ufN2!uAktlqs6-r?oNy8jOl~-rs-GFo-55^rIEg5q6G4v^ zug9?>X!)opFM_s@(#%*NWT7CUF52b!bKf6ad?DA=yfV3@Zt8tsr!_QlOWW z3I!G#ODhB;tPB`$g<-0d1v9O~p~}jG0N%8Yg?Ft*@R79`KDWx?YpVi&u`1zr zYZ?!M1_NsLn`_Nj?KCw<`zglN-Zk@>u>l~hLoy)sf8+n0sJ|Avfz{gq_ z^2ydkyx6*!&$lk+HP&Uk$-11cvaaB#THE;f)|GrKhTE*G_zf7|WNqcQSUdPV)=s|H zx|%<0weXLv>-neF4g6c{M!~Ebgkjw-TzZ0#0VR;%b`wTUCGJz|=5uPC?f6Ajj0 zak6#4IL~@OY_T2`JFJJqb=Je;R_hVbW<4hEvmO@@TTh6mtS7}Q)>Gnb>uK?!^^EwJ z^>^{D^_(=V7i6OK51D1XD7#rN$wKR8Il+2GF0{(zGV3k1RlkHxvaE_4B3TtRL3gloh zTOEiFk@;edIuIQpdn#k=!g$$L8QVmdDzlZbO@dp*J>nR3Ao`_Ps~p%M{31%lTy-G& zyI3sd(SazNj855nIuK<~!BBJ(5#s6mXb)nqq8qr74oP`8KE#9AhtOFZOUI?WfJZ!t z-NtVci|F8#-NCOHi|OE$4~NH8$(bUHjTTE3v;`g%B?x7S``{|R7NHK}VYr+hk5IOF z3NA$FG#PTF33CM9&CEqtu{`P^F#0z;bYiw$Z{PPZBeX?Io3y=YBfgKB-pZ`zjcW99d@qG@)7HcV;Dwl{6k_p$SP+tIWj6>8>ta887_aC_5!wui`# z(DrR_+ROG39V4`L+ne^WJw!J*&Si_x#Y5{ubX-1$Zq_Gol=Uerus(yO*1ur2^#z<| zeF;{qR_}PYzoaRBd8KA z1ab(l5y&MVNNFAO4;&L)K){xeYMao(wxFwRL&SDqfE|D%>;xEVyD-g8ircxI?zexs zsMYPCuC9G@g{xCLmjPTJd1u3^FkFojy14X_S}nn)IDT{;ZlB*fL-)?49o;Mw#Tg%2 z`QFJ=mTBgDr!XX2S%xHvE=18G-#cx}GOc{?RK}w)h@vY|WaoP)P+6v(@14?k6edx4 z@{L@iNKU?YV&kD~LgnUr=QSQGsPc5o_l|1_7vttA)GJ`8Ave>Jn;8(Y!^p)97-(n0 zU^@$DV>rj|0Q2l@ScTzgI|oj;JHq95C%Dn>4ENhz;;sqq^SQjw=kh+E%lkB!32Iba z4xpc1ueh8Fw(n zUhOcp)6H_PrAO*lI>f3-c24y53~F(^1nDOj?GxyQjTW(0y*I*mtWdw(I#Z#H=z9R6 z=%HySzfz+zqNofX6?e2+sW;0H%1O8bvl6a-Uf8@xtf8PyoT%{*MbSB)q2mEBJ|-GZ z@Z#fUcs-T4NF?TXy>6nB^udr?`xD&4H+iqkunuu-h}Ne!z;RI)S7{U($d9WzicH9# z5q;aHIKFm&c>dp&E!&lC{68(*XAfKT{}1W#TG+0T+ye^9jV~lOR!B^)bX(h%LWp+7 z5F%DiNX80^N#y|-5$!Qx+hb9?j6>}*9=g~Q&>l@h?J^05+EZY(JryR~(@>Mng=6h` zP-)MHI(q@Ev8!OCy&SgNE8q^h8XmK2;0?PLzD4{Gc0K%VAIB2y29|3#vOab*8*Hy) zqwLjeioJ#{wAZn6`y^IlpUh6RPhpqYr?Q*u(^#v$p6#|6URZrf+` z6#E>WV{ha=?DP0g`+PplzJQn87xEhWB7VGm8DDQ-&Nted`DJzsztO&q@3pVz&)YZf z5A7TI&-P6s#cmPl_AZfa-!6LDcZgy3ZZXMj6SM6-Vu^j1sJHJHC)@Xk3+(&E7JIL_ z#@;8|><7eS_JiV8`(g3E{fPL=emwRXd zwGO@zCo5gN2HqE^(6%z)$VxpNzl_cGa3JY_DQQi8I(j!Dtn0Gu;Vt5PeVTG}`%8W| z`9pA;=IQKuPxiAJ=|NxH;jKgsZuq9q1JVan}r&SrKQrflEL zE|7((e|h;@?GGs5B%DAyWXj76Cxw&4LFL1=@wSk~uZDkNdAmba!K3gV<%`~iRQDj& z^+k2FQQc__lWP>BM+QB@`EBAxrlxCApAcCju&Ki1TR&27(&(YCm4{L{tFP@WY7-ly5Wl;HPNCJvKyoNWeSHMBZ-MI-Z%6pNEhO3X z`EvoqRQFYXRR>j%R2Nj6+r-7{iuivX#=W|*|D`kc>5JmtebL_Ik;ik?a|SpK}cMs$;T` z9E*MH*y!~+JlzTKJSTx4;kbOdlgP`RB!0XTwAE0;@bb}hI&kuw2A9f83EE3N>@b7_)k~VV@fDm1|6y-drC%^p|w9zYa8H!;TY(v zuj^Xa`_T*U?6p7bSWIjAJ-Gf)dl1uUep9di)27BWp5LbHTi7&zC|-yT1sfI}3f4b5 z6zuT-%c0OO3;bUUKs4w7&UW>7L9_pMLG^!PwtlJLuUH%<`3uJSuN(aO&x2k!cmWsl z;7mmYJ`IA-bjWgMLPw_<`Z%-T2xm4-a*lyYXD*!L%!6&te7MtD0RM0n!dK3*EZ{6+ zJ)FgCq*KBsIi+loQ^v}ia#rJ1uydSBw#`|}o^_V7cbzJp<}BwuoE3b&Q-hYFmNz?f z{6eRm|IIm$?{ymZb50}w(rHF3uu5b&t3{r(2DSfMQR*Bo&UQ`^Tb&cdW6nw9dFN#D zzH^HB&N)?@&S^62td~8V)8$ZSrX1y*EhjkMi-2vO#`L$W{g>rs^kw;MdAPO;ePp7x z3P*@Pv{jfSzS35qQoN{afd!|CyOb@kVVl^dY=HxJic^&>2*5wYQe_Jg;43jn*#egZ z(2i_VR-p&lkt>x|7|DNDwjh~J;$JCy6J(3{o8m^c7ae=X{7>7$(fU(|tFnOQj7N=VlzgTOiT74N{y(;$GHG^o z5cH|5oOboAjW_2jFr9yc>wFCv&Nqcb7r&%m8uaom1`bmw>I>ihwD&VJ~F%hdq^7PnJ4$Zzl< zaldZxAhA!si90|%;O!LBf4tJo+@aY!*xQ_$s)C66MoX~@`V@P+%IX^NZIpDImvmcB zmOSutj{y^`fCXs*8#)9W=o$z>-#`Ks2HZHV4)z;4*uSnjSYOw*AYVKPx!B0A5E2hT zp5p3#Vy|xQ)A~~xl~MmHM}6xcJwFzgDqb2x80`_+2js{;Fh_PYN98Sk@6^Xj105h3 z$cD}sb_wJ_e+&x(xiBiw5oTgo9OwjP7?vYGc0^I>_qNjSZKdw56c0x~N69}zi3;L6 zV``5?`l^b=r`auRlonat!)9rboh}~f5ti!p<#h4bin8+xosbhWgXMRMCkja$e7qTM zOcT$90vl?J5)$Z|2z$3Mk<`Gu^iFbNlJ{nEazuYt5|zmHkzhib_`CkDZG=o?n|M|f zCet?@!q)BLxv+aqe%PS*Pi`0gP!V%^DbnDIE1?u?YbbKpC$ms;D6nJyb6yq^%OIlU zs6=0mgc7MKp(LtTwV~pG=6>uo_hX8+iC08n(*M+sBo<2Y+F`Vb*Hm>M$KcjSp;RQvy4c zBt1!A0Ao}A`%qJ(UmrzCe|?lq6)E~Y)Ku|?dPCM=6U3Y9KsbSo7H_Eo;S_eHcw1T5 zFdHoXsjO>+br-)nF`KCEiok^=Q~C-dAg`sjx|WfS5#>2j_?n5lVvf zP^dIxGJFT~bdDckj?VErOc#WGQ;=uDlXaWZw)Jb+qQe!+Wzl; zu@C$5MVzS0%82_?apPv?t;}->6ycApIsqxK@vkIrsYAVs#5Q-(fQPgs&n}#vksB9; zjS^9<${U5GoB{x6?A0$E%l%|6+=ru*6V%QSh6BV%tzt`epd(>)vQV9*6QaUH)Gr<0 z8j;qZhg&ZwrxbNa(dgP{4GK-*6q+DgQVoiENokm5Mv2XaZ$;Tm3DIH2i*`Kn18A$x zL>K)!fEMff!FSOb#qGB~3!7coCVY=$*k%OtAz2Pl+wQLpH1lz~Q_ObIPDnT583CMM zaF>CSfn5e-yLLHv&;5h_J>?JA!DxZ+g`D*WaML{a^_0jKS|$n2+T8wKe@tjq!GODb`bTqjU zg$S0=AOogFe1ImQo%*cV5MfJ&fuGo5B2x5S@XoW`Bqd6jeAPYs*&RiP=-Tn0;W-NU{rQH$2^TD2s9^`?g# ztJHJd*e>!E+C7k0!P_q^$GGMRdm4!N({Jh3|#m*VgSl&gPbhuHbbp?7^M z);^M!2Nwe3KP78cSM-3g$XRsH`Ma+<`Vbb@YYfGEX4$;3-1X>u);apVe4K>>qXoc< zOL^{@VhdJTu_ihPAy-Meq-Y=drbQyRN?B9iWgE^VUnj@VY{L+|54rmW0}3Z^v)=IT~5%DB_%zas@RmuU7~HRPs2V`AxzMXfb#bj5P)<)>c! zArCV+*+}F%%5Y#1MoEUrTIwY*gS-{X-wD6arLsA>W_5%?|F#4Q!B0j$+z~7r>{y`$1_$H>f+q;!Lv?qjUl+{hJBAy&ati^Z5=&<_G*2d`8# z@Q<1-*D)IwzWTHpK38Go5}}e)B+E3$8wB@Ec6q1?Xhfxa6Qwy*|8@PQG>=VbIRgI9 z=@){MG1D+@xV%%C@k-};+zNEoPK>8s%=`|>O)c&Umuw6A=a%rbo1bvqEI-dndZuSM zPZ0QTjPP@UpGdbX&Lhhi#k&g5inPG2 zx#r0zJ;$GH7`Ni-vrqgALDh<%0YFSG7p5w8Ro&RSq?enlUpqZPfAaM=be*6S%$Y3V zfMyvGYMeoYMQv)NVpN%ri-U`8tp$yWP*bKVn%6?WQC=!FTvd}LkZ6rc&Wc=ZbeNwi zivPs>O0ux{e6j=l>Mrt?o8XW9T9)81ewhDN_-eh7N{KgIIFc)$c{ACtr?cH28v02v z-bl`=Ru>@Xk}8NhDJJ1WPKZNyzAod&$_=uj*zOm4vC=NK$Hj$#+ZC-zTZOQ;9HOmYvN8;Ew%f=kPMUmw7|9k`rYo4d0uQ7D52oU= zEQFPzUQ^olQ83k}dNEguP3~Nd6ocU9197%>Tdu4mkh` z1V%R`4h86T_O6KJukcr78IMcjsl>x9<$soCQGz50tp6Eg(ca@cEwWbKW%hvtdT%nq zOCL&jCGK6^!oXgEG<}V_+Y*hLuSLm7^A0@He zpvAqhW3e#E7j#VIc#0Q&as){N#mMi8NT%ZTXGmERMUjSA!et$sPtQ* zIu0HrcE9!kko)X0M>z*3(^7j3*&Uh5r&EwG|3=EC6g%V|PYV!xTh?dqZO%jj?9<9G zf1FAcAV)M);QbC2lkYehZ(tU4BG(oSLF?(V-Y0OEh)-{9BYl~nD`|`3o(!?I^f|D1 zrz|sl!KN$fGoN>=&dJ^^yT-bbmM3H_bA9oj>&^w|C#7|p9Rco3oHJ!_PG8fV;zZvj zHJiFwsjH1#@~mivvXd?Oye4qq=3Y zRoZnOZj21QoH8&KO<>fZuo}KJznt% zr9*e=7w3-9VYuzgo7Gc?Y|$^3HkuhecUg^zc*At@>sk4~$CR=FcIFJr4VbL~@p+`#_Al6w)BLy|^)?|7oTD%J1Xf|1aRBMhJ@sIqq z5jlUACTklmLD{g$=6N6Glm7x`fMV4g)l86i_yk{MPQL!v^WqHg9H^Rdq^Byqp$ zEBI5FWZftBzNSrK+6VmC2Sw|Z4X&weUhzr)4D%fiJN(7*sf%Uq3n$m4j~vD&Z>HIb z8@uSjm)kOxp*7RR+8T7p2DCP|WQA?@?{kO`_Ianm+=c8;rp$$| z`*!!_LMQD{kw7c80Z(g@MPkK?j0-fz2w6%OLUI>5R`a>oOgUOkxlbzBi;67^fm|Gt z=Lf|W?a8GO=KfhxFD_-wxo0lWG2muYihorm*_0_aWJ+w9Qyc%9AV`{KPvD~$8QF9w zWmH>mJECQvehQa)3ox>%ny$30k-s_EOYi?HH7b+OPBY>47I|EH$|&}7QH=-}_Af`^ zetPM(u!CB_{RpFnOuMBzGSC z*>rFQ{8=|mK23GPs~DDUDnuRjx{fBlx=w1DUe`f6?b&dTRAYMuLLc{EFq)6$EP~qI zQv6#6!C4LRGcDj+U4lmdKqr}U+Z#GCroJ#zwV5s&(^X3W^{nx4X&g(?(wxK9Ev}d( zm*kYA>2YIoyVhJp6Tfk;*86M<;FsCCHGOp)n+LIbguSkr3q zpaPHVP>699rmx`AAham7dPzRXB`eHCCrDB*j6|vbuT_E#jLT%8caeTRtonSYRe6xh zZ}8PJpeKlaKPm%zu*))#C$ayS{NVNSpqFL9PnH3nEd6|N_444CWuQ;YeoCwI>#$E{ zsFycVtAG9dSGyfkQaeAi!Lt6oep#r9r#ot;LSMOi)*0|(VQLlgeLHARp1LZ+ly_X587M@ zv91n$MJn*lRnP-wp%2;o^N4le(>&08CG@fiO7#fpJY(oTeYE*!>f$;T33+7+f=U{% z3L&q98Kg68a6Mh%ZaMJVd4BMDcHpxkfj4wQU*?1_(1czzi8`Qpf3SJ#z<+oGUZe@V zpb~Xp^KGDKT>(E7jJ_BNdf>%3AoK1ZXI=hE#XsA7X6_d!;r_#R0K5B05wLPmCcp(* ztR3)Ai?9bmVh5r48&ZNFs+a(1{vzO?7hw;)L>=UR%prj{MZ!eu!cM@cDS4 zGdOw~S6?_D2x z#y3|F{ERk#8?G{~uxQ7p)FUU+l@{BmXT>dhn%R77a~!821Y#@=vT7sFX`CS3PyYvfp7Rbj(nePrME zBOej}<~V-mo}_b>MB5a=CDqRNj4|lcnTHjRncW<|I=mSC4kq#hXmQRjwQ?sh-84TX zeAdK1=0hm|`W2y9V0j(Qvf&#^=fFOPc0CnX5pG7B{{KLU5h7AzPTZ_1$IB8eHIq){ zPEnCdQ_{LOmWKU4prkEZcT%Bj-E6)GY>%L&xeMI(QR6kk3yxKlZk2vSIGw$!P)M4|mhLul=HRS5p9U9SUry~2Jl{46>H%QVqa?&?U(l>U}HzeR24)9G2_{IbDWnV*D#Cs!otw%!?_bE#H|4#Z6 zBmIn(dc#Sbv{#|(W30RHEZISY>Wn* z4Qh0&xzp)ajlDKK5APh8`xcSCk>m-I=1E@hWLNTrGv!G`dg8-9NS#^K#gKVjS!Aip zHTA%Bj!Vxf)g@j3s|;BG;Q&^b&F;qb+Nmm$?|J$cyCS&2^If0q>|{*pLZA3u zE_zR4mBC|(LC>h_{hIDqML^SmXQ;~4wHE5q*UN!j! z(&0?0tx%^{qFEzVp;f|nHIb0f`~0TR;7&Nw)7xK~H?POP>+BFvQEfz3RjSxzWv{IE z^o-fE5>2XXJ|%CnPIA&>^gB~8^UhtgcBG}_Eg+|NXH_Bl22ZS%J;SOeF|fw`N_G3{ z@#$VW=_x2W0?IaxwYg^(q-YjyWCZ?<(*>!~r{pal#{Y*q-JhbCD?ZJAcB!KMtA{4P zQm$kYUFk9PIm)L}j!HFNsM0U_Q;Fn4$3;)$^mj!zJH#Y^+O(KQ9DCgK!!!)4Pa@R| zvFfd85qtc7iuNq1ZeF%}pGHXRWEUDkT z4?{{4+uvYxc`|IJ3{)~@CGR5)6ZW8w)b+v2Nr#1`$mbp=*#Vs_UXAod_dZ!fjIfUyrp(OVxRa)n<>?CahKN4>&lOfB9Sh`sOQL4?d6h-;fH@pkOdS zKtNDHamwpF7>ON5RuDiyA3rXJAFqRxy|JmYv!$Imy|KNMDZPTYlc9r!rLnV=p_?I- z2td--(A-qm(AdJ1&e+D#**R9t-bQ%^?K{`|lEX3Y%Dj#~c$9KVOnToer1X!ju#~!x z1zaJRlrXgERnvnJPE77PJ%Ax=KCL0`YiC)uTBbOwoc|warC3y_tZIpsa*Ny&ne2M0 z?`4^#62F{K*7&sV3=v|h8G+AC$4Q>^_07k1$Mfs6y8k0lK$ilPAd*t@lGJp?Qq+-; zeXWwKmpFd)dUB{yZR-}F)w8W`HmA`^t{}I%gAf$rA7P_w+O_>&YVYxhj*wC<)5Kh)%VCU;0Nb@yH;-sg7mfU{eCW z%rIl>up^Ao0=qiJA17-df-H!K!=g=3_9{p;%Q{!4(~66S9Z1d7#jdOrXK+RX=z?dP zkgG4`L{^wtIqkZT@h`EbT;lJ8a%^FH12=>XO!$XAV^l%*LpS2TC9S3Q9ke>pLVJBw<45*h(p~%aiVLn_$AAMWGs;E6}$&2i%A~FFfT>;Uoi`j zLDrkpgp8yKE;LpjaT6ZXil>G216zbAqRT!jK7%CghYStz+AljfGA?tJTxTfob0`O{gwBwq^xMaNT;wZr!*O~W z@M&VqRT}CGzwi+Bo8MgrA4U?h`WCH0=5vW}tV-{nxIMk67ws|je~ohqp0B=2pPD99 zCj#=VcZb5BJu@o8-m-6bAd-$N4;*R!lnP5O{A)QbUc0oWm6Q+R20PKtu{&y39DB%# zTVy;YU$be+vnqK!D@W7)6(6}C!Cq5Net;c_){s@BL3Gz&y~bnQqEV_QuVqMmy%Cqc z=}IM}RvdVJ722^RYl9VAVP>=IYr|d=9mX>&!sso zn7t@gvq7}Ev>dM4k@{FNo}T)Aj}^y59%lE2cy}0imqK&SI>29VYzOBZ^2A~N;H)Cs zQ>$foffaF%6mjlCK%`nBn92G0TfiCAmwvgSDUggMoOWVZINGK-tzoYGxwD3NO8WgE z%G~iWlxsNxV`nujwq}@ni7#G;iZdQ>#SYze$gYC`i()$t>_z|*fnbV0sS_bq@Jq zQJ6a-sawNNRTJ*?Q~1P-;q4L5&hV+`;3k)Zc%`(mi9IZ?KVzp91Z5~6yk2qgvp63t zxd)n+56mu!^7E#CX?({grwAWBpQ^|HD1H9-&u98RSzmwo6>2_$tPU_#$@3L?Ka$qR z>8t$wMB(nLtV9m&{A8~%I7jQK#ScTOPhOk3M)_6BUc}FTeQWeg+gCn(ptuJ5SNc)j zC#~`w=U4RI#=Jp(2L<~C4t>Cnwb$wcyp;IV?w4tLC5o<6#u9k03_amf>v2cuPWw=y zUC~GyvHKI=RHh3w_2|`ehwyob?U%t@(7Z?JL!v7Q;-i*h5Eda~qLzc=RoI^*(MQQW zP~szPM#?=nxXi{5aA=xM=lyB9r!<2gKvp5xp+IbyDeJCUA6+LI!X`2iPC{h^+i1hy-xBe$smH0sWpe}vBJinW{nKfZS0YU(PKmm{tICT(_YfPv> z!t@ZFI@v}^^dy^2oA&A&trk5En+ss2f!`xk1qzJ=Mdh|j%T_hEwlys^ORd}MUMkkS zUpqJ1ZOId6pkHrg`Ip`gaW|j6W7!q*eqX=R9Rcaw1TaTq9-X*%Hfp} zL<`y$qDH(&cB3ntYy7EEO>-cW+W2E2EnVIdj2KJu;Y+@(Pe>ey;fFqJ=F~CPff}_7SPA_*Fn5Y)ihKl6&0(1y0G*Kc#UNqsb zn@BMUEEqk09g+J9Q6i4rV99J#CgOWqC0WcH4nX)$3m$#T{p zrGw6W6%21O>;>5lGwK7Xk674tgQ>h{h+)G7YoVjhG@h*C_{tm9>01a9?j#NKY2q=*2IUo;lfoCYtAyc) zMN0TwV?oZI^Izqe0eKP&6ra2m!nfP`b-DfN^D(j!QwY924s1dB)E=Qd0FlbY0)!wOFpxOZNV0b zJ1opYfR53hS>?3p50*U)5t6;K!QTz|-}8=dmrDjLoZAg;3FpNwH1S&5v`$xLDoH1r zS^pY6CvFj_G{R}?*qkmcu`%y7?Y=t%v>#U>+LEBzZfe*L0uyY4Ldv$MuR86mZ6m?8 zYB@l`C!>QVN*H+iw)=7i?a0PnJ((>5u!ymkjGwg~z^(y8>qCdSo`>O=GI5DM5iDeJ zV@BvMLyp98?a9-D4wII827~c$9$@Mjj{~3#q5k-dyMW(JT0`1FRf9bLBEaJ(iQ*i1 zLT*uD{b1seJ|LI~OYUO!@x9Z9n`|2M>UYg=o##(ObAjhADv2rS=Jhoa2E#%C7R3^A z8*6yr+8eJ9ld5{{!FwO0K|76Z%o<&)15XxBO4pr_E@BSh7=H4#+sm4Ft#{xXV;C-R z^s7v9&tC&U7#=r>+ti?fEU0$QF`(RM@$jW>8c1TgTzE;aY5mgZAE`3}QohpdB<(`S zG+bDGjtB@&p>4J$|C)0BTT>n5 z{aa=C@IN);nu`hb3it534It@P*;3W-X5uQK$0kP02K;GWprkaWzgq~=Xs&(D27tPr zL%~5!5$1we>LvW>2wMh9mkW4O%e7Ah?`5!}E327H89%n?RZo|WMuTP~38KTBIWt}^3g&;=xTA+^;2Ig0@*p0* za(pCFF-#5Gw9cz|*EA~6iIg54ZB~}H^n`+tA8TgB4_PKWsfmNs2=b|`{)>krQZ==C z+K0iFjK)Gr@)nEZPVu_S;iKocBQ15P4jqvxoX$iR)%vHc5p*K9r)rvS zmt(O9@XYWCCZ1nFf)kOz^b%*;oQ~HH9&iieTMA0tJ<#g_|6MQ(nai;?h{dr`s(-BC zgYY{yiLq8L=kGA@=msSoWdIV7TWM%2$ILd}L(BHY)nbBZAYM;Vk?%N`S_}AZ+aiij zOkYjl(Mu`qFq!_|*O$;(qIuZvsn&hWr1Cdc!HV2;UFp}wtN*FQFLUgUA z067z4|}w4#A-p5g+7g^=Nq()UxoDew(L^hn8Z#_qbrm{|UV<}E59#y=xJ~iTW|S;itHWwc z5hfe3G(wtpl#EZI;$KPSt0sG9W`+z+3QaakL8;Vf^c6a)O+HvNty-(2EXV6CPg(r_ zdVfEb{)uPV!LFcuf|LnA;-I(|n&C;OI!?(|nJ-Zf6(XNO#xyd7Vy zXiz-RS2gtnHX5b|Cd#-qZt2_av6nRM?bC&h_YMr&OMZ`o4nW|)#f7p@{+q#1I>~(A zw%McQ$=gQ_`}2$sYd_Kh);~J7HUm*nDxGj&rM4N);4@J%Z*BS9rtJZ_U4a~e&0UzM z_(N^KQtlsldw6-@8Apic=ERG--BR-xmztYX#%?cPE-py>RJ;zsWfmC6pNqC*ampPg zM_tWraf&IW@zM%?+z|F==$$jLXyTkf-t-ZC3Z<#rgTCvUK+7ZMA?jb4fpI_)#tbca z+Xxog=xuxCR*DxHxZxhC1ZAe=sLgNeOFB#d^3M^zAoO`(u=Kh(6yboRIO9n`Bq?_x zy;X`TE~pvFKZc+6j$Fi_Uz*0}7eSeizG0aOCvjC;!w57BV73??IV^uKnM_HG9kA9N z+Sgwu@ea04dWa1lm9)|fMgs_6=71JXHa2-DZBYRyW3LrH4Mgw;r$1Si#@)8F{@CGj?d0d1ai9?)ddXy{fg7{uQSxYKNa`s3Z`oSJ>A5VcBP|LpEa6& zntVs|ul9D!Ev-+s;%AEJU0&$T0i@5x5^jV`wQ5U4Pu`8<`Jv*GcIs=+9OOopN8kt) zhi&6t+4!TIZsDFk?FZ)f5GG&Kt@B4vk*0FKg__s7McOc>vJH|2^gshCHRF>CZF#Lu zkBKS_v{|qoFi?mdW*S4NI%n$ZAN?E^Rf@f?AN`d|QW}q};xU<;gT%lz31_k8hj9bx zVr~*0BgpllLIG(C0YcxaT)e+>k2GOg3{Vi+#N2*=NisDgAFaw++YPjNRf$!kGmJEN zE*!Atx~COjBL}JPPc0q;Xz|qrNd2@qv}V_kXm;;{)VOlM=Z*!m1LY4R_I!97^1Z>+ zFe$|nD?zTV1ZyK6#$(yi%7{LCrqSFaH_nn#l$;%wEW#GuJ+ut8T15QWi_oOxT=E$0+|Jo zqr+gc2Enz3=giWSoBL_y$PBVbCr7YE1jOk<#L)5~_|03NZ0(}EZO>7eX&H5IA6*)B zK_X7sz6u8yBSL;#&1I%#P*bhdjI-jaI%Ypbx#}_I|58%XHX?$I5R4S9YI5pPr*Xn( z^B6Iz%a|&RRkT~1=I7@4u0v>+Xr`uZ2(m=M>nsOyQnaI6o`6$6B!1Nm;o+&?{}7%afVkXBb&^d7|{{6H8jF`cU%Gy@0$@<@wq@h0I?5%H;Re zO4|GTc&fb|#$D_@xU49|li0f;hpQzwC!i=dv~3Kz&8hJ`@c{SnoMgaYgUdBs?JA}^ ze&<@ndql6U{cmOgiUXwdu%9=gMHvvF*FLh#0ApihEA1t)JEr;M%A#Zmay_?jWKRL- zhSMa{+Yke9MwX>tPH?(5RehMpe;E1Mv6!`Wl)ij~QH(jmn{iu)?z^44CllioYH3A^ zq5D`I3@Gm@((aBhm+>yaWIRqdci&K&hZw(w)!N?h`HU*}D8q&KyhOqku*tEolX3c2|=Xs(0dOc`yV=y)RrG%WvoW7@%h6zANfBQZ)cWJy5XzlOplfdNCbf(_NrfFUtQtb1mQJCVe z5lfMg$dMp{{X$~#?CMS0fdO!5PUArEW#&(~1F;Cs{m8lR_vFBdK$D_3|EYpT?l^8> z3EugQb=9~C0JhSTmY&m?l8v0ddnV8A71sMJH14L}aGvIN@e*X#TQXuDvEYR+ldzy) zmnJsmZXIE-`Dn&f>@r_MopzIJl~G$LqmC}*c$Z#0P}^qH#<;mG=|94~w5>&V@y~{; z^$zf9fnP+siDi2OAPysqHn@AkXh}>lkHZ|3pusmeXKs7qQgc&HcF=?QR zmUpcyh%Ij4>6a7$HHXI2ehoKW98iz(vMw-g`ekk6s%J|~PT@n>p_gV)s1$whqXHvk zn^lr(c~sWf=va5NSgO7LEA|E#OUD#|xvRp{8xU#ag&l#fUlT*VL^K^220%SR(Ih+! zw_0BhN_?dajEge}uTWG=^^P(M@+j6LEvQJ3gxV|+ z3AYLpDz^$lQ+-c`;jY2|=&l?K@_n9P4wz~aY9Cq~uEhljaq1P1idWq+I^nK1&DW*t zrzv*@dihZlzTW*Ct~nI+pM4h2a0uxHA)C0D2Eueli8f`>jAI&CGCyzyKx}i(?7*3R z34$XGEYeXtBQW8!bQyGhgZPn<8{iBR zfvQi`r~vFulK@YX&(RQuRYBhfQG|=KG%3y-udNzl(WIx;1T>+UVxX8-7d3os(rKK{ zTm&uoeKTrQu)7R!UDq6Mi~0YW{@o{l@U~Yh8Ng6zNB%?)=n=7?k-EPE%(qH3gR@zL zrg_5^%ck@YK7t|n2a*&o0r>K$0d6=e%t$fY3vhpR>oX>aL9r>CQF_bV+@P9Ty{dxiY&`;^1= zD{7Hlrb!8}3j3^C94k###r*3T+v|cp0s0bj(03hR!qtFi9=t+c#&alxlkN-EAYp3( z$(}V9xnpd5JX)Wwc~kli&%CN|7YZWBKk@?dB}GHzg~J79qC z&$xZuKs-W0{K?-Z-U#@%Qtv8Ht2{Z{KVt~}yvXBM4&h29mtV*pNrK#|KZIsH$EVPk zX@sPu`vai;UHO}E!Z}2IaPs&-Q;8AIll8c1O5d_vrZ=+_KIxm+{AYmA=>5NahVVXM zthbDdgX9kUJ`jvAxcCAg1iu6H3nBaqpG^Pt@BFlJ8Nm2N@yQIR;6|aN?*rk=%8z7( zk!HjxGk{V%LeUM$Y)VjPF~V{);?V!Tqjtd53w>>e4L`Wz0EsvFsUmqp*p=`>72i_^ zJM+X1rdNE2i5o#EzZAfwcEKfwD9|_A_ehLQ9+t?VAv3JVh&3&OD2rg_P+dG=nTtCj z7IMzz(6t%r*te=iWIxEjO4cgW+2d>A3oAk7;E-v`fnN1;Qd-!r1}oJPLcL%!pr zD+zJQWJ6517QVBw1*=WNpRj+=Y8NlsR=#EFQa=Ao@(L=>6wJE|h*@<{@Neebma=j^ zyUXK+?~}XrXvgPiFNE}?k1yL*o(Y@jIVm?E;xFCJCs783eRmz)`VfCSKz+R;f2nvc zS?+!-4xVgBFD{Ul@>9yhE@FQ=DamJG14=udD(Ocgam%iE|IJRKk}u1uHcamVJ)00u zn+;+)fwK)k+xWYIY@nm97VCT9!mKtSU^fypI`O^_m~%(>4d+7S=i(qMq1k|=Y#1Ph z5ut1lA&@A9@6eESCv1*;HtCud z796Y?LakFy5PScoF7GW2$&`eAwM28;Q5yUc(w54=d=|k^tC}YX`DvM1-7Pe>MRw|C z<*StXEmbsWEm6H9bs76al}@$er1IMOd-54qwfCU>UN>|r;F;9z+E;*A`H8PMPyOjj zwg+|nA@TRUtkls+%Dtb=;M*ZI<{mo%OXn_1*XyDkUpkynQKuc?b?aA!2W;_y-S_~n zLO|P~#z*axLKK=f7iUZUhDSpv#s2UM!$C7juzU-#9p9Yz6gjVSdVC&DybsyuggMDn z%8XcAy4In}0m|DuPuQ{6;|FDn0e=%c!5aI%?{sZ`CBAy|yH2_=lZVfBqHp{qPNTid zwJC2j3AkfjIa@$P3mYJ7i3$`UJ~>BuTv`d<95 zwg-sa5ab^IIl*9faq)CR$=>N#y|HIF-W2zx#Jf=-IAGz9ru0BlW=tGE(mcumA8A0uEO~X_O&EgIAQUS@Pkop_ zMUNDJ;6x&#FPz3_PBq4aTcZiDdJTs9UOX5E1B2~;HL>V;+!=r9*Au<75eEy>oV3B7 z{#kY3rPJK^N>kj2Ymv~lEHlj!)`S!IH3O$xqltHZI0~-8zM)qt{Jgcu?gazx4q^T? znapUL0ax#plN>W{kU0m~j005O9wN^WVV z{|n>OqqxF!YGL`pp>z^$yl_sn#?(AdbG`{*!@cRE+~2S`?q+AAvE0TPQPA=G#6^`8N@ZGu!-pio8F1-CB;eQ2jC19n0J`@P42)2}mIgbcIMPW~z zNo7lgFNpmwMkt@js4pyvD-&u+!gcI3o8fc$WmKHnb&kjvA`>Z5>mqh*7IV>unA^3H zhcqEqWi-%*mjE3}Q7(BQWi7-|0F2xJGJbDtJ;hs(g*C|i{5^Nuvn`E@54D#;KQlQ%Tept+vRZE}*_`YUm z`FHyr1%wf1Gl7tJLnuBnNRS5{&%UdZnY{pZ%h|rH6R>@QTL*-)W`e& z;wHz&76*6Iu1~x}uRI4oVa^T8Gy?QVAM{Ch$ir^{hwEmLwyNG6t3=5+FfJ8m*oGY_ z0V{?t#y=9$FHFB9XiT+z{=oF==X95Y9~q;d%cpZ>7S8vL%joXZGUbm$<#! zErxYJnS(KV#OCl{pDa^6k&aH$@68DEj%xgNL(z@hu;Q_v|9okN}e=VAC zEt+}O%&{`e3)vI-=vVsL329cD38kijX=$LpTMQZGra~jv9WrWTLqgXnRtwOCByiwr zv=~KN933i-!>L=K9e%SRJy|C2+MN?Dl1U4;Yz#Wc93Yl-w@L5eB>^jpZ)Z;u5d0YF zJ#DG{d?L{I23R!+d(Rc-liR@Oo~Ac;=Oqc^=feaFZ-3}#uSbIEcE%mZlO*7I1s{ze z@FVvW{h|z4l9I^#FK$LrRD^eh0i)vSaq)X7>iE}JNG;?8i+;eMEoFw~PtusByr3k_ z=7k#XEz~L1i(u4Xkp0~^|)YI&*pgrFxqJ7stZ`r%TKkuSb&!SWCqSJVh zxoDBO{K%p{AIT_}4_>~T&O0;OUz4oQfvMb>h6EnX!IA7I>-@Unz6rl)1n=H5`&N|^ zpOO5Q_psRFEB+W8{?b>Fp~L&;IE*O^g0+dcCLq6Rwhu92XXX9m|n#@M0EM9`JsxYl04HFn1r&%C)rB`*PpsPq9^^S zK{A!<-0Yl_Ye6R|edi}*nVzwxcxK4tOtJlRE=@E}IW$!gdZ1623u|yaA0iZ;2@UkZ z|FtBJmlOynkwDL`yd3xR$c%bWjY;g>tzDz=+5ZnOon+3u)sxSP+B48xxrX?6^430 z2-$yn7fprBe4%&7f6vsT=@mA6G441{M#cjp6*rOH=pu%LLg}hIcrtVE5()gZNXJ+% zo@)K#n#UJx!jf#l0_*f|jX_2qSoF;)X<<#FXl2mEmp7--K0wNsgl2IjaO7XNN?ow4 z7jI4#dq4W8P`k`cfUXy+-8}c6ns0Q~zpaaL_d1fDo;aUps@MC@vXuBWYGxsXtFP9S zjsf~+5eT*flbKK$N?$79*9C}(zMTh&_UO+su(G`)^5>xp6k_X7=)@*I;X}7*A5Lr( z5+)HtnV7i9eLKdysaB^JQ)?NS^2fR|$j>0U#LNWWv-E%xeW|357=RO{%shQK%qL9w zT%Aj3?#P`2xz{!iTZIC9;M`?kpo~fwMe;alV;CKdZ%#^MMn=|ckwhPa%%_&bN?kb5 zXEuZ0&XEw;fFRcv zNxxMR5Vu4>d@jW5zDfVI6v!nMFt-=BfpaeLosMgtOn=(H9)nV+&DkzpQbT=%O>Jy> z*%2nR4B3Xw-X271+|DYfpwl_Ni_=RHA99Izgw6+R2KGgcMng#+<0_&{{O zGmM7FQE|Sc6YrHZ1g?lbnOF9-F2{Wv+BJMs@oVc}vWo6xj?B8T_K}r}V1pNn!~^!` zbY{EZS?by`;h?XS95aJjGn@OXMn`3v4>Ml4K6NGiRbnG9PH(dRJ=0n?L?(_V!vyo7 zn|MPA5Iv50Ky)H@^^zd5Q?b#Nc(uj1b$8U!dd){h$M|(0#YRPI=P-MR&3i@tPy=4d zfu)1%$+t?sQpVjsN8L~n(w;A1``d?7`(oHBVbiaxl%?poa{y22V4hYuys|uBRJ=T< z^80zx+PyPnJaU)~4P43wbwn}HzszSmNBP1$P#wumWIQFa%gTmyWh^?RP33mROaxxI z(j9i+r2`FXBmZh6AF2;x$ob?qXeYr6<4!iz5XM~oLcqLss+Fx&wLE%IHhbaqm-%7n zEq!ze7()p~l{e@2{KM%#IdaI@Rak(f;GNkL_lZrd3gY9@8}!3T7nM_n-O#A^Ib2eKnCSK+V& zf7G)Vx+G7RVdTM9@m;*cnpMscg#pSM(0@o%;#mH^rZ@Jjq%Aih=`K zqT3siesQQpTliJ3LPjA2q4Ajv0*kY6T&fGCMTR){I;1n)GTI#f?w z;JY4YIWdWiA0(FXj#!lIZvG(WB_dsJ{&tdEB6E}P^a7dwj^eY&N9QAVDMz#D=q_ja zfbnkh2;|lC@k+nj4`_1y>5HN8XCM4?QLl!QyO;_v6nY=FImT z<`C?e7)%VC55q*gK`A2;RZL)g%(`<7kwai2G~B4ds*%Y6dyGx{GUhQ;+y&~+8LA*Z z(l_a}xp41`3N~ca% za!ED^!{Ik!EQllASs0S)d%R`JDE!{BiH_Recfze3o&-6Tt&*-J{KEU%46|BUsO3?$ zakkb0jRRr|=3Wrkm}uQRNW!@K!xr^gPT#+1S=i5*HKnFo*}e6 zmGRR75_bq- z?5Nn@IwgvUznh7jo}W&tMGvp9-b09O3p(W~2GJIO&r3)<_qNsmzXw|=ofQD6dSX>N zXH4Df-Z85cGPOEw-L%5kL;`!V^d}oe4!2=6J==uDYJJz0u2BAqt#gj?r3u^g*tTuk zwr%5#ZO<9oK4V+Iv2EKpW6v2IJMXvIKQ_C`Q%U9NN>?Y{ovy0B>%N9o-T8wIIEXp_ zQOQME{jsT-ry!8~`%VPMim=Gt9zQewSCYy_{=u^Y>7oyqG+rzx#Enb{hW}- zt(fNx(pon=yVTii%*xMA&@*tE6t1s4#HrTq)kHMvA~$IvJ9+!?tDvO@A9B(Yh~>vQ zyx0jvCRS3Da+KG*MGnO;sX2k2>baIn=HeSQm1q)rE1O}? zcfcb3Ec>qwXaXNN#ipnPNQOwAMYg3dc7BA0rkBXRP0!jnac_DTbdkla;Z064&I_*f zDxCQb#52PNq8Inh79TeaR|(#LE6Bi%B2~RP|172QT&EqJrTt`Nt!zG;!7MrW!^$hs?;~5mwHhye8F36^*IZs=cRXY_^zgT+;dJI@q??Fc&wCySF*gN)@p$LQc_M zlsop2Jp~sJKZl(8DhBK}3j&U*n`uHW)MPOz@)#(?rnH?wkruCzrnp@BNrU=UQ%c#U zfzu$eSEO>B)W@Iv3&t+ZTUfPVIxW3SBx^9m(xn*&n+)zsj!!b{XT%xHVW=zAM%!e) zKC^@|-XfzrMQ$7{l4=5l8mUhL@p)qhuz(A#4s`wus(%iHC4r`KKUI{{F@^#?vYSFkyH z>JfOTx;nX8V<$$6CWbqH9yg`!%zGNxNhGN;9;;enbo7$Y7}2&TE4X5>=#E7tw z!#wih5E^8pN?Tpq(cN8HS>3oH6yH4ucrz!VPe;U%?b15)z`7fpl^{5X!F_gHmg5v!y^ zVLt?DZ=WI-a~JSr!Y_X-`J<37C24q>9mQ1U&{VU~5>(kVw2m4C5HE#P0DDOrycN$` zgoDcQSYo3@JQj=Z5SR+CUJJDnDTUmagq&^2C547&Vb8-Vu=cWxn3F>ENs5|gNeUyKEU^i-IC)8^I(A!KWfyqp0D=Te&G6%hyr36^-bp~v zLQ+H0xp3Rek^+^LmzG!goRGbIlMz~sIZ}?giUwD$xq-j&5!on;N#g|UolM!GdYaO< zcqJ$pHYyp{W)L+~uBBXK9}sG!24?zS6rF5ac$3&R1afxP#zi#L(WwR^Or;H$dC`uw z0D7^Sz91?lXqu+Je?pD)H-VvDVyZM5yv0q0T#7sj3m_UnJ_>G6*{$^*RjjII)HqY7 z35Nx;P}|GORRam9zeK20bd`Yb69pS#tIBv*Vn4=KP+x>ZmTIJ_p$=v#3*QmCH~r<)3TqJBAH1);mq@{w5&aIL zlP7)pm23N)qaZO)qp9U6P@^v@l8mAGSK~*a%cd21zLlZe^r_wyjLJ!*(|BJ6LyP(M zEs_*-Krn)|imfd~cprLuG&v7X{ZD%Qx#@tlmS_h6<2{EAdt>xLP7+pQkOy{U@Q7-4 zoy)!J!d4k%k!`InUw!bHWio+3l^uOKv;a9828Om$c4Bf2ep+-Cnac@*t;<&}T7%NQ zGVukFu5%`H(Zv3aN|QGw4xU)B5^_EL~#P^q{yR!B~cJAJi4SBNgVgMZ7d8o zWbKF-#t_2QR%cLn z&jcOEZTj>FfkAqY2Vo#QM1j+fuRFt>>4`mn$QWV`m2r%lEV5!v`Rtg?U59j8=y^R3 zWkyBaO-OB$Kz_%8*A3!QbU_kY-uM@>+3cG%MSEfRLJ<})PE}P;>FOyN05b5F$7L-= zthQ?~q3kt{^~l}reg=&gz6gdyhWOrgs=paCesz3jJKizE5|9oiF-wYSj18aG1B9s2 z_xMQ1#b8d<+kmN5gAPWS=`D|-_MXj&Is~)HswCk_{}sd#69q~)&}d`o6xnQ%@qpIj0o`$S-fdEmKFI}CJA5o<|_vH9Y!3__P{&FGhFAh8%f+`-rQ z{NgG!&=&IAA?ctiofPRHLiLJpEErZW$C%lOQBrrqN;^4HpC;c?khHR_=CT|YnbDMWHY!wxa92K25pqg&f0ZW>U zzEsSdB|tJCmJ1e1jy+)JhDrg4hFV-PFnLB?zi_J^?}##WWva+vn|>wuaVS=Kg*u5y zXIsj`t(zXBSRyeA;SZBF74f@PH6t;5;zArwC97I-Epqe^oLEXh)rQRX1dVU^aQdRS zF)$-v0&W72(`+b2S{~j-2L}Sdo{!1rBcYKZ-qJdMae>JZ>W)L!aZWY-W8geAG}Mfm zU*&E>gqq*`S)sp32X)E=n-NhL;dCf&5xkCqCvYAI7hNGRq#u-LqD>-PB${Ed(~K{gnwa)41QUo()SHU9MNMPbv|F z`vfmH9)s>^mY&#=An+b(Dcd|`4R3++aOKwmWkn^#`wa+R!?-J-a9ffDLuq2P6PGTsu@8>I_QWQQ-5J<;>hDnQO z8`^opHDoK$L|VJa2_Al-Bw8thAt(qYZAQz`x`=3aMfcL#9sEg5ILWQ`eeo~F02yK; zEdqLUBP9Z!hJlU&wg8J6%AO5r7kbeOXsdSl&@rPq}N)qV$!N4+h<3O9OSpS% zqGnnN8Cxn8g&z?F=EYt#ihOo31w1`L5AA|-u zU|ZG*O0Ju*Csd|AHyo&=JGUITp))raxS>1u<6)sQHyOyIJ(q<=r;aw`u97A9aOIkk zt0@ARNRop7&-|9*(mKdn>&D?FF5dt{@!;&RVm$sNk#KgB5>j#5xAOQTnRm#Ae!I{l zA%(~9^xttWMAs;!wl9+)sKrPyKZTP5f~Lxj8y|(^a>fYy@$`kmU4d`gNO_G%LI!pLxPozOkXnDA=uf57cBta^nze`W$&=?VYKtS z4e70wSy<%(MQBM4;*Aht;NMzK^4R$HGL;m+V)Kjew;|MF##-mQ18(5grfgAVUcE33 zN79q;sj5d@c`qMwa1C$-2}Q*{mr0d7<$8kHY{(5uZliGs>qEKd{h8OZ>)7fld6H++ z*2R~6nui(p(igm{DS9WCAv&qm#oo0iSFJu+Y|C22XZ&dQ|1_GToOnZsDs+5v0zY={ zX{?WjG?KIuFCD|6+=odRRRwjz?1ioO_&B}D-9!I; z4NY&eUZ!hHVlbo69c3`0OTA%(@kTq%xNt%%IeJUMinwz%RqnRPi{~_0RZi;z3Si>B zO~kCrW~e>WDt^YLGSG^#V3m{lM`9A&BOcZt?oC_C8UmFpb%kxk`4jsd37j#NGz^BP zP9eTu`WP{xPQ@^t^!}W^kn&mf9?9UEJiE9tgR1W6XG&!hJ^XWC_}&F@DqYUthHX3CLXLU8R!%lfU}9(>Ojgk>y%M8oNIYKh#R{VJ zsKyr}>=wl~xyK3)4I(i@ChoPR`Q^cG8< zWO!49K_Bo~-=4hOpGsoPwaTrF|Mov&wzZLZ7mv;xv`E7AUEi;RV$@R7QRwu87pE*# zoER|K0)kE(h@X3bJEW@c#f}QZ(~<|4&M zu@?Jtm^N;|K0&YOGKtn|dzEIl)lj3`;xhSUzur&J+hJCz>+U?s)+*;QIb***OwYR2 zP^IhcGI?#kK1lD=VaC{cd6g#IUx(qyvz-tq0J4gC@kw(22@oJE6hOKNCOHoV_)CcS zLHUPuJcPF&IWi-b9dM@c_`OpcPlvE}JDDczS~fr-juNah5$Mi{>^(~IeZG@JXyDDc z6!)!3bF=6#32hW-2Vl(IT7$uLy@B-ZvC9m~#>AwXyGkqFCdnz`b~Kg9`V6>{Pz5vS zqj$Md>N#{gz|-~H2wI;J5)BD;z!khPopUGUD+gkAnJ?&>RtV(2$q`wa^o?BnsytEh z;}K?s&P2BiTji_7RPjU5KZeLWa3es@RD5(94x2$;J@V{^q`1U@%M4jXC_gvS1Iq-! zc;jFWq8$*{4`{)AV5j%Nj+EShwtU9yXVOU|oGU`Jq5$xSfmrPr<>Xb*iOK?N^X#$u z(Z|l=xdzoux{e;g&X@*ET;pV|K%R=e((+R>$W{lZP_6Xi{p^K;yTs>YoZdQ{prTM{ zM3JzmF(2;r-dG*0@q`82q2D^|N9~J$x8~;^KYW9}fhA@oAZ1-lvk_jfu@KV(5bhR} z&WS?q(FvI@@~Pkx_l1fPl{6hH`~G5ZB^{-5COh8xb6N;83Nc9Y!% z6^{?>(#27Nl~$9UilEoV&}{(s6;WwM>P`ZPS$i36-g@9_EW_{<^`TlaEAC~_=9hV6 z{P9EMpHV$UH$bYgIiA|9oe}%TDp?(;C9vAufE-c4zeT0RaFB9_C~_t-rXUDbV!Ft) zDvHevH7T=?%s@scNF1&jQG>lIo;0APW6n>P8})KD@k5f?7BSc1sS1aUKmf+fld}}8 zo{@HtlT>>eC^1c3GgGw@CTPV???QI7!9A}U3~?GL>5azqMEvt1!1Inc*Ze!e{*83& za`f~`K)CfuaV$s?@NF>`_FI_P7u?Kqju){f&}Pr3_yu3(gP>(FKFF#&q|M<$%$rm% z(mfDBn6tX<80(l~=X5B6b|#VShN?%|r~A$kbO(G?#`W1mxjKd^Qm`4_;M@S2lo`u|sZ0nBg5xTF^rH^( zWlMQLYlK^w$!Vv0bymNfV`t|ENcE2y*})PoA?WW7|29?&#>>j!oDk_z^y^&jAmj#5 zy&!n$YVD9jN*_Aekv3h*Y9j1&WRj=LP`~RCi;fP$3%T-oeUn`8wpQcC0cR~-Cap~< z`M5{(2saBOMB1ETh0mp@X-r$iAp#Zm7BK(8IxZ59hp7hS*&M2OM zAU48{vqV+s@iz%B`C*sLc+ZxdNw;1a?N!lE#kB*XUwwa}V64GHCG}x~w{j{Ds}%~F z;Hcr^*P_nt#6t%oib@l*H24w%aCqNGHX`)Cq)#RmBbC6Pu=Il z87ujE2P^m#bKk_R3xw6Yyuwwz)-|$)!}7h=)SNO@{dP2R0>d&+#g+ZM!gc-H1EEQk zVFT%f`*UFh+zD_tSuAJLL|Jr!?bco`pD~3v-I3vbRsEH7XO=Vj4nXPzt6VE_1lA3v z>~F45twDvuyRzLe{mT&_xXA}$e~;BRZI&POb*UbL7Sp6TXakj))`j3;^vxNl@(W@# zgz3bDurM(W`0z@!uVDeV(|vDpQ9s<^p-;e*v%7!BbleJHm*1G>7|bb3>24E3QPvr~ zG9T#|gJg9_x%Vr?&6RX@_|P1+E_|r?qQEOtOj)83iZt@frhv%_wMj}xoK{DjBMGCm z@-thOd540`4usb!wJ#zJi5+eWk&ZGkB+B3>@1R4hypxQaVtKF(nOYQc3*`zx&|{mh z^QVp8=(%uoC!XLP$oulW0NV#hWi5Cvjvq{aZE!A~KWM=RO`>5iVVWS^WeruSKQ{#D z360KJQYmV7fW}>o$rS01p!H1p#w5ll4vcYx%RI_7Ff{QJH|4KXj1+<^f<&K#6PVZg zC)NSpqR-mn(>-ck@Uir&Fy5Klm;23pnCPZZ;@HK>mc)JbQ3s5PGwmKY{+195+2bsu z!ql*<+3<`+#7MJHv^Ze5ZjGAVb2_aF|B1Wlm*D`=6MBrhh9=t`E|AUdX3r@@c@Ei}MX&@gpW%GV_%R z$cwb09g^bp>oakeG|s11tXenYdXw_mY~}Ijy*Qz6t`quvM09sxd2V**{y_fBgYhNq z1QJ3Y8@&Vp-Pkh=U03qYEu7n%JFX5si`!S=H(JlMaY}Qp?|lvfzg_zdPMkv6_>SGp z4y)Zz$W0k=qq>LkbDj32u_%boIvds)nDYpO#{px-*@&WhF(Fg}Fomy{Tgv7kAj94> zqN2UxGo(P-(lLCPgW1%+C@97YR_6)oq6*j?R8| zScJt!qGe$Q56KE0x%BP35U0&b(w2vi8Gze)vNs*T5~VVR!1X|R-wq=ko(v%Mps~EN zWDKPb!ub)C*@~qijJeubO7%# z7Ir(=F4}$Dehkr09(lA+bkI~2u`cZCp6cr~T0uLtVLZhuE zE}thge$^e)jq}G5pq_M&^v~`M**|1I=Z|g$LjW*!ZvEyUC-*)CmLfly(g-7%mYfJE zM*zPP*(nNxGY&kx^}J|3j{em8M97qxqMM;TUN)gR`+T7(_<{}JxQgK*AIT#P>+o8E z*#twv3a24DgFxXjEI=W@XbE<`gsAf>*D?AV^v%}2yy9%?9+biQdzXRxYVg}=PKL~` zw21uPH}E;k90be}DUYO)L4rhUkU_e3v6<{u?T_ih#?Q6US$EXOP>w^+vB(EwjIjOc!WiL7`iGU)wc1#W zTrj)sMo|I|;#7@#g$-im%r9FtJf%6%0KlmRIYj;qU2+T45yDv@Cm97T4_@|@*KAW-|DJg00NbO9ERa~e-%DlI(Cb}VhniX7%$*VcnkfI{@5@$&FNAh zzDXpARuD<9Hd&+k=uL3w>MEvz)%kKU+T_86xe|n0hR==9H@`hfDmR6W^VcWb=ZbZdnC_>SfLpmS9h%%@{{6$Sv)kU9wrBT+kgAVqoS& zgs%xzB*Z30X~nT+h1O@sKB`n?(5K3*k!u-5`PHT#H(V4uyEm$hyUVgyD>x%e$)2Y1 zRy{X$?<~6qjqHsF6vgchH-wrygu&Z(&0W&hYn(QMcntEnr$I3y?p6E>f~uVz@Z?Aw zfaS%X{gYfy_%`;(BxFKnk1g#CVsE^<3^yd62>cD@Z*Yr~Eet_b(&5!UgO;2M+((3w z3Vk`$o^g=8{00c*tA2c-D&{gEn+?q625z(zmMW~j=n~Ih)O;cXq=>{6g%2IK zls6JS%l_iQ&`CilH#a9X;?L4tQJzSCP2E!b^J(~cqcZF?3fiWW67%U~i*ihkCe9Q` z!dJ^dUiA{zvC?MTE)5kWx$!-bFf6q3xjyVXmzHcx^Sotadm~BSCEfgQT4{qKA=gcM~u{N^J;b zag~xyZI~v&*RZ2SxZx%cb6OyPfJ!mUS8&8Rl+hb$qn_^v=!i9R7y3(6h*Kkg6x|af zUJs!OVzz)dL`~17C!r96o9ap=QKULpqgtvMN%BU?;83PTQmbL%lcX2YJ*U1B)Lc*$ zCezC9LRmhzN2g64MyJ{FPYSDJf?XmPwQ4G7@NQaFFwb#gGZO6#*Xt(Gbhn(ycOhhv z^IW@#&kT$t!7TFHXkJ5(n`4yeT=U zTN;iEX1RvJ|w$s3D56;LwINSLNgvxg$+dyGW;B;2FLsFa~E>@6avYete4~bR_ z^mFPR=-XR%bBKy(gT=f?#jcdUWIBzynsD{Ex6A9Fg#b;E$Fgpx=jVGSR*ZTZB2iHhsVZQV<3OOGf|7o;kf3c!T(-=9*Nx zhF~u&P9^0U1D|QH=y@aP@7-4yJ%Gq28~oxgNnay6Gvm?>7KIqt5N4?;IeDvffhPn1>X!)#^xYS(*)!pg%$N}5r-Dxd zv=3PNLyQM%xr{kEtp+3Na6%=IIQHjG!(TJ9 z6O<(fvu*--_q%VP(x6DQkuAGw#03SfD;(BRj%=KcZp&%t2TLzuK{c=)`-Wp-2t|rRgrbRqA5MTT03KrE9bwM7uah7wEAh7(TVoMEsx>uqZ?L^EriGX*Y}nsE${{;gNgYqZE`w`$5Za7Q28p z%b?+0Q>VQ`ly+Cn?Kxc#e9MV+ z28`%jvTsQ4p=m^_K%m%J-ki)E+=h&y5apTd1Ic$#&w?h_@fUniaUHYv8w7>aZoli9 zPX_fTkk^9Zskpxc;~lJ;?05goGi`O6f3Qu-fg>$}{-iMB z-!-u0{SE`9XVv_^lzd6RKaE(35mg0&0rNk#b-A`JJ9baFDu_3HXS!8wco7V;hJyiF zabxcr!o89Y&y8=rmu$;ZxLN2t)BuqTT3-dYQi8$I^r+C~IYZApt~8i$cZt7y=h7Bn zwa#g*LHdVJ(c&{;g9b9p38>SFlj{SN;Pjg$y=1liPO%uP0cbH!{OY#!$LsxVIxhj2 zY~^9{>@!XpnKg-x3zfkFiA%#gPHGtk{%~I{j97-SsmN>2#%h`P!7~#W5V*TVhOD~s zmgbwD$52gLQ7sh|s?CY_D34Mnp%Ei9v^#*q)Z3{z54aZ<-jTRT_;YArIZO3XtFwXV zS7hQYEjEyW=wap!)IZK3>w?;jQxjU|qcHcMSDYr1Hzr}Ge}@lq6M1`KuDiA}cp?(M6DskVPxU<#l9XndbAx490+IQ+cW(?VULf`T`OeIcg0i9WzXlSKYcZW3%Q4 z45mk7EwL$YL@eO73#F4~d4x%S3~=AQh6|MR3~%T~i=MFujl-QXmJh@30f75d)p>lrpFggYmq;4kt+q zlnB6wohec#Ee1%u;Ie5g`iJkdv>4-qYn(Z@$m7FB@3e1X_<#*kDF<-Zo=v@2e5n-! z2@fkA^#rocoDrfEApyUP~`pMf(yUPE5WSd2ticoZLIzy$)=Dg7PH2dR;SYx_JnDPP%y{ z|1H0`ejBu@?VRjS8FTUo{%f|nJsmKr@8JQ_b=uMS$8pWg!*371MTo1t;-(4Ic;Y_A z(c`d~3{wYml?TZe8b73S(aC)ENZi0j^=Ndc}e zakd^_%0TKf6uZT6yv-k<3=+5Tdzyqa7d>MjtmLkrZ=Gv>_^-w>ewb z`FB%TUc}IN2-&$}T;=>94Cd zx$^bf_=9s`ZAS}h6BpLh$JE&N+tiqBY@Zn{vWLm;=DUgsAH<8@@fBt6NR}C*Iuy$b ze`xZepxu{yB#@Q~K`)Z|FU={jA$-~7YM&7wUu+Vm3Emo*#rSIf`ki?OgCS!39lR2e zLm-M5ZOX)EfkY2-+Bh#0##RX6uf`hbF398E)lG*lZWr}#ztGNjn=j_uJFj+SSC-j$ z=Ni{50f+WT8|5m%<*=KM?4RlIU3azG&TQo&sBM9-;M+&=CCDq1F1g?sLn5KX@895? zRCT7Chm>mwuhK25{!!cHg45T@dB%`O7VD&U%5pY&ri>G_jhu&=Yr1#Qm!hxaPmv!i z?;`%-2YpqSKCkRg$sZ6WcUfDMga@~Gx_sLH@ra4LM}vomFSf6K1|+|SRwoGW-0mnp z2wqJMD1T2FCV!9bCJ3JV8#la(KV*C@yVLyGz3YATxLf_8eAR_M{70t!Ww3BWSYr7~ zNv-guZO!m4DU+C{Ezdj=y_Mq5q1BIP##kT@U2hz`$aL;EEw7BXLAf2oJ8Sy=4a zg7#SmH@yyi$%ibeU@E)Dg3R4fPtu|%7U`-nr4do&j+hoMkgKw{xDMwY7y%W$PUc>4 z^ID{Zp-b)S4{sCd6cV>FnGyRYJbpbqWr7*~%Y#4JF(>76Wstc==jDUbn6XpL(=pEK zp=2PqY(OtY{jh(uAF3tIS6~y_fO-?#fVz{hOQq$fxHEOBJV|+$T>e*vZ)CU;>r&na zXpe69Qtu9LWM1oUWW1z3OMLY`OS%}kRK6rUOUCYJ*Uhfe9W;qNPPqeK*iNjVPpV9G z)6dsCPziQaK#3fW^7Hk?(@<)h)VSbW|~vfU@g&4u&-gD+4&7 zv{78ixn_UpHuKBcyN_)G9hNqZyF-kkXrBoQnsW$ z1IP*UwQRrF$FVbz@IRanup#%eO;v9$bf!d*HuO_BBOnj%!GalVgm~^j<6c%g0@pCp zO5(6V*hpSoifhx=hzkm*ZUep6sEgQr@5Z(rnp)oBM+T>EUA>DTx4gD%%vDH|yeH)N z25RXrZl+bz!Z8%LT*}pnw)LZ%4ki02Jj#&*L?$nq<-Oj{#N(@2aDe5)5bx6mPb5#Rau9Od$B z&!^%W`xl5E$hNwg0hqcMG~JPzD^#73>=Cq~l`i$rs-y?mk z>MqEO`YxGQBn}$FevTv4wdfm*SdyxL~~G!1!*%je*^VQ9t>0^jV006M3Oo*jvkb z38f%sG%5^nrU}n{u>)BF&H2p?gc^dZ+>m@S(F3&^S+>uGkbEpcg`g4Y(*a zra!g8w%q!BjAly0oRka0jVfv-CzVP;!o4+Q;X(6c#Y#*<)rjDxhep--ozO9<{!W{0 zj-alMruG4@o4-L_>x&!$Rx-wI$XFLwT1E9#I__PyojcxL|6CcGL29H912m8IaAF#Z zG}oE;bbN8PllqHr_{%PAFW23ROYXO;0uC z;kE-25(uHMOda+oOqIUnfK5AV&=;|E`IJ>hcUnw2X}$|({PBG>Q=H4=x)qfo@)577 zDD9~g*})hDM&R{mxBDJjP}_!**(|j#X($~5b=iHxbuJ*7-#gHH3)(Y|FnDZwE7^VI zC%l2OJ-g6)GO(16)aokr+VnB9o09@*LDTcn(f_#EeCZ*n6d6Lc6FP#Yfo-Fi-iwCB{I@AmhToV{@BVz` z3%cJhXBUc*53#>PAC!c>GbDM|OQgxNil27~=XjND{QYEPyI&dUmb;Eqq;}slr4YHu z7kIxxtPZwSN&Hp~iM!8Jr2f6r7BBvsWBYet(~ptA)aobt0{c&2--g87cPUbWH<(g3 zkb_@(os0u{zn9nYqD8@9?@MY0zvpjHx;Ac4RB{hyOHAVg(_Oam5V{UuT#o2Q^Jo=$ zzx1YEKic2Q4`!Q*O@faeif60ZJZTIO#TW~2g8Q!wO%}Tqw;l+dIQ+jt^BC(L>_`4_ ze^7o0fL_=vzklbpXT?GNW_jLi`d2DCLO5H)_x3!s?JD=0+|K&nK?I)Pe61f%8N3hS zE@h#h^N}tb+GhV8{_b;9Uc^cqD)l~%lm4Afu)WiqLD;M2kbp!jzkNcIx zlPO;DXG&wVKJ8pe4=jIg6 z$|K)Io&NO7`&V#la>E*pTN}VuxyC(yM5n5L-^Ehs2hx*|ivCodM*1D*()|nVIg7uX z{*0iK=8Z%BhX#Khp=P>tn0Eo1lBP`Lxk^QMhm4H6rY!b3xeDUXvSoaS1Wt8r>WJ~5 z8UqS>Q9UVr#%XoNbPS_j^mB+akwJ#T zd55^S@HRtt=?)dXs)y9SDo*LVN={ipPecMy-jUPazY zJCy`U{|21X-}1W%o#HDICnc984>jv|JI{?@K_8)CRUf5aWgn?ubsr->qTiZKDkahK z-eMNy{A8q+<7x1hPf`fZQ73>N!OiO58dya9#K+YP)f<*qQ>f1`WQfzm&v7SwhjOY2 zR2h_ZRaQ)TZI(PzzHG#)|C!ruy1^WFB zs|=}jD-5Z7%fB_^stl{5-eRpQb}J*bC@OX<@R3*bKZUP~zRD3)dsRj&1*;C0cbBNo zo!l}ZtZPS>)^Rj3joOuxmtc`vB~+K-Gb?ujKJDjSAKj2>@N zCQq6Jyy2V(Z2;%#I@xc@$BSe&?WNX{8#pzo?xF6PEz+{{_KP|;olPwp1~obEN;Y-) z!*}4-z2$CmJ0mT>tt&P(bttbeYf@`1&pK+&PW@}DcH}NfJ?1(ta+(Re6>G|N3@=J7 zjQ_+w-s(8`@wA{@mtB3b4 zj^0sM6V8WS)ERAdZb*Hi+NFHK$GxggvI$MHsM%HTt&U*VG}#vAaO_B}&aik}qsHuM z#SOe!+7&V*Z_dn9;1b(KDaV;&*jV7oHlK}vZ@?X(T;Z7}b1be^PP14y>m4xA&vJzv z4Ql-so8-(LZdq+gxQ)}W^bIrZSv1ELw04QvZE7#AOwF8b@-k1-Fn?N^m}W&1P|b44 zEm6;8ZQ?dh)UZplgq?P_OKextwKb@wXI`~F$<(x#ou1zCI>y(!9(c32`{M<)iC{xJ zRn~kzt?4x7vk`h6zCm-(dS!BtdqpT9t$W4VByfkTc1UWO;8g7#NH5br%Bs=7qFt@MrC+Um)GxMssF~+@tzD|U-wrvV*XmW@yxa`7 zL$u_4Ay{sCiQCUuZMN$%-9XrV-;nQ_ZOZcNwQR;%vUX%;IC}jwCZlx z*W|f}vx{{uPAs@U6v1wyf$@Ts5v(KI^QSwxeHcHoaHp ztZCHY*I%z*w-Ssp&)PuNq&J0Eb2f$7JU2^LJ2Xkw?AJ`HJlGswIAS#`mQ%uy$*%4rV4e0PqSpRoq89t4vZQi#RGzv)tE_44 zMZdynT_^GLh2(8sEjn-FEJWDLplmi(RUaLH*6)}wzx#r)!f$VOsprnZ=KD!;x#wwirRR2bvFB0K zX7@GSdiQ$aZ1!vEITHAoJcNzvuSU097_Le>*`r> zDx0te^`Y5?7rVeA`zPynv85n!%6rQS8PwxpPf7X^?9xhDK$z3{3H3>4Pl@`_*p?$V z$GGp#B8(WFHMaeMyY_o%`z!x9{kys^I^SGx)F(v`48gVGOk8wbkmPH+^V_X4o$ZYW z>MrL{KgVy}TR&00=%~sQIbU>NBoArCPc~CUA%BPdw$(u{ zYW|pHZ=W`G$I@tB#4Ek6NrPUGfzQKh(UCa(j-Z(Xb19AK%O@&DC4; zr6sw`eZMVne22v2!<{y9+p+2L1A0a)_yexG2&pm?KU$0;SKM}5E z`q`5})fTTS&RBDR-!(t8IJM*1dafK%4vVwr-KP~|gs&)0=C@JZC(GO6sx^O8ascuc z8b<)0b{&r4%~pI4d|EWxXUUH-vvQCx6d!Kg&0W2q+t=(3vQ^p|0_u&@RYJ)+r^~Fa zXcCq?uyIkdj?@j08+(J*jh|K1YJqufCzFtWEUdUs3R#4KeAYWp4WJ$q$zND3TFs#*hZC zg>lwM@}hisTeNl{Svwj}pNqHa^s4MS@c}ho>h)auf?UYFlK^|42#Y=z`Z^X0b11^?T!7+X7}{Akw5_>!P3!c0)b?%-WxQU$N#f8dzGH9U z-MM{z)v~jF6{EUy_3!e*!+qT|J`RF$n4e*gpJB9{KKS|#1}pT)^3yjX%xsXr+|wsx z@5(r-H9U(CUcr6$7;vNbOpPq08jIv zV_9Yhfvx2}+5oxlZMqIQ*|S!b*Mku2!B6veL^bi~h>?bh#ECuG2$<>@SbU&Ws^HA` ztP5eGJ2BOcY{Rj&F2(rO}%j*K%226R_#dn~D^#+7K z&DoN4T%lY0R6aS{ zC&EsDtwDKT&i4D3u{mx9_Fr>|s!#le18s<^k3WY3ZTRSrdLfzTm|TYIgyghfETVS( zUz9XjeHwHwCMvIcQ`H&#qd+%MH02(S38pJxfsYo3E584UH6n_;Fh(5b0{-;6xlpH3)lA| z&66oJ;d3oDd8(WhNAj-$-&LoBZ!#2S~-r{lgg*oGJ-X+T);m5CmD zlZRZWB2Sc281u;t#H71Il031=Z((Hi*|92mgINZ zBk`gWh7c4{c=@DlpU43H$wStPD43o}T8GkwQ^`ZNnkb~krL>W^Oyj9TO;FO8KW&y% zhYr3|$!?;)DOH;!$|wqde*Ptl8FpARthfTA`py}iepA*cD(mDGGzmyr`2{Y#p_Du_ zrmSdE)zmR-`GO9=wNe%QGw%KZwHo3kTRHtQ_Pv5j+>WjU}%bDC&54 zE_AFXub3<9X#UieQdhucOVE87?6gCguJ4NN5;<@vZcLs&dyI1o+Da;LU0M3!1ib2p-a$nZ8X zKug$wn+#;gI+NE-WW+qv*HGiZIxP;U*EY(-gWQDQHz6M-l!u6X#Dw=DA3>Cdlzha3 zhcN9x9GxNtpz5^=7bGEF|BJD64iY7Z_VfC#ZQHhO+qSK{_TIH^+qP}nwyo^TOI}q{ zNh&pc=FCj>A6?Zm)zhc@{Js&S`-s$u=Iz zHeks%B1sOEqD(LXBAjK+ti0_}zmceF@;zwxt<#WSjRm@>>)VVtgga9raH%wZvLiem zil2#u`_Syfo%_Pie6k}l9tyroNsdE_zg1*M@8A?SPlcT;EJrOrAMm9#5~z05<3j=G zb9>Uk>9vU>1pwe^II`Np4Te;*On^ZV-#L(Ve2@+RkPi5e4)Bl;^pJPZ$ouff`}C=n z(4nBi;H~56piRT(tD#3-qNLb;_ZA1z>>(zBW!+b4=NsAZdUrvukz|8n+yvV<5O=t8 z|5`i*H?JWbC_e{K_JPP9g56bu;BQ`nT6a+PKYp6ZaCgqPW5V)YJ~&7MG@i>| z{K$qs$cLMd4>=|pf=W8@O4cD3sRt`o`dbVGsT)%VRYVQhN7RAHI52FQWkwXYqGvNC z_iL%Mir?YLh2OX7w@0b9#x;#Zkz=9ZqQ-j;yQBV=wlK?!e7{TYrfI}uu~Zsf1XCT2WT(A;GP ztVZV#(#7;#mb&jQh*EsSUy=>%nX{GCDkv$O@3zHbKyhA;WWV$*ba@v1A?fRS? z^x!3pHd}dUhzDVY$n)S8p%(5OwWh#ysi2V$8?w;Sr$x2U!VeO8M`iyLkxxSp8nLE@ zj}1W7V(a*lNeRq6rJ=ro{cCZ1ANrL6P^MNsKdSn}2}yl*}TMLG;|6Wsx` zD0RT@a$qS$&&W-wL-4@LAXsRHon~(CH8!F;G)yzI4pgK*!Pv+Hn*be# zshw>_P(|mWXWs<*9m)E2hHY*W9k@h4vTh3;$dn>G)U}Mztn4<&+p#=X`3s_9SkBkP zjp!yApX7}$n3{=E!zo)R2wlf&L{N zsfAL0)J^-a_vpc^watMFF&*a`zVUNoq|36h6mIeO3~@jqA4LRj#tm!}WtNxWfGmnW zW59U}WO_p<7<`AAY1Rpyf?m^`G<<=svK>S-%&=q03fC;3L9wp+uNm1|%1Li*eKvVN z%1O6jyyDa(KMPp3aI`?%8-MjC41;Q}ny{5o%IW)C%7-DHE^8My^-I~T=+ojUI;TCXSmV4^Ev^ek!liOZD<%m z6b8`?lCq?JUzFBa41f7>wm&hqsf?dYDHvKQP`4NsSO!Tnm6v^?QNI%dl*1H2&=h-;?O>04Aw+7@ z)V?VVU?nZgJ|PXHCADgowgKjnWuxEQl&f{e8ZLAa_O^2kL6=c!kE#Lb)3TU>o{MSh za+I1Wa41zrqkb*Qh2FDX)|75}?Q#k%Rlqg*FK33uv&oPtAL|Ns?|7|E9>+f#wm%J4 zQv}u#Ysp)N(fTbJL~C8g}yBF}jRT_gW=?!l*rVKp`)O#++ z*gmtF6EUeppDa$eKj3#esVJXhPTe4;MaJnWicSrhmS(Er7{`QVEgahCcG*-gtSOR0 zlP2@>PHoKd+60|Pvg43NbK9Owq8;0caUpk@do*_Y8E-(pZVyYuD`AhrU9|H^)8J$E zFD!`L9o4Jg-Rk1kEv{aWu5O^vsS{eDdkNy>?jtU2ppGAn6Nocc$KcrrZ0(RNpHIif zxkR8ZoHw>OCS>{T6yp1_lZN8JPP_n3e$AmzU#pCRi|gUem?Mp#(&@{@zMUz{U1