From 9bef4281a4ad890d110ede2cc1e49f70678fb6db Mon Sep 17 00:00:00 2001 From: user Date: Thu, 18 Apr 2024 17:32:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=89=93=E7=82=B9=EF=BC=8C?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=A1=AB=E6=8C=96=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 10 + src/main/java/org/example/test/Caclelate.java | 1 + .../java/org/example/test/CreateGrid.java | 360 +++++++++++------- .../classes/org/example/test/Caclelate.class | Bin 3409 -> 3409 bytes .../org/example/test/CreateGrid$1.class | Bin 661 -> 661 bytes .../org/example/test/CreateGrid$2.class | Bin 0 -> 915 bytes .../classes/org/example/test/CreateGrid.class | Bin 14838 -> 21317 bytes 7 files changed, 224 insertions(+), 147 deletions(-) create mode 100644 target/classes/org/example/test/CreateGrid$2.class diff --git a/pom.xml b/pom.xml index 80bb434..26e3955 100644 --- a/pom.xml +++ b/pom.xml @@ -82,5 +82,15 @@ gt-grid ${geotools.version} + + org.geotools + gt-process + ${geotools.version} + + + org.geotools + gt-opengis + 29.5 + diff --git a/src/main/java/org/example/test/Caclelate.java b/src/main/java/org/example/test/Caclelate.java index 31fd3b1..9a58942 100644 --- a/src/main/java/org/example/test/Caclelate.java +++ b/src/main/java/org/example/test/Caclelate.java @@ -26,6 +26,7 @@ public class Caclelate { * Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER:设置经度为第一轴顺序 * */ + GeoTiffReader reader = new GeoTiffReader(file, new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE)); GridCoverage2D coverage = reader.read(null); diff --git a/src/main/java/org/example/test/CreateGrid.java b/src/main/java/org/example/test/CreateGrid.java index e7e17f7..e571e6f 100644 --- a/src/main/java/org/example/test/CreateGrid.java +++ b/src/main/java/org/example/test/CreateGrid.java @@ -1,9 +1,6 @@ package org.example.test; import org.example.utils.IntersectionBuilder; -import org.geotools.api.data.FeatureSource; -import org.geotools.api.data.FileDataStore; -import org.geotools.api.data.FileDataStoreFinder; import org.geotools.api.data.SimpleFeatureSource; import org.geotools.api.feature.simple.SimpleFeature; import org.geotools.api.feature.simple.SimpleFeatureType; @@ -14,39 +11,29 @@ import org.geotools.coverage.grid.GridCoordinates2D; import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.coverage.grid.GridGeometry2D; import org.geotools.coverage.processing.Operations; -import org.geotools.data.DataUtilities; import org.geotools.data.collection.CollectionFeatureSource; import org.geotools.data.collection.ListFeatureCollection; -import org.geotools.data.simple.SimpleFeatureCollection; -import org.geotools.data.store.EmptyFeatureCollection; import org.geotools.feature.DefaultFeatureCollection; -import org.geotools.feature.FeatureCollection; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; -import org.geotools.filter.FilterFactoryImpl; -import org.geotools.filter.function.color.ConstrastFunction; import org.geotools.gce.geotiff.GeoTiffReader; import org.geotools.geometry.Position2D; -import org.geotools.geometry.jts.JTSFactoryFinder; -import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.grid.Grids; import org.geotools.map.FeatureLayer; import org.geotools.map.Layer; import org.geotools.map.MapContent; import org.geotools.referencing.CRS; import org.geotools.referencing.crs.DefaultGeographicCRS; -import org.geotools.styling.FillImpl; import org.geotools.styling.SLD; import org.geotools.swing.JMapFrame; -import org.geotools.swing.data.JFileDataStoreChooser; import org.geotools.util.factory.Hints; import org.locationtech.jts.geom.*; import org.locationtech.jts.operation.buffer.BufferOp; import org.locationtech.jts.operation.buffer.BufferParameters; -import java.awt.image.RenderedImage; import java.io.File; import java.util.*; +import java.util.concurrent.atomic.AtomicReference; public class CreateGrid { public static GridCoverage2D coverage; @@ -76,6 +63,7 @@ public class CreateGrid { builder.add("the_geom", Point.class); // builder.length(15).add("name", String.class); // <- 15 chars width for name field builder.add("id", String.class); + builder.add("height", double.class); return builder.buildFeatureType(); } public static void main(String[] args) throws Exception{ @@ -99,16 +87,16 @@ public class CreateGrid { coordinates[3] = new Coordinate(coords.get(3)[0], coords.get(3)[1]); // 闭合多边形,复制第一个坐标作为最后一个坐标 coordinates[4] = new Coordinate(coords.get(0)[0], coords.get(0)[1]); -// coordinates[0] = new Coordinate(0, 0); -// coordinates[1] = new Coordinate(0, 30); -// coordinates[2] = new Coordinate(30, 30); -// coordinates[3] = new Coordinate(30, 0); -// // 闭合多边形,复制第一个坐标作为最后一个坐标 -// coordinates[4] = new Coordinate(0, 0); + // 创建GeometryFactory GeometryFactory geometryFactory = new GeometryFactory(); - List> featuresProperties = new ArrayList<>(); - List> pointFeaturesProperties = new ArrayList<>(); + List> featuresProperties = new ArrayList<>();// 面要素属性集合 +// List> pointFeaturesProperties = new ArrayList<>();// 扩展点属性集合 + List> tPointFeaturesProperties = new ArrayList<>();// 目标平面的点集属性集合 + List> p1PointFeaturesProperties = new ArrayList<>();// p1面内的扩展点属性集合 + List> p2PointFeaturesProperties = new ArrayList<>();// p2面内的扩展点属性集合 + List> p3PointFeaturesProperties = new ArrayList<>();// p3面内的扩展点属性集合 + List> p4PointFeaturesProperties = new ArrayList<>();// p4面内的扩展点属性集合 // 创建多边形(矩形) Map innerPolygon = new HashMap<>(); @@ -118,13 +106,20 @@ public class CreateGrid { innerPolygon.put("id",1); featuresProperties.add(innerPolygon); - // 获取中心点的高程 - double targetHeight = getElevation(rectangle.getCentroid()); + // 计算设计标高,取四个角的高程平均值 + double centerHeight = getElevation(rectangle.getCentroid()); + double corner1Height = getElevation( geometryFactory.createPoint(coordinates[0])); + double corner2Height = getElevation( geometryFactory.createPoint(coordinates[1])); + double corner3Height = getElevation( geometryFactory.createPoint(coordinates[2])); + double corner4Height = getElevation( geometryFactory.createPoint(coordinates[3])); + double targetHeight = (corner1Height+corner2Height+corner3Height+corner4Height)/4; + System.out.println("设计标高:"+targetHeight); // 缓冲区建立,外扩100m double meter = 100; - double degree = meter/(2*Math.PI*6371004)*360; + double degree = meter2degree(meter); + double side = meter2degree(2);// side为间隔,单位为米 BufferParameters bufferParameters = new BufferParameters(); bufferParameters.setEndCapStyle(BufferParameters.CAP_FLAT); @@ -150,7 +145,7 @@ public class CreateGrid { extPolygon2.put("geom",p2); extPolygon2.put("name","第二个面"); extPolygon2.put("id",3); -// featuresProperties.add(extPolygon2); + featuresProperties.add(extPolygon2); // Map extPolygon3 = new HashMap<>(); Coordinate[] cords3 = new Coordinate[] {bgcoords[2],bgcoords[3],pcoords[3],pcoords[2],bgcoords[2]}; @@ -158,7 +153,7 @@ public class CreateGrid { extPolygon3.put("geom",p3); extPolygon3.put("name","第3个面"); extPolygon3.put("id",4); -// featuresProperties.add(extPolygon3); + featuresProperties.add(extPolygon3); Map extPolygon4 = new HashMap<>(); Coordinate[] cords4 = new Coordinate[] {bgcoords[3],bgcoords[0],pcoords[0],pcoords[3],bgcoords[3]}; @@ -166,20 +161,43 @@ public class CreateGrid { extPolygon4.put("geom",p4); extPolygon4.put("name","第4个面"); extPolygon4.put("id",5); -// featuresProperties.add(extPolygon4); + featuresProperties.add(extPolygon4); + // 外接矩形打点 Map outPolygon1 = new HashMap<>(); // Coordinate[] cords4 = new Coordinate[] {bgcoords[3],bgcoords[0],pcoords[0],pcoords[3],bgcoords[3]}; - Polygon out1 = (Polygon) p1.getEnvelope();//geometryFactory.createPolygon(cords4); + Polygon out1 = (Polygon) rectangle.getEnvelope();//geometryFactory.createPolygon(cords4); outPolygon1.put("geom",out1); - outPolygon1.put("name","第1个面的外边框"); + outPolygon1.put("name","输入面的外接矩形"); outPolygon1.put("id",6); -// featuresProperties.add(outPolygon1); + featuresProperties.add(outPolygon1); + Coordinate[] outCoords = out1.getCoordinates(); + Coordinate[] outLine = new Coordinate[]{outCoords[0],outCoords[1]}; + addPartPoint(outLine,geometryFactory,side,rectangle,tPointFeaturesProperties,targetHeight,"0"); + + // 打点 + double outBottomHeight = targetHeight - meter/2; + System.out.println("边界高程:"+outBottomHeight); + Coordinate[] coordArr1 = new Coordinate[]{bgcoords[0],bgcoords[1]}; + List gridsP1 = addPartPoint(coordArr1,geometryFactory,side,p1,p1PointFeaturesProperties,outBottomHeight,"-1"); + Coordinate[] coordArr2 = new Coordinate[]{bgcoords[1],bgcoords[2]}; + List gridsP2 = addPartPoint(coordArr2,geometryFactory,side,p2,p2PointFeaturesProperties,outBottomHeight,"-1"); + Coordinate[] coordArr3 = new Coordinate[]{bgcoords[2],bgcoords[3]}; + List gridsP3 = addPartPoint(coordArr3,geometryFactory,side,p3,p3PointFeaturesProperties,outBottomHeight,"-1"); + Coordinate[] coordArr4 = new Coordinate[]{bgcoords[3],bgcoords[0]}; + List gridsP4 = addPartPoint(coordArr4,geometryFactory,side,p4,p4PointFeaturesProperties,outBottomHeight,"-1"); + + extPanelCalc(gridsP2,side); + + + // Create a map content and add our shapefile to it + MapContent map = new MapContent(); + map.setTitle("填挖方计算-创建网格"); + // 构建添加面图层 final SimpleFeatureType TYPE =createFeatureType(); DefaultFeatureCollection featureCollection = new DefaultFeatureCollection(); SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE); - featuresProperties.forEach(props->{ featureBuilder.add(props.get("geom")); featureBuilder.add(props.get("name")); @@ -187,12 +205,39 @@ public class CreateGrid { SimpleFeature feature = featureBuilder.buildFeature((String.valueOf(props.get("id")))); featureCollection.add(feature); }); + Style style = SLD.createSimpleStyle(featureCollection.getSchema()); + Layer layer = new FeatureLayer(featureCollection, style); + map.addLayer(layer); + // 构建点要素图层 + List>> pointList = new ArrayList(){{ +// add(pointFeaturesProperties); + add(tPointFeaturesProperties); + add(p1PointFeaturesProperties); + add(p2PointFeaturesProperties); + add(p3PointFeaturesProperties); + add(p4PointFeaturesProperties); + }}; + pointList.stream().forEach(list->{ + if(!list.isEmpty()){ + final SimpleFeatureType PTYPE =createPointFeatureType(); + DefaultFeatureCollection pointFeatureCollection = new DefaultFeatureCollection(); + SimpleFeatureBuilder pointFeatureBuilder = new SimpleFeatureBuilder(PTYPE); + list.forEach(props->{ + pointFeatureBuilder.add(props.get("geom")); + pointFeatureBuilder.add(props.get("id")); + pointFeatureBuilder.add(props.get("height")); + SimpleFeature feature = pointFeatureBuilder.buildFeature((String.valueOf(props.get("id")))); + pointFeatureCollection.add(feature); + }); + Style pointStyle = SLD.createSimpleStyle(pointFeatureCollection.getSchema()); + Layer pointLlayer = new FeatureLayer(pointFeatureCollection, pointStyle); + map.addLayer(pointLlayer); + } + }); -// ReferencedEnvelope bounds = featureCollection.getBounds(); - // 创建grids点,side为间隔,单位为米 - double side = 1/(2*Math.PI*6371004)*360; - + // 添加网格图层 + // 创建grids点, ListFeatureCollection collection = new ListFeatureCollection(TYPE); Iterator iterator = featureCollection.stream().iterator(); iterator.next(); @@ -200,137 +245,151 @@ public class CreateGrid { SimpleFeatureSource source = new CollectionFeatureSource(collection); IntersectionBuilder intersectionBuilder = new IntersectionBuilder(TYPE, source); SimpleFeatureSource grid = Grids.createSquareGrid(collection.getBounds(), side, -1); - - - // 打点 - Coordinate pc1 = bgcoords[0]; - Coordinate pc2 = bgcoords[1]; - Coordinate pc3 = bgcoords[2]; - - double t1 = (pc2.y - pc1.y)/(pc2.x-pc1.x); - double t2 = (pc3.y - pc2.y)/(pc3.x-pc2.x); - System.out.println("t1:"+t1); - System.out.println("t2:"+t2); - List centerPointList = new ArrayList(); - Coordinate center1 = new Coordinate((pc1.x+pc2.x)/2,(pc1.y+pc2.y)/2); - Map centerPointMap = new HashMap<>(); - Point center = geometryFactory.createPoint(center1); -// centerPointList.add(center); -// centerPointMap.put("geom",center); -// centerPointMap.put("id",10001); -// pointFeaturesProperties.add(centerPointMap); -// -// for(int i=1;i<200;i++){ -// double x1 = Math.sin(Math.atan(t1))*side*i + center1.x; -// double y1 = - Math.cos(Math.atan(t1))*side*i + center1.y; -// -// Point p = geometryFactory.createPoint(new Coordinate(x1,y1)); -//// double height = getElevation(p); -// boolean contains = p1.contains(p); -// if(contains){ -// Map tmpPoint = new HashMap<>(); -// centerPointList.add(p); -// tmpPoint.put("geom",p); -// tmpPoint.put("id",i); -// pointFeaturesProperties.add(tmpPoint); -// }else{ -// break; -// } -// } - // 下一个点 -// double nextX= center1.x + side*Math.cos(Math.atan(t1)); -// double nextY = center1.y + side*Math.sin(Math.atan(t1)); -// for(int i=1;i<200;i++){ -// double x1 = Math.sin(Math.atan(t1))*side*i + nextX; -// double y1 = - Math.cos(Math.atan(t1))*side*i + nextY; -// -// Point p = geometryFactory.createPoint(new Coordinate(x1,y1)); -//// double height = getElevation(p); -// boolean contains = p1.contains(p); -// if(contains){ -// Map tmpPoint = new HashMap<>(); -// centerPointList.add(p); -// tmpPoint.put("geom",p); -// tmpPoint.put("id",2000+i); -// pointFeaturesProperties.add(tmpPoint); -// }else{ -// break; -// } -// } - Coordinate[] coordArr = new Coordinate[]{bgcoords[0],bgcoords[1],bgcoords[2]}; - addPointSet(coordArr,geometryFactory,side,p1,pointFeaturesProperties,center); - - - final SimpleFeatureType PTYPE =createPointFeatureType(); - DefaultFeatureCollection pointFeatureCollection = new DefaultFeatureCollection(); - SimpleFeatureBuilder pointFeatureBuilder = new SimpleFeatureBuilder(PTYPE); - - pointFeaturesProperties.forEach(props->{ - pointFeatureBuilder.add(props.get("geom")); - pointFeatureBuilder.add(props.get("id")); - SimpleFeature feature = pointFeatureBuilder.buildFeature((String.valueOf(props.get("id")))); - pointFeatureCollection.add(feature); - }); - - // Create a map content and add our shapefile to it - MapContent map = new MapContent(); - map.setTitle("填挖方计算-创建网格"); - // 添加初始范围和扩展面图层 - Style style = SLD.createSimpleStyle(featureCollection.getSchema()); - Layer layer = new FeatureLayer(featureCollection, style); - map.addLayer(layer); - - // 添加点 - Style pointStyle = SLD.createSimpleStyle(pointFeatureCollection.getSchema()); - Layer pointLlayer = new FeatureLayer(pointFeatureCollection, pointStyle); - map.addLayer(pointLlayer); - - // 添加网格图层 Style styleBox = SLD.createSimpleStyle(grid.getSchema()); Layer layerBox = new FeatureLayer(grid, styleBox); // map.addLayer(layerBox); // Now display the map JMapFrame.showMap(map); + targetPanelCalc(tPointFeaturesProperties,side); } - public static void addPointSet(Coordinate[] bgcoords, + + public static void targetPanelCalc (List> pointFeaturesProperties,double side){ + AtomicReference sum = new AtomicReference<>((double) 0);// 土方量总和,负数挖、整数填 + pointFeaturesProperties.stream().forEach(pfp->{ + double h = (double)pfp.get("height"); + Point p = (Point)pfp.get("geom"); + try { + double elevation = getElevation(p); + sum.updateAndGet(v -> new Double((double) (v + (h - elevation) * Math.pow(degree2meter(side), 2)))); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + System.out.println("sum:"+sum); + } + + public static void extPanelCalc(List>> gridPolygon,double side){ + AtomicReference sum = new AtomicReference<>((double) 0);// 土方量总和,整数填 + for(int i=0;i> col = gridPolygon.get(i); + // 逆序比较 + for(int j=col.size()-1;j>=0;j--){ + Map pfp = col.get(j); + double h = (double)pfp.get("height"); + Point p = (Point)pfp.get("geom"); + try { + double elevation = getElevation(p); + if(elevation>h){ + break; + } + sum.updateAndGet(v -> new Double((double) (v + (h - elevation) * Math.pow(degree2meter(side), 2)))); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + System.out.println("gridPolygon sum:"+sum); + } + // 添加一个面的点集 + public static List>> addPartPoint(Coordinate[] bgcoords, + GeometryFactory geometryFactory, + double side, + Polygon p, + List> pointFeaturesProperties, + double outHeight, + String type){ + List>> gridList = new ArrayList(); + // 计算外边界上的点 + List> headPart = new ArrayList<>(); + double t1 = (bgcoords[1].y - bgcoords[0].y)/(bgcoords[1].x-bgcoords[0].x); + Coordinate startCoord = new Coordinate(bgcoords[0].x,bgcoords[0].y); + Map centerPointMap = new HashMap<>(); + Point center = geometryFactory.createPoint(startCoord); + + centerPointMap.put("geom",center); + centerPointMap.put("id",UUID.randomUUID()); + centerPointMap.put("height",outHeight); + if(!type.equals("0")){ + pointFeaturesProperties.add(centerPointMap); + headPart.add(centerPointMap); + } + List> lastPart = addPointSet(bgcoords,geometryFactory,side,p,pointFeaturesProperties,center,outHeight,type); + headPart.addAll(lastPart); + gridList.add(headPart); + + int len = (int)Math.ceil((Math.sqrt(Math.pow(bgcoords[1].y - bgcoords[0].y,2)+Math.pow(bgcoords[1].x - bgcoords[0].x,2)))/side); + //确定符号 + double xx = bgcoords[1].x-bgcoords[0].x; + double yy = bgcoords[1].y-bgcoords[0].y; + int xSign = xx>=0?1:-1; + int ySign = yy>=0?1:-1; + for(int i=1;i> extHeadPart = new ArrayList<>(); + Coordinate nextCoord = new Coordinate(nextX,nextY); + Map nextPointMap = new HashMap<>(); + Point nextPoint = geometryFactory.createPoint(nextCoord); + nextPointMap.put("geom",nextPoint); + nextPointMap.put("id",UUID.randomUUID()); + nextPointMap.put("height",outHeight); + if(type.equals("0")){ + if(p.intersects(nextPoint)){ + pointFeaturesProperties.add(nextPointMap); + extHeadPart.add(nextPointMap); + } + }else{ + pointFeaturesProperties.add(nextPointMap); + extHeadPart.add(nextPointMap); + } + // 添加垂直于边界线的点阵 + List> extLastPart = addPointSet(bgcoords,geometryFactory,side,p,pointFeaturesProperties,nextPoint,outHeight,type); + extHeadPart.addAll(extLastPart); + gridList.add(extHeadPart); + } + return gridList; + } + public static List> addPointSet(Coordinate[] bgcoords, GeometryFactory geometryFactory, double side, - Polygon p1, + Polygon polygon, List> pointFeaturesProperties, - Point startPoint){ - Coordinate pc1 = bgcoords[0]; - Coordinate pc2 = bgcoords[1]; - Coordinate pc3 = bgcoords[2]; + Point startPoint, + double boundHeight, + String type){ + List> extendPointProperties = new ArrayList<>(); - double t1 = (pc2.y - pc1.y)/(pc2.x-pc1.x); - double t2 = (pc3.y - pc2.y)/(pc3.x-pc2.x); - System.out.println("t1:"+t1); - System.out.println("t2:"+t2); - List centerPointList = new ArrayList(); - Coordinate center1 = new Coordinate((pc1.x+pc2.x)/2,(pc1.y+pc2.y)/2); - Map centerPointMap = new HashMap<>(); - Point center = geometryFactory.createPoint(center1); - centerPointList.add(center); - centerPointMap.put("geom",startPoint); - centerPointMap.put("id",UUID.randomUUID()); - pointFeaturesProperties.add(centerPointMap); + double t1 = (bgcoords[1].y - bgcoords[0].y)/(bgcoords[1].x-bgcoords[0].x); + //确定符号 + double xx = bgcoords[1].x-bgcoords[0].x; + double yy = bgcoords[1].y-bgcoords[0].y; + int xSign = (xx>=0&&yy>0)||(xx<0&&yy>0)?1:-1; + int ySign = (xx<0&&yy<0)||(xx<0&&yy>0)?1:-1; - for(int i=1;i<200;i++){ - double x1 = Math.sin(Math.atan(t1))*side*i + startPoint.getX(); - double y1 = - Math.cos(Math.atan(t1))*side*i + startPoint.getY(); - Point p = geometryFactory.createPoint(new Coordinate(x1,y1)); - boolean contains = p1.contains(p); + for(int i=1;i<300;i++){ + double x1 = xSign * Math.abs(Math.sin(Math.atan(t1)))*side*i + startPoint.getX(); + double y1 = ySign * Math.abs(Math.cos(Math.atan(t1)))*side*i + startPoint.getY(); + Point point = geometryFactory.createPoint(new Coordinate(x1,y1)); + boolean contains = polygon.contains(point); if(contains){ Map tmpPoint = new HashMap<>(); - centerPointList.add(p); - tmpPoint.put("geom",p); + tmpPoint.put("geom",point); tmpPoint.put("id",UUID.randomUUID()); + double ph = boundHeight;//+(degree2meter(side))*i/2; + if(type.equals("-1")){//下挖的高程计算 + ph+=(degree2meter(side))*i/2; + }else if(type.equals("1")){// +// ph-=(degree2meter(side))*i/2; + } + tmpPoint.put("height",ph); pointFeaturesProperties.add(tmpPoint); + extendPointProperties.add(tmpPoint); }else{ break; } } + return extendPointProperties; } public static void loadDem() throws Exception{ File file = new File("src\\main\\resources\\public\\data\\ASTGTMV003_N23E113_dem.tif"); @@ -353,4 +412,11 @@ public class CreateGrid { // System.out.println("---------"+height);//---------108.0 return height; } + + public static double meter2degree(double meter){ + return meter/(Math.PI*6371004/180); + } + public static double degree2meter(double degree){ + return degree*(Math.PI*6371004)/180; + } } diff --git a/target/classes/org/example/test/Caclelate.class b/target/classes/org/example/test/Caclelate.class index da3e9c59f26f912f675be83951ee9987eb2ecf74..2c2012148f4f35ef2120b14d269afd32e6609940 100644 GIT binary patch delta 65 zcmca8bx~?V43DWCgBgQ7gB^nsgDZmyLkNQ!Lo|aXLlT2FLotI6LluKALog9L*wgARiqg9C#0}De0g9Jk)gAPL!g9Ae}LkL3*Lk2_ad@LJBZ34g!bA&^2>NuA9MV%JGvUlh(Xa4Z z1V_OKKfrhK`YqxMP7w}~C@oDyu5XI;3Na(9aIoQqT+&e|-U=d3;mR+pi0>eVq#(kyu zE7J?Z%v~8teUBkut+gGh_o9nctdY%oJ%**~pYB5*_5CNEBhl6M+H;21i9eglzf<~O zyVho~8gWlB6ayKF$D=_$E+dBJ>WjZ-)Y6I))lE0 q_>KmCAiz&5A9Tm2q$V!o3Sk~s>CK^nYlIfAQ`{CYhg3O2`hEkw(c_K) literal 0 HcmV?d00001 diff --git a/target/classes/org/example/test/CreateGrid.class b/target/classes/org/example/test/CreateGrid.class index dfe763d18ebc5f47e611a8734cb524018dc84eff..05a79486f2c959d977a281cfbca3ab59f2607e68 100644 GIT binary patch literal 21317 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 delta 6791 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