• 点云数据转pnts二进制数据


    public byte[] getPntsBytes(List pointList, List attributeTransferList) {
    
        XYZModel offsetModel = calculateQuantizedVolumeOffset(pointList);
        XYZModel maxOffset = calculateQuantizedVolumeOffsetMax(pointList);
        XYZModel scaleModel = calculateQuantizedVolumeScale(offsetModel, maxOffset);
    
        //组装头文件
        String magic = "pnts";
        int version = 1;
        int byteLength = 0;
        int featureTableJSONByteLength = 0;
        int featureTableBinaryByteLength = 0;
        int batchTableJSONByteLength = 0;
        int batchTableBinaryByteLength = 0;
        //体文件
    
        //量化后坐标
        List quantizedList = calculatePositionQuantized(pointList, offsetModel, scaleModel);
    
        //坐标
        byte[] positionBinary = new byte[0];
        for (PointModel xyzModel : quantizedList) {
            positionBinary = byteMergerByList(positionBinary, short2byte_Little((short) xyzModel.x), short2byte_Little((short) xyzModel.y), short2byte_Little((short) xyzModel.z));
        }
        positionBinary = fillBytesWithZero(positionBinary, 8);
    
        //颜色
        byte[] colorByteRGB = {(byte) 0, (byte) 0, (byte) 0};
        byte[] colorBinary = new byte[0];
        for (PointModel xyzModel : pointList) {
            colorBinary = byteMergerByList(colorBinary, colorByteRGB);
        }
    
        //要素表
        FeatureTable featureTable = new FeatureTable();
        featureTable.POINTS_LENGTH = pointList.size();
        featureTable.POSITION_QUANTIZED = new OffsetModel();
        featureTable.POSITION_QUANTIZED.byteOffset = 0;
    
        //偏移
        if (!ObjectUtils.isEmpty(offsetModel)) {
            featureTable.QUANTIZED_VOLUME_OFFSET = offsetModel.toMatrixArray();
        }
    
        //缩放
        if (!ObjectUtils.isEmpty(scaleModel)) {
            featureTable.QUANTIZED_VOLUME_SCALE = scaleModel.toMatrixArray();
        }
    
        //RGB
        featureTable.RGB = new OffsetModel();
        featureTable.RGB.byteOffset = positionBinary.length;
    
        String featureTableJson = JSON.toJSONString(featureTable);
    
        byte[] featureTableJsonBytes = featureTableJson.getBytes();
        featureTableJsonBytes = fillBytesWithEmpty(featureTableJsonBytes);
        featureTableJSONByteLength = featureTableJsonBytes.length;
    
    
        //批量表
        BatchTable batchTable = transferBatchTableItem(pointList, attributeTransferList);
    
        byte[] batchTableBinary = new byte[0];
    
        int byteOffsetIndex = 0;
    
        //分布式处理+ForkJoin并行处理生成pnts
        List processList = new PNTSProcess().process(batchTable.items);
    
        for (BatchTableItem batchItem : batchTable.items) {
            PNTSProcessModel pntsProcessModel = processList.stream().filter(it -> it.batchTableItem.name.equals(batchItem.name)).findFirst().orElse(null);
            if (!ObjectUtils.isEmpty(pntsProcessModel)) {
                batchTableBinary = byteMergerByList(batchTableBinary, pntsProcessModel.batchTableBinary);
                batchItem.batchTableBaseItem.byteOffset = byteOffsetIndex;
                byteOffsetIndex += pntsProcessModel.byteOffsetIndex;
            }
        }
    
        String batchTableJSONString = batchTable.toBatchTableJSONString();
        byte[] batchTableJSONBytes = batchTableJSONString.getBytes();
        batchTableJSONBytes = fillBytesWithEmpty(batchTableJSONBytes);
        batchTableJSONByteLength = batchTableJSONBytes.length;
    
        //batchTableBinary
        batchTableBinary = fillBytesWithZero(batchTableBinary, 8);
        batchTableBinaryByteLength = batchTableBinary.length;
    
    
        //计算填充量
        int fillNum = 0;
        int i = 28 + positionBinary.length + colorBinary.length;
        if (i % 8 != 0) {
            fillNum = 8 - i % 8;
        }
        if (fillNum != 0) {
            colorBinary = fillInputBytesWithZero(colorBinary, fillNum);
        }
    
        //合并
        byte[] featureTableBinary = byteMergerByList(positionBinary, colorBinary);
        featureTableBinaryByteLength = featureTableBinary.length;
    
    
        byteLength = 28 + featureTableJSONByteLength + featureTableBinaryByteLength + batchTableJSONByteLength + batchTableBinaryByteLength;
    
        //组装pnts的二级制文件
        byte[] bytes1 = magic.getBytes();
        byte[] bytes2 = int32ToLHByte(version);
        byte[] bytes3 = int32ToLHByte(byteLength);
        byte[] bytes4 = int32ToLHByte(featureTableJSONByteLength);
        byte[] bytes5 = int32ToLHByte(featureTableBinaryByteLength);
        byte[] bytes6 = int32ToLHByte(batchTableJSONByteLength);
        byte[] bytes7 = int32ToLHByte(batchTableBinaryByteLength);
    
        byte[] bytes8 = featureTableJsonBytes;
        byte[] bytes9 = featureTableBinary;
        byte[] bytes10 = batchTableJSONBytes;
        byte[] bytes11 = batchTableBinary;
    
        //合并bytes
        byte[] pntsBinaryBytes = byteMergerByList(bytes1, bytes2, bytes3, bytes4, bytes5, bytes6, bytes7, bytes8, bytes9, bytes10, bytes11);
    
        return pntsBinaryBytes;
    }
    
    public class PointModel {
        public double x;
        public double y;
        public double z;
        public double value;
    }
    
    public class PointAttributeTransferModel {
        /**
         * input文件对应输入字段名称
         */
        public String inputKey;
        /**
         * PointModel对应字段
         */
        public Field field;
        /**
         * Pnts输出字段名称
         */
        public String outputKey;
    
        public PointAttributeTransferModel(String outputKey, Field field, String inputKey){
            this.outputKey = outputKey;
            this.field = field;
            this.inputKey = inputKey;
        }
    }
    public static XYZModel calculateQuantizedVolumeOffset(List points) {
        double minX = Double.MAX_VALUE;
        double minY = Double.MAX_VALUE;
        double minZ = Double.MAX_VALUE;
    
        // Find minimum values for each dimension
        for (PointModel point : points) {
            minX = Math.min(minX, point.x);
            minY = Math.min(minY, point.y);
            minZ = Math.min(minZ, point.z);
        }
    
        // Calculate quantized volume offset
        XYZModel offsetModel = new XYZModel(minX, minY, minZ);
        return offsetModel;
    }
    
    public static XYZModel calculateQuantizedVolumeOffsetMax(List points) {
        double maxX = -Double.MAX_VALUE;
        double maxY = -Double.MAX_VALUE;
        double maxZ = -Double.MAX_VALUE;
    
        // Find minimum values for each dimension
        for (PointModel point : points) {
            maxX = Math.max(maxX, point.x);
            maxY = Math.max(maxY, point.y);
            maxZ = Math.max(maxZ, point.z);
        }
    
        // Calculate quantized volume offset
        XYZModel offsetModel = new XYZModel(maxX, maxY, maxZ);
        return offsetModel;
    }
    
    public static XYZModel calculateQuantizedVolumeScale(XYZModel quantizedVolumeOffset, XYZModel maxOffset) {
        double[] range = {maxOffset.x - quantizedVolumeOffset.x, maxOffset.y - quantizedVolumeOffset.y, maxOffset.z - quantizedVolumeOffset.z};
        double offsetQuantizedX = range[0] > 1 ? range[0] / 1 : 1;
        double offsetQuantizedY = range[1] > 1 ? range[1] / 1 : 1;
        double offsetQuantizedZ = range[2] > 1 ? range[2] / 1 : 1;
        // Calculate quantized volume scale
    
        XYZModel scaleModel = new XYZModel(offsetQuantizedX, offsetQuantizedY, offsetQuantizedZ);
    
        return scaleModel;
    }
    
    public List calculatePositionQuantized(List points, XYZModel quantizedVolumeOffset, XYZModel quantizedScaleModel) {
        List positionQuantizedList = new ArrayList<>();
        for (PointModel point : points) {
            int xQuantized = (int) Math.floor(((point.x - quantizedVolumeOffset.x) / quantizedScaleModel.x * 65535));
            int yQuantized = (int) Math.floor(((point.y - quantizedVolumeOffset.y) / quantizedScaleModel.y * 65535));
            int zQuantized = (int) Math.floor(((point.z - quantizedVolumeOffset.z) / quantizedScaleModel.z * 65535));
    
            //short xQuantized = (short) ((point.x - quantizedVolumeOffset.x) / quantizedScaleModel.x * 65535);
            //short yQuantized = (short) ((point.y - quantizedVolumeOffset.y) / quantizedScaleModel.y * 65535);
            //short zQuantized = (short) ((point.z - quantizedVolumeOffset.z) / quantizedScaleModel.z * 65535);
    
            PointModel positionQuantized = new PointModel();
            positionQuantized.x = xQuantized;
            positionQuantized.y = yQuantized;
            positionQuantized.z = zQuantized;
    
            positionQuantizedList.add(positionQuantized);
        }
        return positionQuantizedList;
    }
    
    public static byte[] byteMergerByList(byte[]... bytes) {
        int totalLength = 0;
        for (byte[] array : bytes) {
            totalLength += array.length;
        }
        ByteBuffer buffer = ByteBuffer.allocate(totalLength);
        for (byte[] array : bytes) {
            buffer.put(array);
        }
        return buffer.array();
    }
    
    public static byte[] fillBytesWithZero(byte[] featureTableBinary, int fillBoundary) {
        int length = featureTableBinary.length;
        int remain = length % fillBoundary;
        Short s = 0;
        if (remain != 0) {
            int fillNum = fillBoundary - remain;
            for (int i = 0; i < fillNum; i++) {
                featureTableBinary = byteMergerByList(featureTableBinary, int8ToLHByte(s));
            }
        }
        return featureTableBinary;
    }
    
    public static byte[] fillInputBytesWithZero(byte[] featureTableBinary, int fillNum) {
        Short s = 0;
        for (int i = 0; i < fillNum; i++) {
            featureTableBinary = byteMergerByList(featureTableBinary, int8ToLHByte(s));
        }
        return featureTableBinary;
    }
    
    public static byte[] int8ToLHByte(int n) {
        byte[] b = new byte[1];
        b[0] = (byte) (n & 0xff);
        return b;
    }
    
    public class FeatureTable {
        public int POINTS_LENGTH;
        public OffsetModel POSITION_QUANTIZED;
        public List QUANTIZED_VOLUME_OFFSET;
        public List QUANTIZED_VOLUME_SCALE;
        public OffsetModel RGB;
    }
    
    public static byte[] fillBytesWithEmpty(byte[] featureTableJsonBytes) {
        int length = featureTableJsonBytes.length;
        int remain = length % 8;
        String emptyStr = " ";
        if (remain != 0) {
            int fillNum = 8 - remain;
            for (int i = 0; i < fillNum; i++) {
                featureTableJsonBytes = byteMergerByList(featureTableJsonBytes, emptyStr.getBytes());
            }
        }
        return featureTableJsonBytes;
    }
    
    public BatchTable transferBatchTableItem(List pointList, List attributeTransferList) {
        BatchTable batchTable = new BatchTable();
        batchTable.items = new ArrayList<>();
        List pointModelFiledNames = getFiledName(new PointModel());
        for (PointAttributeTransferModel pointAttributeTransferModel : attributeTransferList) {
            String enumKey = pointAttributeTransferModel.field.getName().toLowerCase();
            List collect = pointModelFiledNames.stream().filter(it -> it.filedName.equals(enumKey)).collect(Collectors.toList());
    
            BatchTableItem batchTableItem = new BatchTableItem();
            batchTableItem.batchTableBaseItem = new BatchTableBaseItem();
            batchTableItem.batchTableBaseItem.byteOffset = 0;
            batchTableItem.batchTableBaseItem.componentType = ObjectUtils.isEmpty(collect) ? "DOUBLE" : collect.get(0).filedType.toUpperCase();
            batchTableItem.batchTableBaseItem.type = "SCALAR";
            batchTableItem.name = pointAttributeTransferModel.outputKey;
            List valueList = extractColumn(pointList, "enumKey");
            batchTableItem.dataList = valueList;
            batchTable.items.add(batchTableItem);
        }
        return batchTable;
    }
    
    public static List getFiledName(Object o) {
        List retList = new ArrayList<>();
        Field[] fields = o.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            FiledNameAndType filedNameAndType = new FiledNameAndType();
            String filedName = fields[i].getName();
            String filedType = fields[i].getType().toString();
            filedNameAndType.filedName = filedName;
            filedNameAndType.filedType = filedType;
            retList.add(filedNameAndType);
        }
        return retList;
    }
    
    public static  List extractColumn(List pointList, String fieldName) {
        return pointList.stream()
                .map(point -> {
                    try {
                        return (T) PointModel.class.getField(fieldName).get(point);
                    } catch (Exception e) {
                        e.printStackTrace();
                        return null;
                    }
                })
                .collect(Collectors.toList());
    }
    
                    
                        
                    
    
                    
  • 相关阅读:
    论文精读之 Google_v3,以及其相对于 Google_v1 和 Google_v2_BN 的模型比较
    《Kubernetes部署篇:Ubuntu20.04基于containerd二进制部署K8S 1.25.14集群(多主多从)》
    8. sqoop-1.4.7安装部署
    Python 爬取深交所交易日历
    怎么把多张图片合成gif?教你简单几步快速制作gif
    JavaWeb在线问题.Linux服务器MEM内存核查
    牛客多校2 - Link with Bracket Sequence I(括号序列,三维DP)
    go语言的channel笔记
    汽车零部件加工行业工业互联网智能工厂解决方案
    平衡小车调车保姆式教程
  • 原文地址:https://blog.csdn.net/yhzrf/article/details/132686819