From 3d6ff15899256f33cd100d95237f613c023d50df Mon Sep 17 00:00:00 2001
From: MrShi <1878285526@qq.com>
Date: 星期一, 08 十二月 2025 09:54:09 +0800
Subject: [PATCH] 优化

---
 server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/ClusterCustomKMeans.java |  147 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 147 insertions(+), 0 deletions(-)

diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/ClusterCustomKMeans.java b/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/ClusterCustomKMeans.java
new file mode 100644
index 0000000..8915a9b
--- /dev/null
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/ClusterCustomKMeans.java
@@ -0,0 +1,147 @@
+package com.doumee.core.tsp;
+
+import java.math.BigDecimal;
+import java.util.*;
+
+import com.doumee.core.utils.Constants;
+import com.doumee.dao.admin.request.SketchCateModel;
+import com.doumee.dao.business.model.JkSketchCustomer;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.math3.ml.clustering.*;
+import org.apache.commons.math3.ml.distance.EuclideanDistance;
+/**
+ *
+ * @author xjx
+ *
+ */
+@Slf4j
+public class ClusterCustomKMeans{
+    //娆у紡璺濈
+
+        public  List<SketchCateModel> clusterPoints(List<JkSketchCustomer> customers, int k, int d){
+            List<SketchCateModel> list = new ArrayList<>();
+            if(customers.size() <= k){
+                int index =0;
+                for (JkSketchCustomer c : customers) {
+                    SketchCateModel sketchCateModel = new SketchCateModel();
+                    sketchCateModel.setId(index);
+                    List<JkSketchCustomer> cList = new ArrayList<>();
+                    cList.add(c);
+                    sketchCateModel.setTotalNum(c.getTotalNum());
+                    sketchCateModel.setCustomerList(cList);
+                    sketchCateModel.setStartPoint(c);
+                    sketchCateModel.setTotalCustomer(1);
+                    list.add(sketchCateModel);
+                    log.error("Cluster " + index + "members锛�"+1+"/200 "+" 瀹㈡埛锛�"+   c.getName());
+                    index ++;
+                }
+                return list;
+            }
+            List<DoublePointNew> points = new ArrayList<>();
+            for (int i = 0; i < customers.size(); i++) {
+                DoublePointNew p = new DoublePointNew(new double[]{customers.get(i).getLatitude().doubleValue(), customers.get(i).getLongitude().doubleValue()});
+                p.setCustomer(customers.get(i));
+                points.add(p); // 绀轰緥鐐�1
+            }
+            KMeansPlusPlusClusterer<DoublePointNew> clusterer = new KMeansPlusPlusClusterer<>(k, d, new EuclideanDistance());
+            List<CentroidCluster<DoublePointNew>> clusters = clusterer.cluster(points);
+
+            int index  = 0;
+            int maxMembersPerCluster = 200; // 璁剧疆姣忎釜绨囩殑鏈�澶ф垚鍛樻暟
+            List<CentroidCluster<DoublePointNew>> allList = new ArrayList<>();
+            for (CentroidCluster<DoublePointNew> cluster : clusters) {
+                if(cluster.getPoints() ==null || cluster.getPoints().size() ==0){
+                    log.error("Cluster " + clusters.indexOf(cluster) + "members锛�"+cluster.getPoints().size()+"/200  鏃犳暟鎹�");
+                    continue;
+                }
+                log.error("Cluster " + clusters.indexOf(cluster) + "members锛�"+cluster.getPoints().size()+"/200 "+"涓績鐐癸細"+ Arrays.toString(cluster.getCenter().getPoint())+"涓績鐐癸細"+ cluster.getPoints().get(0).getCustomer().getName());
+                if (cluster.getPoints().size() > maxMembersPerCluster) {
+                    // 杩欓噷鍙互閲嶆柊杩愯鑱氱被绠楁硶鎴栬�呮墜鍔ㄨ皟鏁寸皣鐨勫垎閰嶇瓥鐣�
+                    log.error("Cluster " + clusters.indexOf(cluster) + " exceeds maximum members锛�" + cluster.getPoints().size() + "/200, re-clustering needed.");
+                    // 鍙互鑰冭檻鍐嶆璋冪敤KMeansPlusPlusClusterer鎴栧叾瀹冮�昏緫鏉ュ鐞嗚秴闄愭儏鍐点��
+                }
+                allList.add(cluster);
+            }
+            for (CentroidCluster<DoublePointNew> cluster : allList) {
+//                System.out.println("Cluster " + clusters.indexOf(cluster) + "members锛�"+cluster.getPoints().size()+"/200 ");
+                if (cluster.getPoints().size() > maxMembersPerCluster) {
+                    // 杩欓噷鍙互閲嶆柊杩愯鑱氱被绠楁硶鎴栬�呮墜鍔ㄨ皟鏁寸皣鐨勫垎閰嶇瓥鐣�
+//                    System.out.println("Cluster " + clusters.indexOf(cluster) + " exceeds maximum members锛�"+cluster.getPoints().size()+"/200, re-clustering needed.");
+                    // 鍙互鑰冭檻鍐嶆璋冪敤KMeansPlusPlusClusterer鎴栧叾瀹冮�昏緫鏉ュ鐞嗚秴闄愭儏鍐点��
+                }
+                SketchCateModel sketchCateModel = new SketchCateModel();
+                sketchCateModel.setId(index);
+                List<JkSketchCustomer> cList = new ArrayList<>();
+                for(DoublePointNew doublePointNew:cluster.getPoints()){
+                    cList.add(doublePointNew.getCustomer());
+                    sketchCateModel.setTotalNum(Constants.formatBigdecimal(sketchCateModel.getTotalNum()).add(Constants.formatBigdecimal(doublePointNew.getCustomer().getTotalNum())));
+                }
+                sortPointByCenterPoint(cluster,cList);
+                sketchCateModel.setCustomerList(cList);
+                sketchCateModel.setStartPoint(cList.get(0));
+                sketchCateModel.setTotalCustomer(cList.size());
+                list.add(sketchCateModel);
+            }
+            return list;
+        }
+
+    private void sortPointByCenterPoint(CentroidCluster<DoublePointNew> cluster, List<JkSketchCustomer> cList) {
+        double clat = Constants.formatBigdecimal(cList.get(0).getLatitude()).doubleValue();
+        double clong = Constants.formatBigdecimal(cList.get(0).getLongitude()).doubleValue();
+        if(cluster!=null || cluster.getCenter() != null || cluster.getCenter().getPoint() != null && cluster.getCenter().getPoint().length>=2){
+            clong = cluster.getCenter().getPoint()[1];
+            clat = cluster.getCenter().getPoint()[0];
+        }
+        for(JkSketchCustomer c : cList){
+            double latDiff = Constants.formatBigdecimal(c.getLatitude()).doubleValue() - clat;
+            double lonDiff = Constants.formatBigdecimal(c.getLongitude()).doubleValue() - clong;
+            c.setDistanceCenter(Math.sqrt(latDiff * latDiff + lonDiff * lonDiff)); // 娆ф皬璺濈
+        }
+        Collections.sort(cList, (p1, p2) -> Double.compare(p1.getDistanceCenter(), p2.getDistanceCenter()));
+    }
+
+    public  class  DoublePointNew extends  DoublePoint{
+        private JkSketchCustomer customer;
+
+        public DoublePointNew(double[] point) {
+            super(point);
+        }
+
+        public JkSketchCustomer getCustomer() {
+            return customer;
+        }
+
+        public void setCustomer(JkSketchCustomer customer) {
+            this.customer = customer;
+        }
+
+    }
+    public static void main(String[] args) {
+        List<JkSketchCustomer> points = new ArrayList<>();
+        for (int i = 0; i <10; i++) {
+            JkSketchCustomer a = new JkSketchCustomer();
+            a.setLatitude(new BigDecimal(30.19d ));
+            a.setLongitude(new BigDecimal(117.40 ));
+            a.setName("瀹㈡埛"+i);
+            points.add(a);
+        }
+        for (int i = 0; i <10; i++) {
+            JkSketchCustomer a = new JkSketchCustomer();
+            a.setLatitude(new BigDecimal(31.19d ));
+            a.setLongitude(new BigDecimal(118.40 ));
+            a.setName("瀹㈡埛"+i);
+            points.add(a);
+        }
+         for (int i = 10; i <3000; i++) {
+            JkSketchCustomer a = new JkSketchCustomer();
+            a.setLatitude(new BigDecimal(31.19d-(0.1d)*Math.random()));
+            a.setLongitude(new BigDecimal(118.40-(0.2d)*Math.random()));
+            a.setName("瀹㈡埛"+i);
+            points.add(a);
+        }
+
+        double threshold = 1000; // 璁剧疆璺濈闃堝�硷紝瓒呰繃杩欎釜璺濈灏变笉灞炰簬鍚屼竴鑱氱被銆�
+        (new ClusterCustomKMeans()).clusterPoints(points, 100,1);
+    }
+
+}
\ No newline at end of file

--
Gitblit v1.9.3