From 05ecb7490307a44b77f5ff8600cf62565174cf7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?LAPTOP-S9HJSOEB=5C=E6=98=8A=E5=A4=A9?= Date: Wed, 14 May 2025 14:48:21 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=A1=E7=AE=97=E9=9D=A2=E7=A7=AF=E6=9D=A5?= =?UTF-8?q?=E8=AE=A1=E7=AE=97=E4=B8=AA=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IndustrialCameraController.java | 3 + .../algorithm/IntervalPolygonArea.java | 80 +++++++++ .../web/service/algorithm/PcdPojo.java | 2 + .../algorithm/PointCloudProcessor.java | 162 +++++++++++++++--- 4 files changed, 222 insertions(+), 25 deletions(-) create mode 100644 web/src/main/java/com/zhehekeji/web/service/algorithm/IntervalPolygonArea.java diff --git a/web/src/main/java/com/zhehekeji/web/controller/IndustrialCameraController.java b/web/src/main/java/com/zhehekeji/web/controller/IndustrialCameraController.java index 8e598af..77679c7 100644 --- a/web/src/main/java/com/zhehekeji/web/controller/IndustrialCameraController.java +++ b/web/src/main/java/com/zhehekeji/web/controller/IndustrialCameraController.java @@ -159,6 +159,9 @@ public class IndustrialCameraController { break; } } + if(pa.equals("")){ + pa = listResult.getData().get(0); + } //3d pcd保存 LocalDate currentDate = LocalDate.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); diff --git a/web/src/main/java/com/zhehekeji/web/service/algorithm/IntervalPolygonArea.java b/web/src/main/java/com/zhehekeji/web/service/algorithm/IntervalPolygonArea.java new file mode 100644 index 0000000..ec8bb63 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/service/algorithm/IntervalPolygonArea.java @@ -0,0 +1,80 @@ +package com.zhehekeji.web.service.algorithm; + +import java.util.*; +import java.util.*; + +public class IntervalPolygonArea { + + public static double calculateArea(List points,double xMin, double interval) { + if (points == null || points.isEmpty() || interval <= 0) return 0; + + // 分组统计每个区间的 minY 和 maxY + Map stats = new HashMap<>(); + + for (double[] point : points) { + double x = point[0]; + + int group = (int) Math.floor((x - xMin) / interval); + stats.computeIfAbsent(group, k -> new MinMax()).add(point[1]); + } + + if (stats.isEmpty()) return 0; + + // 构造上、下轮廓点 + List upperContour = new ArrayList<>(); + List lowerContour = new ArrayList<>(); + + for (Map.Entry entry : stats.entrySet()) { + int group = entry.getKey(); + double xCenter = xMin + group * interval + interval / 2; + double minY = entry.getValue().min; + double maxY = entry.getValue().max; + + upperContour.add(new double[]{xCenter, maxY}); + lowerContour.add(new double[]{xCenter, minY}); + } + + // 将下轮廓反转后合并到上轮廓,形成闭合多边形 + Collections.sort(upperContour, Comparator.comparingDouble(p -> p[0])); + Collections.sort(lowerContour, Comparator.comparingDouble(p -> p[0])); + Collections.reverse(lowerContour); + + List polygon = new ArrayList<>(upperContour); + polygon.addAll(lowerContour); + + // 如果只有一两个点,无法构成多边形 + if (polygon.size() < 3) return 0; + + // 计算面积 + return polygonArea(polygon); + } + + private static class MinMax { + double min = Double.POSITIVE_INFINITY; + double max = Double.NEGATIVE_INFINITY; + + void add(double value) { + min = Math.min(min, value); + max = Math.max(max, value); + } + } + + // 多边形面积公式(Shoelace) + private static double polygonArea(List polygon) { + double area = 0; + int n = polygon.size(); + + for (int i = 0; i < n; i++) { + double[] p1 = polygon.get(i); + double[] p2 = polygon.get((i + 1) % n); + area += (p1[0] * p2[1] - p2[0] * p1[1]); + } + + return Math.abs(area) / 2.0; + } + + // 示例主函数 + public static void main(String[] args) { + + } +} diff --git a/web/src/main/java/com/zhehekeji/web/service/algorithm/PcdPojo.java b/web/src/main/java/com/zhehekeji/web/service/algorithm/PcdPojo.java index 21b2900..d49f547 100644 --- a/web/src/main/java/com/zhehekeji/web/service/algorithm/PcdPojo.java +++ b/web/src/main/java/com/zhehekeji/web/service/algorithm/PcdPojo.java @@ -31,11 +31,13 @@ public class PcdPojo { private Integer count; private int width; private int[] height; + private int high; private int length; private String arrangeType; PcdPojo setPCDInfo(PcdPojo pojo) { this.setMinBounds(pojo.getMin_pt()); this.setMaxBounds(pojo.getMax_pt()); + this.floorHeight = pojo.getFloorHeight(); double[] x = {pojo.getRotation()[0], pojo.getRotation()[1], pojo.getRotation()[2]}; double[] y = {pojo.getRotation()[3], pojo.getRotation()[4], pojo.getRotation()[5]}; double[] z = {pojo.getRotation()[6], pojo.getRotation()[7], pojo.getRotation()[8]}; diff --git a/web/src/main/java/com/zhehekeji/web/service/algorithm/PointCloudProcessor.java b/web/src/main/java/com/zhehekeji/web/service/algorithm/PointCloudProcessor.java index 1590093..566f389 100644 --- a/web/src/main/java/com/zhehekeji/web/service/algorithm/PointCloudProcessor.java +++ b/web/src/main/java/com/zhehekeji/web/service/algorithm/PointCloudProcessor.java @@ -391,32 +391,32 @@ public class PointCloudProcessor { int horizontalCount;//横向个数 int longitudinalCount; } - - public static void main(String[] args) { -// List points = readPCD("E:\\泸州\\c88165e7-9ea6-493e-9130-e74342e5b639--192.168.40.11.pcd"); -// PcdPojo pojo = new PcdPojo(); -// pojo.setConfigPath("E:\\26.json"); -// ObjectMapper mapper = new ObjectMapper(); -// PcdPojo pcdPojo -// try { -// // 读取 JSON 文件并转换为 配置信息 -// pcdPojo = mapper.readValue(new File("E:\\1.txt"), mapper.getTypeFactory().constructType(PcdPojo.class)); -// // 打印转换后的实体类列表 -// pojo = pojo.setPCDInfo(pojoIn); -// //报错则认为没有配置文件,返回盘点失败 -// } catch (JsonMappingException e) { -// e.printStackTrace(); // -// } catch (JsonProcessingException e) { -// e.printStackTrace(); -// } catch (IOException e) { -// e.printStackTrace(); +// public static void main(String[] args) { +//// List points = readPCD("E:\\泸州\\c88165e7-9ea6-493e-9130-e74342e5b639--192.168.40.11.pcd"); +//// PcdPojo pojo = new PcdPojo(); +//// pojo.setConfigPath("E:\\26.json"); +//// ObjectMapper mapper = new ObjectMapper(); +//// PcdPojo pcdPojo +//// try { +//// // 读取 JSON 文件并转换为 配置信息 +//// pcdPojo = mapper.readValue(new File("E:\\1.txt"), mapper.getTypeFactory().constructType(PcdPojo.class)); +//// // 打印转换后的实体类列表 +//// pojo = pojo.setPCDInfo(pojoIn); +//// //报错则认为没有配置文件,返回盘点失败 +//// } catch (JsonMappingException e) { +//// e.printStackTrace(); +//// +//// } catch (JsonProcessingException e) { +//// e.printStackTrace(); +//// } catch (IOException e) { +//// e.printStackTrace(); +//// } +// getBaijiuBox("E:\\泸州\\5a11d221-268a-4ed6-ad50-446fa481a56e--192.168.40.11.pcd" ,"E:\\26.json","E:\\1.txt"); +// {//getLongitudinalType(points, pojo, pcdPojo.getWidth(), pcdPojo.getLength(), pcdPojo.getHeight(),pcdPojo.getArrangeType()); +// //getLongitudinalType(points, pojo, 350, 297, new int[]{2443,2142,1750, 1420},"3w 4h 4h"); // } - getBaijiuBox("E:\\泸州\\5a11d221-268a-4ed6-ad50-446fa481a56e--192.168.40.11.pcd" ,"E:\\26.json","E:\\1.txt"); - {//getLongitudinalType(points, pojo, pcdPojo.getWidth(), pcdPojo.getLength(), pcdPojo.getHeight(),pcdPojo.getArrangeType()); - //getLongitudinalType(points, pojo, 350, 297, new int[]{2443,2142,1750, 1420},"3w 4h 4h"); - } - } +// } static int getBaijiuBox(String path,String configPath,String typeConfPath){ List points = readPCD(path); PcdPojo pojo = new PcdPojo(); @@ -442,7 +442,7 @@ public class PointCloudProcessor { e.printStackTrace(); } - return getLongitudinalType(points, pojo, pcdPojo.getWidth(), pcdPojo.getLength(), pcdPojo.getHeight(),pcdPojo.getArrangeType()); + return getLongitudinalType(points, pojo, pcdPojo.getWidth(), pcdPojo.getLength(), pcdPojo.getHigh(),pcdPojo.getArrangeType()); } @@ -605,6 +605,118 @@ public class PointCloudProcessor { //计算相似度 return (int) count; } + +//采用计算面积方式来计算个数 + + /** + * 将点云数据分割为若列,并计算出每一列的最大和最小值, + * @param points + * @param pojo + * @param l + * @param w + * @param height + * @param type + * @return + */ + private static int getLongitudinalType(List points, PcdPojo pojo, int l, int w, int height,String type){ +//pojo里面的floorHeight为地板的值,以后所有的height都将根据地板值进行计算地板值减去当前点的z轴值,为高度,且当为height的倍数的时候,认为是有效的点,其中1倍的冗余在50mm,每高一层,冗余增加20mm +// 计算 + double baseTolerance = 50; // 初始冗余 50mm + double additionalTolerancePerLevel = 20; // 每层增加 20mm 冗余 + Map> map = new HashMap<>(); + + points = points.stream() + .filter(point -> clipPoints(point, pojo.getMinBounds(), pojo.getMaxBounds())) + .filter(point -> { + // 计算当前点的高度(地板值减去 z 轴值) + double currentHeight = pojo.getFloorHeight() - point[2]; + + // 确保高度为正值 + if (currentHeight < 0) { + return false; + } + + // 计算当前高度是 height 的几倍 + int level = (int) Math.round(currentHeight / height); + + // 计算允许的冗余范围 + double tolerance = baseTolerance + level * additionalTolerancePerLevel; + + // 判断当前高度是否在允许的范围内 + if (Math.abs(currentHeight - level * height) <= tolerance) { + if (!map.containsKey(level)) { + map.put(level, new ArrayList<>()); + } + map.get(level).add(point); + return true; + }else return false; + }) + .peek(point -> point[2] = pojo.getFloorHeight() - point[2]) + + .collect(Collectors.toList()); + String[] types = type.split(" "); + + int layersCount = 0; + //计算最大值 + for (String s : types){ + if (s.endsWith("w")){ + int maxW= Integer.parseInt(s.substring(0,1)); + layersCount +=maxW; + }else if (s.endsWith("h")){ + int maxL= Integer.parseInt(s.substring(0,1)); + layersCount +=maxL; + } + } + for (int h =5; h>0; h--){ + if (map.containsKey(h) && map.get(h).size()>500){ + double area =IntervalPolygonArea.calculateArea(map.get(h),pojo.minBounds[0],10); + if (area>0){ + int i =(layersCount*(h-1))+(int) Math.round(area/(double) (l*w)); + return i; + } + break; + } + } + return 0; + } + + public static void main(String[] args) { + String path ="E:\\工作\\泸州测试\\2025-05-12\\7d5a619e-190d-4e7d-95a9-1e47aa49eef8--192.168.48.11.pcd"; + String configPath = "E:\\工作\\泸州测试\\27.json"; + String typeConfPath = "E:\\工作\\泸州测试\\temlent\\40014847.json"; + List points = readPCD(path); + PcdPojo pojo = new PcdPojo(); + PcdPojo pcdPojo = new PcdPojo(); + pojo.setConfigPath(configPath); + ObjectMapper mapper = new ObjectMapper(); + try { + // 读取 JSON 文件并转换为 配置信息 + PcdPojo pojoIn = mapper.readValue(new File(pojo.getConfigPath()), mapper.getTypeFactory().constructType(PcdPojo.class)); + // 打印转换后的实体类列表 + pojo = pojo.setPCDInfo(pojoIn); + // 读取 JSON 文件并转换为 配置信息 + pcdPojo = mapper.readValue(new File(typeConfPath), mapper.getTypeFactory().constructType(PcdPojo.class)); + + + //报错则认为没有配置文件,返回盘点失败 + } catch (JsonMappingException e) { + e.printStackTrace(); + + } catch (JsonProcessingException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + int i = getLongitudinalType(points,pojo, pcdPojo.getWidth(), pcdPojo.getLength(), pcdPojo.getHigh(),pcdPojo.getArrangeType()); + System.out.println(i); + } + + + + + + static int getTopCount(List points, PcdPojo pojo, int l, int w,Map map ,int minIndex,int maxIndex,int maxW,int maxL,int h){ int count = 0; //列相等