| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <classpath> |
| | | <classpathentry kind="src" path="src"/> |
| | | <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"> |
| | | <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"> |
| | | <attributes> |
| | | <attribute name="module" value="true"/> |
| | | </attributes> |
| | |
| | | # å²èæºå°åéç¢ç©é
ç½®æä»¶ |
| | | # çææ¶é´ï¼2025-12-27T13:39:05.917584700 |
| | | # çææ¶é´ï¼2025-12-27T16:33:13.889689700 |
| | | # åæ ç³»ï¼WGS84ï¼åº¦åæ ¼å¼ï¼ |
| | | |
| | | # ============ å°ååºåç«é
ç½® ============ |
| | |
| | | # æ ¼å¼ï¼plot.[å°åç¼å·].obstacle.[éç¢ç©åç§°].originalCoords=[åæ ä¸²] |
| | | # æ ¼å¼ï¼plot.[å°åç¼å·].obstacle.[éç¢ç©åç§°].xyCoords=[åæ ä¸²] |
| | | |
| | | # --- å°åLAND1çéç¢ç© --- |
| | | plot.LAND1.obstacle.éç¢ç©1.shape=1 |
| | | plot.LAND1.obstacle.éç¢ç©1.originalCoords=0.000000,N;0.000000,E;0.000000,N;0.000000,E;0.000000,N;0.000000,E;0.000000,N;0.000000,E |
| | | plot.LAND1.obstacle.éç¢ç©1.xyCoords=53.95,39.88;55.58,45.69;64.53,45.45;66.97,40.57 |
| | | |
| | |
| | | #Dikuai Properties |
| | | #Sat Dec 27 13:39:05 GMT+08:00 2025 |
| | | #Sat Dec 27 16:33:13 GMT+08:00 2025 |
| | | LAND1.intelligentSceneAnalysis=-1 |
| | | LAND1.mowingSafetyDistance=0.53 |
| | | LAND1.landArea=577.12 |
| | |
| | | LAND1.returnPathRawCoordinates=-1 |
| | | LAND1.boundaryOriginalXY=-1 |
| | | LAND1.mowingWidth=1.00 |
| | | LAND1.plannedPath=73.871028,49.873176;50.776259,50.037243;41.965934,22.443191;49.612130,19.993609;51.845415,34.259086;66.290000,36.696945;66.290000,21.401369;78.088741,24.750277;73.871028,49.873176;73.955072,49.372566;50.616974,49.538362;50.298405,48.540599;74.123160,48.371347;74.291248,47.370128;49.979836,47.542837;49.661267,46.545075;74.459336,46.368908;74.627423,45.367689;49.342698,45.547313;49.024129,44.549551;55.663908,44.502382;64.552007,44.439240;74.795511,44.366470;74.963599,43.365250;65.098159,43.435335;55.361561,43.504504;48.705560,43.551789;48.386992,42.554027;55.059215,42.506627;65.644310,42.431430;75.131687,42.364031;75.299775,41.362812;66.190462,41.427525;54.756869,41.508750;48.068423,41.556265;47.749854,40.558503;54.454523,40.510872;59.489469,40.475104;75.467863,40.361592;75.635951,39.360373;47.431285,39.560741;47.112716,38.562978;75.804039,38.359154;75.972127,37.357934;46.794147,37.565216;46.475578,36.567454;64.753396,36.437608;66.290000,36.426692;76.140215,36.356715;76.308303,35.355496;66.290000,35.426666;59.067471,35.477976;46.157009,35.569692;45.838440,34.571930;53.381545,34.518343;66.290000,34.426641;76.476391,34.354276;76.644478,33.353057;66.290000,33.426616;51.731282,33.530042;45.519871,33.574168;45.201302,32.576406;51.574900,32.531127;66.290000,32.426591;76.812566,32.351838;76.980654,31.350618;66.290000,31.426565;51.418519,31.532213;44.882733,31.578644;44.564164,30.580882;51.262137,30.533299;66.290000,30.426540;77.148742,30.349399;77.316830,29.348180;66.290000,29.426515;51.105755,29.534385;44.245595,29.583120;43.927026,28.585357;50.949373,28.535470;66.290000,28.426490;77.484918,28.346960;77.653006,27.345741;66.290000,27.426464;50.792992,27.536556;43.608458,27.587595;43.289889,26.589833;50.636610,26.537642;66.290000,26.426439;77.821094,26.344522;77.989182,25.343302;66.290000,25.426414;50.480228,25.538727;42.971320,25.592071;42.652751,24.594309;50.323846,24.539813;66.290000,24.426389;76.687398,24.352525;73.250178,23.376918;66.290000,23.426363;50.167465,23.540899;42.334182,23.596547;42.015613,22.598785;50.011083,22.541985;66.290000,22.426338;69.812957,22.401311;66.375737,21.425704;66.290000,21.426313;49.854701,21.543070;44.660415,21.579971;47.852711,20.557267;49.698319,20.544156 |
| | | LAND1.updateTime=2025-12-27 13\:39\:05 |
| | | LAND1.plannedPath=73.87,49.87;50.78,50.04;41.97,22.44;49.61,19.99;51.85,34.26;66.29,36.70;66.29,21.40;78.09,24.75;73.87,49.87;73.96,49.37;50.62,49.54;50.30,48.54;74.12,48.37;74.29,47.37;49.98,47.54;49.66,46.55;74.46,46.37;74.63,45.37;49.34,45.55;49.02,44.55;74.80,44.37;74.96,43.37;48.71,43.55;48.39,42.55;75.13,42.36;75.30,41.36;48.07,41.56;47.75,40.56;75.47,40.36;75.64,39.36;47.43,39.56;47.11,38.56;75.80,38.36;75.97,37.36;46.79,37.57;46.48,36.57;64.75,36.44;66.29,36.43;76.14,36.36;76.31,35.36;66.29,35.43;59.07,35.48;46.16,35.57;45.84,34.57;53.38,34.52;66.29,34.43;76.48,34.35;76.64,33.35;66.29,33.43;51.73,33.53;45.52,33.57;45.20,32.58;51.57,32.53;66.29,32.43;76.81,32.35;76.98,31.35;66.29,31.43;51.42,31.53;44.88,31.58;44.56,30.58;51.26,30.53;66.29,30.43;77.15,30.35;77.32,29.35;66.29,29.43;51.11,29.53;44.25,29.58;43.93,28.59;50.95,28.54;66.29,28.43;77.48,28.35;77.65,27.35;66.29,27.43;50.79,27.54;43.61,27.59;43.29,26.59;50.64,26.54;66.29,26.43;77.82,26.34;77.99,25.34;66.29,25.43;50.48,25.54;42.97,25.59;42.65,24.59;50.32,24.54;66.29,24.43;76.69,24.35;73.25,23.38;66.29,23.43;50.17,23.54;42.33,23.60;42.02,22.60;50.01,22.54;66.29,22.43;69.81,22.40;66.38,21.43;66.29,21.43;49.85,21.54;44.66,21.58;47.85,20.56;49.70,20.54 |
| | | LAND1.updateTime=2025-12-27 16\:33\:13 |
| | | LAND1.baseStationCoordinates=3949.89151752,N,11616.79267501,E |
| | | LAND1.boundaryPointInterval=-1 |
| | | LAND1.createTime=2025-12-23 17\:08\:09 |
| | |
| | | LAND1.landName=123 |
| | | LAND1.mowingTrack=-1 |
| | | LAND1.boundaryOriginalCoordinates=39.831522,116.279873,49.25;39.831524,116.279878,49.25;39.831525,116.279878,49.24;39.831524,116.279912,49.30;39.831524,116.279911,49.29;39.831523,116.279911,49.23;39.831521,116.279915,49.31;39.831517,116.279925,49.34;39.831514,116.279940,49.30;39.831514,116.279957,49.28;39.831516,116.279974,49.28;39.831518,116.279991,49.29;39.831521,116.280008,49.24;39.831524,116.280025,49.30;39.831526,116.280042,49.24;39.831529,116.280059,49.29;39.831529,116.280076,49.26;39.831530,116.280093,49.32;39.831531,116.280110,49.28;39.831533,116.280127,49.28;39.831535,116.280144,49.26;39.831539,116.280161,49.27;39.831544,116.280175,49.25;39.831551,116.280190,49.24;39.831558,116.280204,49.26;39.831566,116.280219,49.26;39.831574,116.280234,49.22;39.831583,116.280248,49.24;39.831591,116.280260,49.24;39.831600,116.280272,49.23;39.831608,116.280285,49.18;39.831615,116.280298,49.12;39.831618,116.280312,49.11;39.831618,116.280328,49.12;39.831615,116.280342,49.15;39.831610,116.280356,49.21;39.831602,116.280369,49.23;39.831592,116.280379,49.25;39.831581,116.280388,49.25;39.831569,116.280394,49.19;39.831559,116.280395,49.23;39.831552,116.280387,49.28;39.831547,116.280373,49.32;39.831544,116.280357,49.33;39.831541,116.280340,49.29;39.831539,116.280324,49.27;39.831536,116.280307,49.24;39.831534,116.280290,49.25;39.831531,116.280273,49.26;39.831527,116.280257,49.28;39.831522,116.280242,49.21;39.831514,116.280232,49.28;39.831504,116.280229,49.24;39.831491,116.280230,49.33;39.831478,116.280233,49.34;39.831466,116.280236,49.31;39.831454,116.280239,49.31;39.831441,116.280242,49.26;39.831429,116.280244,49.23;39.831416,116.280247,49.25;39.831402,116.280250,49.22;39.831389,116.280253,49.25;39.831376,116.280256,49.26;39.831364,116.280258,49.24;39.831351,116.280261,49.25;39.831338,116.280265,49.26;39.831324,116.280268,49.20;39.831311,116.280271,49.16;39.831298,116.280274,49.17;39.831285,116.280277,49.22;39.831271,116.280278,49.16;39.831261,116.280273,49.23 |
| | | LAND1.obstacleCoordinates=(53.95,39.88;55.58,45.69;64.53,45.45;66.97,40.57) |
| | | LAND1.obstacleCoordinates=-1 |
| | | LAND1.boundaryCoordinates=50.39,50.57;74.32,50.40;78.69,24.37;65.76,20.70;65.76,36.07;52.31,33.80;50.04,19.30;41.30,22.10 |
| | | LAND1.mowingBladeWidth=0.51 |
| | |
| | | #Mower Configuration Properties - Updated |
| | | #Sat Dec 27 13:39:12 GMT+08:00 2025 |
| | | #Current work land selection updated |
| | | #Sat Dec 27 20:42:43 GMT+08:00 2025 |
| | | appVersion=-1 |
| | | simCardNumber=-1 |
| | | currentWorkLandNumber=LAND1 |
| | |
| | | boundaryLengthVisible=false |
| | | idleTrailDurationSeconds=60 |
| | | handheldMarkerId=1872 |
| | | viewCenterX=-60.00 |
| | | viewCenterY=-34.94 |
| | | viewCenterX=-61.89 |
| | | viewCenterY=-39.06 |
| | | manualBoundaryDrawingMode=false |
| | | mowerId=6258 |
| | | serialPortName=COM15 |
| | | serialAutoConnect=true |
| | | mapScale=10.32 |
| | | mapScale=17.84 |
| | | measurementModeEnabled=false |
| | | firmwareVersion=-1 |
| | | cuttingWidth=200 |
| | |
| | | */ |
| | | public void connect() throws MqttException { |
| | | if (client != null && client.isConnected()) { |
| | | System.out.println("MQTT客æ·ç«¯å·²è¿æ¥ï¼ClientId: " + clientId); |
| | | return; |
| | | } |
| | | |
| | |
| | | |
| | | // æ§è¡è¿æ¥ |
| | | client.connect(options); |
| | | System.out.println("MQTTè¿æ¥æåï¼ClientId: " + clientId + ", æå¡å¨: " + host + ", 主é¢: " + topic); |
| | | |
| | | // å¯å¨è¿æ¥çæ§çº¿ç¨ |
| | | startConnectionMonitor(); |
| | |
| | | connect(); |
| | | } |
| | | client.subscribe(topic, qos); |
| | | System.out.println("已订é
主é¢: " + topic + ", QoS: " + qos); |
| | | } |
| | | |
| | | /** |
| | |
| | | Thread.sleep(5000); // æ¯5ç§æ£æ¥ä¸æ¬¡ |
| | | |
| | | if (client != null && !client.isConnected()) { |
| | | System.out.println("æ£æµå°MQTTè¿æ¥æå¼ï¼å°è¯éè¿... ClientId: " + clientId); |
| | | try { |
| | | // å°è¯éæ°è¿æ¥ |
| | | if (!client.isConnected()) { |
| | |
| | | // éè¿æååéæ°è®¢é
|
| | | if (client.isConnected()) { |
| | | client.subscribe(topic, qos); |
| | | System.out.println("è¿æ¥çæ§ï¼éè¿æåå¹¶éæ°è®¢é
主é¢: " + topic); |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | |
| | | connectionMonitorThread.setDaemon(true); |
| | | connectionMonitorThread.setName("MQTT-ConnectionMonitor-" + clientId); |
| | | connectionMonitorThread.start(); |
| | | System.out.println("å·²å¯å¨MQTTè¿æ¥çæ§çº¿ç¨: " + clientId); |
| | | } |
| | | |
| | | /** |
| | |
| | | public static boolean connectMQTT() { |
| | | // 鲿¢éå¤éè¿ |
| | | if (isReconnecting) { |
| | | System.out.println("MQTTæ£å¨éè¿ä¸ï¼è·³è¿æ¬æ¬¡éè¿è¯·æ±"); |
| | | return false; |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦å·²ç»è¿æ¥ |
| | | if (areClientsConnected()) { |
| | | System.out.println("MQTT客æ·ç«¯å·²è¿æ¥ï¼æ ééå¤è¿æ¥"); |
| | | return true; |
| | | } |
| | | |
| | |
| | | if (gpsClient != null && gpsClient.isConnected()) { |
| | | gpsClient.subscribe(); |
| | | gpsSuccess = true; |
| | | System.out.println("GPS主é¢MQTTè¿æ¥å¹¶è®¢é
æå"); |
| | | } |
| | | } catch (MqttException e) { |
| | | System.err.println("GPS主é¢MQTTè¿æ¥å¤±è´¥: " + e.getMessage()); |
| | |
| | | if (responseClient != null && responseClient.isConnected()) { |
| | | responseClient.subscribe(); |
| | | responseSuccess = true; |
| | | System.out.println("ååºä¸»é¢MQTTè¿æ¥å¹¶è®¢é
æå"); |
| | | } |
| | | } catch (MqttException e) { |
| | | System.err.println("ååºä¸»é¢MQTTè¿æ¥å¤±è´¥: " + e.getMessage()); |
| | |
| | | } |
| | | |
| | | if (gpsSuccess && responseSuccess) { |
| | | System.out.println("ææMQTT主é¢è¿æ¥å¹¶è®¢é
æåï¼"); |
| | | return true; |
| | | } else if (gpsSuccess || responseSuccess) { |
| | | System.out.println("é¨åMQTT主é¢è¿æ¥æå"); |
| | | return true; |
| | | } else { |
| | | System.err.println("ææMQTT主é¢è¿æ¥å¤±è´¥"); |
| | |
| | | public static boolean connectMQTT(String host, String deviceId, String userEmail) { |
| | | // 鲿¢éå¤éè¿ |
| | | if (isReconnecting) { |
| | | System.out.println("MQTTæ£å¨éè¿ä¸ï¼è·³è¿æ¬æ¬¡éè¿è¯·æ±"); |
| | | return false; |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦å·²ç»è¿æ¥ |
| | | if (areClientsConnected()) { |
| | | System.out.println("MQTT客æ·ç«¯å·²è¿æ¥ï¼æ ééå¤è¿æ¥"); |
| | | return true; |
| | | } |
| | | |
| | |
| | | if (gpsClient != null && gpsClient.isConnected()) { |
| | | gpsClient.subscribe(); |
| | | gpsSuccess = true; |
| | | System.out.println("GPS主é¢MQTTè¿æ¥å¹¶è®¢é
æå"); |
| | | } |
| | | } catch (MqttException e) { |
| | | System.err.println("GPS主é¢MQTTè¿æ¥å¤±è´¥: " + e.getMessage()); |
| | |
| | | if (responseClient != null && responseClient.isConnected()) { |
| | | responseClient.subscribe(); |
| | | responseSuccess = true; |
| | | System.out.println("ååºä¸»é¢MQTTè¿æ¥å¹¶è®¢é
æå"); |
| | | } |
| | | } catch (MqttException e) { |
| | | System.err.println("ååºä¸»é¢MQTTè¿æ¥å¤±è´¥: " + e.getMessage()); |
| | |
| | | } |
| | | |
| | | if (gpsSuccess && responseSuccess) { |
| | | System.out.println("ææMQTT主é¢è¿æ¥å¹¶è®¢é
æåï¼"); |
| | | return true; |
| | | } else if (gpsSuccess || responseSuccess) { |
| | | System.out.println("é¨åMQTT主é¢è¿æ¥æå"); |
| | | return true; |
| | | } else { |
| | | System.err.println("ææMQTT主é¢è¿æ¥å¤±è´¥"); |
| | |
| | | Client mqttClient = new Client(host, topic, clientId); |
| | | mqttClient.connect(); |
| | | mqttClient.subscribe(qos); |
| | | System.out.println("MQTT客æ·ç«¯å建并订é
æåï¼ä¸»é¢: " + topic + ", ClientId: " + clientId); |
| | | return mqttClient; |
| | | } catch (MqttException e) { |
| | | System.err.println("MQTT客æ·ç«¯å建失败: " + e.getMessage() + ", 主é¢: " + topic); |
| | |
| | | try { |
| | | if (gpsClient != null) { |
| | | gpsClient.close(); |
| | | System.out.println("GPS主é¢MQTTè¿æ¥å·²æå¼"); |
| | | gpsClient = null; |
| | | } |
| | | if (responseClient != null) { |
| | | responseClient.close(); |
| | | System.out.println("ååºä¸»é¢MQTTè¿æ¥å·²æå¼"); |
| | | responseClient = null; |
| | | } |
| | | } catch (Exception e) { |
| | |
| | | try { |
| | | // éæ°è®¢é
ä¸»é¢ |
| | | clientInstance.getClient().subscribe(topic, qos); |
| | | System.out.println("MQTTéè¿æåï¼å·²éæ°è®¢é
主é¢: " + topic); |
| | | return; // éè¿æåï¼éåºå¾ªç¯ |
| | | } catch (Exception e) { |
| | | System.err.println("éæ°è®¢é
主é¢å¤±è´¥: " + e.getMessage()); |
| | |
| | | } |
| | | |
| | | retryCount++; |
| | | if (retryCount % 5 == 0) { |
| | | System.out.println("çå¾
MQTTèªå¨éè¿... (" + retryCount + "/" + maxRetries + ")"); |
| | | } |
| | | } catch (InterruptedException e) { |
| | | Thread.currentThread().interrupt(); |
| | | System.err.println("éè¿çº¿ç¨è¢«ä¸æ"); |
| | |
| | | clientInstance.connect(); |
| | | if (clientInstance.isConnected()) { |
| | | clientInstance.subscribe(qos); |
| | | System.out.println("æå¨éè¿æåï¼å·²éæ°è®¢é
主é¢: " + topic); |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | |
| | | } |
| | | |
| | | public void deliveryComplete(IMqttDeliveryToken token) { |
| | | System.out.println("deliveryComplete---------" + token.isComplete()); |
| | | // 交ä»å®æåè° |
| | | } |
| | | |
| | | public void messageArrived(String topic, MqttMessage message) throws Exception { |
| | |
| | | // é«çº§å¤çè¾¹çæ°æ®æ¹æ³ |
| | | public List<Coordinate> processBoundaryDataAdvanced(String gnggaData, double baseLat, double baseLon, |
| | | BoundaryParameters params) { |
| | | System.out.println("å¼å§å¤çè¾¹çæ°æ®..."); |
| | | System.out.println("åºåç«åæ : " + baseLat + ", " + baseLon); |
| | | System.out.println("åæ°: é´é=" + params.interval + "ç±³, è§åº¦éå¼=" + params.angleThreshold + "度"); |
| | | |
| | | // 1. è§£æGNGGAæ°æ® |
| | | List<Coordinate> rawPoints = parseGNGGA(gnggaData, baseLat, baseLon); |
| | | System.out.println("è§£æå°åå§ç¹: " + rawPoints.size() + " 个"); |
| | | |
| | | if (rawPoints.size() < 3) { |
| | | System.out.println("æ°æ®ç¹ä¸è¶³ï¼æ æ³å½¢æè¾¹ç"); |
| | | return new ArrayList<>(); |
| | | } |
| | | |
| | | // 2. è¿æ»¤åå¹³æ»æ°æ® |
| | | List<Coordinate> filteredPoints = filterAndSmoothPoints(rawPoints); |
| | | System.out.println("è¿æ»¤åç¹: " + filteredPoints.size() + " 个"); |
| | | |
| | | // 3. é«çº§è¾¹çç¹ä¼å |
| | | List<Coordinate> optimizedPoints = optimizeBoundaryPointsAdvanced(filteredPoints, params); |
| | | System.out.println("ä¼ååè¾¹çç¹: " + optimizedPoints.size() + " 个"); |
| | | |
| | | // 4. è¾¹çè´¨éè¯ä¼° |
| | | BoundaryQuality quality = evaluateBoundaryQuality(optimizedPoints); |
| | | System.out.println(quality.toString()); |
| | | |
| | | return optimizedPoints; |
| | | } |
| | |
| | | // 5. èªå¨éæ©é¢è®¾åºæ¯ |
| | | selectPresetAutomatically(analysis); |
| | | |
| | | System.out.println(analysis.toString()); |
| | | return analysis; |
| | | } |
| | | |
| | |
| | | } else { |
| | | analysis.suggestedPreset = "夿å°åºå"; |
| | | } |
| | | |
| | | System.out.println("èªå¨åºæ¯éæ©å¾å: " + String.format("%.2f", score) + " -> " + analysis.suggestedPreset); |
| | | } |
| | | |
| | | // æ ¹æ®åºæ¯åç§°è·ååæ° |
| | |
| | | } |
| | | |
| | | String[] records = gnggaData.split("\\$GNGGA"); |
| | | System.out.println("æ¾å°GNGGAè®°å½: " + (records.length - 1) + " æ¡"); |
| | | |
| | | for (String record : records) { |
| | | try { |
| | |
| | | |
| | | String[] fields = trimmedRecord.split(","); |
| | | if (fields.length < 7) { |
| | | System.out.println("è®°å½å段ä¸è¶³: " + trimmedRecord); |
| | | continue; |
| | | } |
| | | |
| | |
| | | try { |
| | | fixStatus = Integer.parseInt(fields[6]); |
| | | } catch (NumberFormatException e) { |
| | | System.out.println("å®ä½ç¶ææ ¼å¼é误: " + fields[6]); |
| | | continue; |
| | | } |
| | | |
| | | if (fixStatus != 4) { |
| | | System.out.println("è·³è¿éé«ç²¾åº¦å®ä½ç¹ï¼ç¶æ: " + fixStatus); |
| | | continue; |
| | | } |
| | | |
| | |
| | | double speed = calculateDistance(points.get(i-1), points.get(i)); |
| | | if (speed < 5.0) { // æå¤§åçé度为5ç±³/ç§ |
| | | filtered.add(points.get(i)); |
| | | } else { |
| | | System.out.println("ç§»é¤é«éç¹: é度=" + speed + "ç±³/ç§"); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | // 1. é¦å
è¿è¡éæ ¼ææ¯-æ®å
ç®æ³ç®å |
| | | List<Coordinate> simplified = douglasPeuckerSimplification(points, params.simplificationTolerance); |
| | | System.out.println("éæ ¼ææ¯-æ®å
ç®åå: " + simplified.size() + " 个ç¹"); |
| | | |
| | | // 2. åºäºè·ç¦»åè§åº¦çè¿ä¸æ¥ä¼å |
| | | optimized.add(simplified.get(0)); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package chuankou; |
| | | |
| | | public interface DataListener<T> { |
| | | void accept(T t); |
| | | } |
| | |
| | | */ |
| | | public static void enableDebugMode() { |
| | | DEBUG_MODE = true; |
| | | System.out.println("[" + getCurrentTime() + "] Sendmsgè°è¯æ¨¡å¼å·²å¯ç¨"); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public static void disableDebugMode() { |
| | | DEBUG_MODE = false; |
| | | System.out.println("[" + getCurrentTime() + "] Sendmsgè°è¯æ¨¡å¼å·²ç¦ç¨"); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public static void setDebugMode(boolean debug) { |
| | | DEBUG_MODE = debug; |
| | | System.out.println("[" + getCurrentTime() + "] Sendmsgè°è¯æ¨¡å¼: " + (debug ? "å¯ç¨" : "ç¦ç¨")); |
| | | } |
| | | |
| | | /** |
| | |
| | | // æ¸
çThreadLocalèµæº |
| | | TIME_FORMATTER.remove(); |
| | | STRING_BUILDER_CACHE.remove(); |
| | | |
| | | if (DEBUG_MODE) { |
| | | System.out.println("[" + getCurrentTime() + "] Sendmsgèµæºæ¸
ç宿"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | // æ£æ¥ç¼å²åºå®¹éï¼å¨æå¤ç |
| | | if (!ensureBufferCapacity(rawData.length)) { |
| | | // ç¼å²åºä¸è¶³æ¶ï¼æ¸
çå¹¶éæ°å¼å§ |
| | | if (debugEnabled) { |
| | | System.out.println("ç¼å²åºä¸è¶³ï¼æ¸
空ç¼å²åºéæ°å¼å§"); |
| | | } |
| | | bufferPosition = 0; |
| | | } |
| | | |
| | |
| | | int startIndex = findStartMarker(); |
| | | if (startIndex == -1) { |
| | | // æ²¡ææ¾å°èµ·å§æ è®°ï¼æ¸
ç©ºæ ææ°æ® |
| | | if (debugEnabled) { |
| | | System.out.println("æªæ¾å°èµ·å§æ è®°ï¼æ¸
空ç¼å²åº"); |
| | | } |
| | | bufferPosition = 0; |
| | | return; |
| | | } |
| | |
| | | |
| | | // æ£æ¥æ°æ®é¿åº¦æææ§ |
| | | if (dataLength < 0 || totalPacketLength > BUFFER_SIZE) { |
| | | if (debugEnabled) { |
| | | System.out.println("æ ææ°æ®é¿åº¦: " + dataLength + ", è·³è¿èµ·å§åè"); |
| | | } |
| | | // è·³è¿é误çèµ·å§æ è®°ï¼ç»§ç»æ¥æ¾ |
| | | compactBuffer(startIndex + 1); |
| | | continue; |
| | |
| | | // æå宿´æ°æ®å
|
| | | byte[] packet = Arrays.copyOfRange(dataBuffer, startIndex, startIndex + totalPacketLength); |
| | | |
| | | if (debugEnabled) { |
| | | System.out.println("è§£æå°å®æ´æ°æ®å
: " + bytesToHex(packet)); |
| | | } |
| | | |
| | | // æ·»å å°è¿åå表 |
| | | completePackets.add(packet); |
| | | |
| | |
| | | * æå°åå§æ°æ®ï¼è°è¯ç¨ï¼ |
| | | */ |
| | | private void printRawData(String prefix, byte[] data, int maxPrintLength) { |
| | | if (data == null || data.length == 0) { |
| | | System.out.println(prefix + ": ç©ºæ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | StringBuilder sb = new StringBuilder(); |
| | | sb.append(prefix).append(" [é¿åº¦: ").append(data.length).append("]: "); |
| | | |
| | | int printLength = Math.min(data.length, maxPrintLength); |
| | | for (int i = 0; i < printLength; i++) { |
| | | sb.append(String.format("%02X ", data[i])); |
| | | } |
| | | |
| | | if (data.length > maxPrintLength) { |
| | | sb.append("... [æªæï¼æ»é¿åº¦: ").append(data.length).append("]"); |
| | | } |
| | | |
| | | System.out.println(sb.toString()); |
| | | // è°è¯è¾åºå·²ç§»é¤ |
| | | } |
| | | |
| | | /** |
| | |
| | | if (opened) { |
| | | service.ensureCaptureRunning(); |
| | | service.setPaused(false); |
| | | System.out.println("串å£èªå¨è¿æ¥æå: " + portName + " @ " + baudRate); |
| | | } else { |
| | | System.err.println("串å£èªå¨è¿æ¥å¤±è´¥: " + portName + " @ " + baudRate); |
| | | } |
| | |
| | | return; |
| | | } |
| | | |
| | | System.out.println("å¼å§åå§å jSerialComm æ¬å°åº..."); |
| | | |
| | | // ç¬¬ä¸æ¥ï¼è®¾ç½®ç³»ç»å±æ§ï¼é»æ¢èªå¨ä¸è½½ |
| | | setCriticalSystemProperties(); |
| | |
| | | try { |
| | | extractNativeLibraryFromResources(); |
| | | libraryConfigured = true; |
| | | System.out.println("jSerialComm æ¬å°åºåå§åæå"); |
| | | } catch (Exception e) { |
| | | System.err.println("ä»èµæºæå DLL 失败: " + e.getMessage()); |
| | | // å°è¯å¤ç¨æ¹æ¡ |
| | | try { |
| | | setupLibraryFromFileSystem(); |
| | | libraryConfigured = true; |
| | | System.out.println("ä»æä»¶ç³»ç»å è½½ jSerialComm æå"); |
| | | } catch (Exception ex) { |
| | | System.err.println("ææå è½½æ¹å¼é½å¤±è´¥: " + ex.getMessage()); |
| | | // æåå°è¯ï¼å
许 jSerialComm 使ç¨é»è®¤æ¹å¼ |
| | |
| | | // ç¦ç¨æ¥å¿åè°è¯ |
| | | System.setProperty("com.fazecast.jSerialComm.debug", "false"); |
| | | System.setProperty("com.fazecast.jSerialComm.log", "false"); |
| | | |
| | | System.out.println("已设置 jSerialComm ç³»ç»å±æ§"); |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | // æ£æ¥ DLL æ¯å¦å·²åå¨ä¸å¯ç¨ |
| | | if (Files.exists(dllPath)) { |
| | | System.out.println("DLL å·²åå¨äº: " + dllPath); |
| | | // 设置åºè·¯å¾ |
| | | System.setProperty(LIB_PROPERTY, targetDir.toString()); |
| | | return; |
| | |
| | | } |
| | | } |
| | | |
| | | System.out.println("DLL å·²æåå°: " + dllPath); |
| | | |
| | | // 设置åºè·¯å¾ |
| | | System.setProperty(LIB_PROPERTY, targetDir.toString()); |
| | | System.setProperty("java.library.path", |
| | |
| | | for (String path : possiblePaths) { |
| | | File dllFile = new File(path); |
| | | if (dllFile.exists()) { |
| | | System.out.println("æ¾å° DLL: " + dllFile.getAbsolutePath()); |
| | | // ä½¿ç¨ DLL æå¨ç®å½ |
| | | File parentDir = dllFile.getParentFile(); |
| | | System.setProperty(LIB_PROPERTY, parentDir.getAbsolutePath()); |
| | |
| | | import user.Usrdell; |
| | | import Mqttmessage.Client; |
| | | import login.LoginVerifier; |
| | | import publicway.buttonset; |
| | | import javax.swing.*; |
| | | import java.awt.*; |
| | | import java.awt.event.*; |
| | |
| | | private JPasswordField passwordField; |
| | | private JCheckBox rememberMe; |
| | | private JButton loginButton; |
| | | private JButton registerButton; |
| | | private Map<String, Map<String, String>> translations; |
| | | private JPanel mainPanel; |
| | | private JLabel usernameLabel, passwordLabel; |
| | | private JLabel forgotPassword, noAccountLabel, signupLink, appInfoLabel; |
| | | private JLabel forgotPassword, noAccountLabel, signupLink; |
| | | |
| | | // 主é¢é¢è² |
| | | private final Color THEME_COLOR = new Color(46, 139, 87); |
| | |
| | | zh.put("sign_up", "ç«å³æ³¨å"); |
| | | zh.put("app_title", "æºè½å²èç³»ç»"); |
| | | zh.put("window_title", "æºè½å²èç³»ç» - ç»å½"); |
| | | zh.put("app_info", "æºè½å²èç³»ç» Â© 2023 - æºè½å²èè§£å³æ¹æ¡"); |
| | | zh.put("register_button", "æ³¨åæ°è´¦æ·"); |
| | | translations.put("zh", zh); |
| | | |
| | |
| | | en.put("sign_up", "Sign Up"); |
| | | en.put("app_title", "Smart Mowing System"); |
| | | en.put("window_title", "Smart Mowing System - Login"); |
| | | en.put("app_info", "Smart Mowing System © 2023 - Intelligent Lawn Care"); |
| | | en.put("register_button", "Create New Account"); |
| | | translations.put("en", en); |
| | | |
| | |
| | | es.put("sign_up", "RegÃstrate"); |
| | | es.put("app_title", "Sistema de Corte Inteligente"); |
| | | es.put("window_title", "Sistema de Corte Inteligente - Iniciar Sesión"); |
| | | es.put("app_info", "Sistema de Corte Inteligente © 2023 - Soluciones Inteligentes"); |
| | | es.put("register_button", "Crear Nueva Cuenta"); |
| | | translations.put("es", es); |
| | | |
| | |
| | | fr.put("sign_up", "S'inscrire"); |
| | | fr.put("app_title", "Système de Tonte Intelligent"); |
| | | fr.put("window_title", "Système de Tonte Intelligent - Connexion"); |
| | | fr.put("app_info", "Système de Tonte Intelligent © 2023 - Solutions de Tonte"); |
| | | fr.put("register_button", "Créer un Nouveau Compte"); |
| | | translations.put("fr", fr); |
| | | |
| | |
| | | de.put("sign_up", "Registrieren"); |
| | | de.put("app_title", "Intelligentes Mähsystem"); |
| | | de.put("window_title", "Intelligentes Mähsystem - Anmeldung"); |
| | | de.put("app_info", "Intelligentes Mähsystem © 2023 - Mählösungen"); |
| | | de.put("register_button", "Neues Konto Erstellen"); |
| | | translations.put("de", de); |
| | | } |
| | |
| | | // 主表ååºå |
| | | JPanel formPanel = createFormPanel(); |
| | | |
| | | // åºé¨åºç¨ä¿¡æ¯ |
| | | JPanel appInfoPanel = createAppInfoPanel(); |
| | | // åºé¨é¢æ¿ï¼å
嫿³¨å龿¥ï¼ |
| | | JPanel bottomPanel = createBottomPanel(); |
| | | |
| | | mainPanel.add(topPanel, BorderLayout.NORTH); |
| | | mainPanel.add(formPanel, BorderLayout.CENTER); |
| | | mainPanel.add(appInfoPanel, BorderLayout.SOUTH); |
| | | mainPanel.add(bottomPanel, BorderLayout.SOUTH); |
| | | |
| | | add(mainPanel); |
| | | } |
| | |
| | | rememberForgotPanel.add(rememberMe, BorderLayout.WEST); |
| | | rememberForgotPanel.add(forgotPassword, BorderLayout.EAST); |
| | | |
| | | // ç»å½æé® - æ°´å¹³å±
ä¸ï¼é¿åº¦ä¸ææ¬æ¡å®½åº¦ä¿æç¸è¿ |
| | | // ç»å½æé® - 使ç¨buttonsetåå»ºï¼æ°´å¹³å±
ä¸ï¼é¿åº¦ä¸ææ¬æ¡å®½åº¦ä¿æç¸è¿ |
| | | JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); |
| | | buttonPanel.setBackground(Color.WHITE); |
| | | buttonPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 50)); |
| | | |
| | | loginButton = new JButton("ç»å½"); |
| | | loginButton.setBackground(THEME_COLOR); |
| | | loginButton.setForeground(Color.WHITE); |
| | | // 使ç¨buttonsetå建ç»å½æé®ï¼ä½¿ç¨ä¸»é¢è² |
| | | loginButton = buttonset.createStyledButton("ç»å½", THEME_COLOR); |
| | | loginButton.setFont(new Font("PingFang SC", Font.BOLD, 15)); |
| | | // 设置ç»å½æé®é¿åº¦æ¥è¿ææ¬æ¡å®½åº¦ |
| | | loginButton.setPreferredSize(new Dimension(300, 48)); |
| | | loginButton.setBorderPainted(false); |
| | | loginButton.setFocusPainted(false); |
| | | loginButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); |
| | | |
| | | // é¼ æ æ¬åææ |
| | | loginButton.addMouseListener(new MouseAdapter() { |
| | | public void mouseEntered(MouseEvent e) { |
| | | loginButton.setBackground(THEME_HOVER_COLOR); |
| | | } |
| | | public void mouseExited(MouseEvent e) { |
| | | loginButton.setBackground(THEME_COLOR); |
| | | } |
| | | }); |
| | | loginButton.setMinimumSize(new Dimension(300, 48)); |
| | | loginButton.setMaximumSize(new Dimension(300, 48)); |
| | | |
| | | buttonPanel.add(loginButton); |
| | | |
| | | // 注åæé® - æ´ææ¾ç注åå
¥å£ |
| | | JPanel registerButtonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); |
| | | registerButtonPanel.setBackground(Color.WHITE); |
| | | registerButtonPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 45)); |
| | | |
| | | registerButton = new JButton("æ³¨åæ°è´¦æ·"); |
| | | registerButton.setBackground(Color.WHITE); |
| | | registerButton.setForeground(THEME_COLOR); |
| | | registerButton.setFont(new Font("PingFang SC", Font.BOLD, 14)); |
| | | registerButton.setPreferredSize(new Dimension(180, 42)); |
| | | registerButton.setBorder(BorderFactory.createCompoundBorder( |
| | | BorderFactory.createLineBorder(THEME_COLOR), |
| | | BorderFactory.createEmptyBorder(5, 15, 5, 15) |
| | | )); |
| | | registerButton.setFocusPainted(false); |
| | | registerButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); |
| | | |
| | | // 注åæé®æ¬åææ |
| | | registerButton.addMouseListener(new MouseAdapter() { |
| | | public void mouseEntered(MouseEvent e) { |
| | | registerButton.setBackground(new Color(240, 250, 240)); |
| | | } |
| | | public void mouseExited(MouseEvent e) { |
| | | registerButton.setBackground(Color.WHITE); |
| | | } |
| | | }); |
| | | |
| | | registerButtonPanel.add(registerButton); |
| | | |
| | | // 注å龿¥ï¼ä¿çåæçææ¬é¾æ¥ï¼ |
| | | JPanel signupPanel = new JPanel(); |
| | | signupPanel.setBackground(Color.WHITE); |
| | | noAccountLabel = new JLabel("è¿æ²¡æè´¦æ·ï¼ "); |
| | | noAccountLabel.setFont(new Font("PingFang SC", Font.PLAIN, 12)); |
| | | noAccountLabel.setForeground(new Color(120, 120, 120)); |
| | | signupLink = new JLabel("ç«å³æ³¨å"); |
| | | signupLink.setFont(new Font("PingFang SC", Font.BOLD, 12)); |
| | | signupLink.setForeground(THEME_COLOR); |
| | | signupLink.setCursor(new Cursor(Cursor.HAND_CURSOR)); |
| | | signupPanel.add(noAccountLabel); |
| | | signupPanel.add(signupLink); |
| | | |
| | | // ç»è£
表å |
| | | formPanel.add(Box.createRigidArea(new Dimension(0, 15))); |
| | | formPanel.add(usernameLabel); |
| | |
| | | formPanel.add(rememberForgotPanel); |
| | | formPanel.add(Box.createRigidArea(new Dimension(0, 20))); |
| | | formPanel.add(buttonPanel); // ç»å½æé® |
| | | formPanel.add(Box.createRigidArea(new Dimension(0, 15))); |
| | | formPanel.add(registerButtonPanel); // 注åæé® |
| | | formPanel.add(Box.createRigidArea(new Dimension(0, 15))); |
| | | formPanel.add(signupPanel); // ä¿çåæç注å龿¥ |
| | | |
| | | return formPanel; |
| | | } |
| | | |
| | | private JPanel createAppInfoPanel() { |
| | | JPanel appInfoPanel = new JPanel(); |
| | | appInfoPanel.setBackground(Color.WHITE); |
| | | appInfoPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 5, 0)); |
| | | appInfoLabel = new JLabel( |
| | | getTranslationValue(currentLanguageCode, "app_info", "æºè½å²èç³»ç» Â© 2023") |
| | | ); |
| | | appInfoLabel.setFont(new Font("PingFang SC", Font.PLAIN, 10)); |
| | | appInfoLabel.setForeground(new Color(150, 150, 150)); |
| | | appInfoPanel.add(appInfoLabel); |
| | | private JPanel createBottomPanel() { |
| | | JPanel bottomPanel = new JPanel(); |
| | | bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS)); |
| | | bottomPanel.setBackground(Color.WHITE); |
| | | |
| | | return appInfoPanel; |
| | | // 注å龿¥ï¼æ¾å°é¡µé¢æä¸æ¹ï¼ |
| | | JPanel signupPanel = new JPanel(); |
| | | signupPanel.setBackground(Color.WHITE); |
| | | noAccountLabel = new JLabel("è¿æ²¡æè´¦æ·ï¼ "); |
| | | noAccountLabel.setFont(new Font("PingFang SC", Font.PLAIN, 12)); |
| | | noAccountLabel.setForeground(new Color(120, 120, 120)); |
| | | signupLink = new JLabel("ç«å³æ³¨å"); |
| | | signupLink.setFont(new Font("PingFang SC", Font.BOLD, 12)); |
| | | signupLink.setForeground(THEME_COLOR); |
| | | signupLink.setCursor(new Cursor(Cursor.HAND_CURSOR)); |
| | | signupPanel.add(noAccountLabel); |
| | | signupPanel.add(signupLink); |
| | | signupPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 5, 0)); |
| | | |
| | | // 注å龿¥æ¾å¨æåºé¨ |
| | | bottomPanel.add(signupPanel); |
| | | |
| | | return bottomPanel; |
| | | } |
| | | |
| | | private void setupEventHandlers() { |
| | |
| | | openRegistrationWindow(); |
| | | } |
| | | }); |
| | | |
| | | // 注åæé®ç¹å»äºä»¶ - æå¼æ³¨åçªå£ |
| | | registerButton.addActionListener(e -> openRegistrationWindow()); |
| | | } |
| | | |
| | | private void updateLanguage(String language) { |
| | |
| | | loginButton.setText(getTranslationValue(langCode, "login_button", loginButton.getText())); |
| | | noAccountLabel.setText(getTranslationValue(langCode, "no_account", noAccountLabel.getText())); |
| | | signupLink.setText(getTranslationValue(langCode, "sign_up", signupLink.getText())); |
| | | appInfoLabel.setText(getTranslationValue(langCode, "app_info", appInfoLabel.getText())); |
| | | |
| | | // æ´æ°æ³¨åæé®ææ¬ |
| | | registerButton.setText(getTranslationValue(langCode, "register_button", registerButton.getText())); |
| | | |
| | | // æ´æ°çªå£æ é¢ |
| | | setTitle(getTranslationValue(langCode, "window_title", getTitle())); |
| | |
| | | } |
| | | |
| | | public static void launchMainApp() { |
| | | System.out.println("å夿å¼ä¸»åºç¨ç¨åº..."); |
| | | |
| | | SwingUtilities.invokeLater(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | |
| | | mainFrame.setLocationRelativeTo(null); |
| | | mainFrame.setVisible(true); |
| | | |
| | | System.out.println("主åºç¨ç¨åºå·²å¯å¨"); |
| | | |
| | | // å¯å¨åè¿æ¥MQTT |
| | | new Thread(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | System.out.println("æ£å¨è¿æ¥MQTTæå¡å¨..."); |
| | | Client.lianjiemqqt(); |
| | | } |
| | | }).start(); |
| | |
| | | |
| | | UDPServer.startAsync();//å¯å¨æ°æ®æ¥æ¶çº¿ç¨ |
| | | |
| | | // æ¾ç¤ºåå§æ°æ® |
| | | System.out.println("åå§ç¨æ·å: " + UserChuShiHua.getProperty("userName")); |
| | | System.out.println("åå§å¯ç : " + UserChuShiHua.getProperty("password")); |
| | | |
| | | // å¯å¨ç»å½çé¢ï¼èªå¨ç»å½é»è¾å¨ loadUserPreferences ä¸å¤çï¼ |
| | | EventQueue.invokeLater(() -> { |
| | | try { |
| | |
| | | import ui.UIConfig; |
| | | import login.EmailCodeSender; |
| | | import login.UserRegister; |
| | | import publicway.buttonset; |
| | | import javax.swing.*; |
| | | import java.awt.*; |
| | | import java.awt.event.*; |
| | |
| | | )); |
| | | verificationCodeField.setAlignmentX(Component.LEFT_ALIGNMENT); |
| | | |
| | | // åééªè¯ç æé® - åç¬ä¸è¡ |
| | | sendCodeButton = new JButton("åééªè¯ç "); |
| | | sendCodeButton.setBackground(THEME_COLOR); |
| | | sendCodeButton.setForeground(Color.WHITE); |
| | | // åééªè¯ç æé® - 使ç¨buttonsetå建 |
| | | sendCodeButton = buttonset.createStyledButton("åééªè¯ç ", THEME_COLOR); |
| | | sendCodeButton.setFont(new Font("PingFang SC", Font.BOLD, 14)); |
| | | sendCodeButton.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35)); |
| | | sendCodeButton.setBorderPainted(false); |
| | | sendCodeButton.setFocusPainted(false); |
| | | sendCodeButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); |
| | | sendCodeButton.setAlignmentX(Component.LEFT_ALIGNMENT); |
| | | |
| | | // éªè¯ç æé®æ¬åææ |
| | | sendCodeButton.addMouseListener(new MouseAdapter() { |
| | | public void mouseEntered(MouseEvent e) { |
| | | if (sendCodeButton.isEnabled()) { |
| | | sendCodeButton.setBackground(THEME_HOVER_COLOR); |
| | | } |
| | | } |
| | | public void mouseExited(MouseEvent e) { |
| | | if (sendCodeButton.isEnabled()) { |
| | | sendCodeButton.setBackground(THEME_COLOR); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | // å¯ç - æ ç¾å·¦å¯¹é½ |
| | | passLabel = new JLabel("å¯ç "); |
| | | passLabel.setFont(new Font("PingFang SC", Font.BOLD, 13)); |
| | |
| | | passwordHintLabel.setForeground(Color.RED); |
| | | passwordHintLabel.setAlignmentX(Component.LEFT_ALIGNMENT); |
| | | |
| | | // 注åæé® - åç¬ä¸è¡ï¼é¿åº¦ä¸ææ¬æ¡ç¸å |
| | | registerButton = new JButton("注å"); |
| | | registerButton.setBackground(THEME_COLOR); |
| | | registerButton.setForeground(Color.WHITE); |
| | | // 注åæé® - 使ç¨buttonsetå建ï¼é¿åº¦ä¸ææ¬æ¡ç¸å |
| | | registerButton = buttonset.createStyledButton("注å", THEME_COLOR); |
| | | registerButton.setFont(new Font("PingFang SC", Font.BOLD, 14)); |
| | | registerButton.setMaximumSize(new Dimension(Integer.MAX_VALUE, 40)); |
| | | registerButton.setBorderPainted(false); |
| | | registerButton.setFocusPainted(false); |
| | | registerButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); |
| | | registerButton.setAlignmentX(Component.LEFT_ALIGNMENT); |
| | | |
| | | // 注åæé®æ¬åææ |
| | | registerButton.addMouseListener(new MouseAdapter() { |
| | | public void mouseEntered(MouseEvent e) { |
| | | registerButton.setBackground(THEME_HOVER_COLOR); |
| | | } |
| | | public void mouseExited(MouseEvent e) { |
| | | registerButton.setBackground(THEME_COLOR); |
| | | } |
| | | }); |
| | | |
| | | // åæ¶æé® - åç¬ä¸è¡ï¼é¿åº¦ä¸ææ¬æ¡ç¸å |
| | | cancelButton = new JButton("åæ¶"); |
| | | cancelButton.setBackground(Color.LIGHT_GRAY); |
| | | cancelButton.setForeground(Color.DARK_GRAY); |
| | | // åæ¶æé® - 使ç¨buttonsetå建ï¼é¿åº¦ä¸ææ¬æ¡ç¸å |
| | | cancelButton = buttonset.createStyledButton("åæ¶", Color.LIGHT_GRAY); |
| | | cancelButton.setFont(new Font("PingFang SC", Font.BOLD, 14)); |
| | | cancelButton.setMaximumSize(new Dimension(Integer.MAX_VALUE, 40)); |
| | | cancelButton.setBorderPainted(false); |
| | | cancelButton.setFocusPainted(false); |
| | | cancelButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); |
| | | cancelButton.setAlignmentX(Component.LEFT_ALIGNMENT); |
| | | |
| | | // ç»è£
表å - 缩å°è¡é´è· |
| | |
| | | userProperties = new Properties(); |
| | | try (InputStream input = new FileInputStream(FILE_PATH)) { |
| | | userProperties.load(input); |
| | | System.out.println("ç¨æ·æ°æ®åå§åæåï¼"); |
| | | } catch (IOException e) { |
| | | System.err.println("åå§åå¤±è´¥ï¼æä»¶æªæ¾å°æè¯»åé误: " + e.getMessage()); |
| | | } |
| | |
| | | |
| | | // ç¡®ä¿è¡é´è·ä¸ºæ£æ° |
| | | if (rowSpacing <= 0) { |
| | | System.out.println("è¦åï¼å²è宽度è¿å°ï¼æ æ³ä¿è¯å
¨è¦ç"); |
| | | rowSpacing = cuttingWidth; // è¿ååå§å¼ |
| | | } |
| | | |
| | |
| | | public class LoginTestRunner { |
| | | |
| | | public static void main(String[] args) { |
| | | System.out.println("========== ç»å½åè½æµè¯å¼å§ ==========\n"); |
| | | |
| | | // æµè¯é®ç®±éªè¯ç åé |
| | | //testSendEmailCode(); |
| | | |
| | |
| | | * æµè¯åéé®ç®±éªè¯ç |
| | | */ |
| | | private static void testSendEmailCode() { |
| | | System.out.println("ãæµè¯1ãåéé®ç®±éªè¯ç "); |
| | | System.out.println("----------------------------------------"); |
| | | |
| | | // æµè¯æ£å¸¸é®ç®± |
| | | String testEmail = "979909237@qq.com"; |
| | | System.out.println("æµè¯é®ç®±: " + testEmail); |
| | | |
| | | EmailCodeSender.EmailCodeResponse response = EmailCodeSender.sendEmailCode(testEmail); |
| | | |
| | | System.out.println("请æ±ç»æ:"); |
| | | System.out.println(" â æå: " + response.isSuccess()); |
| | | System.out.println(" â ç¶æç : " + response.getStatusCode()); |
| | | System.out.println(" â æ¶æ¯: " + response.getMessage()); |
| | | if (response.getResponseBody() != null && !response.getResponseBody().isEmpty()) { |
| | | System.out.println(" â ååºä½: " + response.getResponseBody()); |
| | | } |
| | | System.out.println(); |
| | | } |
| | | |
| | | /** |
| | | * æµè¯ç»å½éªè¯ |
| | | */ |
| | | private static void testVerifyLogin() { |
| | | System.out.println("ãæµè¯2ãç»å½éªè¯"); |
| | | System.out.println("----------------------------------------"); |
| | | |
| | | String email = "979909237@qq.com"; |
| | | String password = "password123"; |
| | | |
| | | System.out.println("æµè¯åæ°:"); |
| | | System.out.println(" - é®ç®±: " + email); |
| | | System.out.println(" - å¯ç : " + password); |
| | | |
| | | LoginVerifier.LoginVerifyResponse response = LoginVerifier.verifyLogin(email, password); |
| | | |
| | | System.out.println("éªè¯ç»æ:"); |
| | | System.out.println(" â æå: " + response.isSuccess()); |
| | | System.out.println(" â ç¶æç : " + response.getStatusCode()); |
| | | System.out.println(" â æ¶æ¯: " + response.getMessage()); |
| | | if (response.getResponseBody() != null && !response.getResponseBody().isEmpty()) { |
| | | System.out.println(" â ååºä½: " + response.getResponseBody()); |
| | | } |
| | | System.out.println(); |
| | | } |
| | | |
| | | /** |
| | | * æµè¯ç¨æ·æ³¨å |
| | | */ |
| | | private static void testUserRegister() { |
| | | System.out.println("ãæµè¯3ãç¨æ·æ³¨å"); |
| | | System.out.println("----------------------------------------"); |
| | | |
| | | String email = "979909237@qq.com"; |
| | | String password = "password123"; |
| | | String code = "709212"; |
| | | String nickname = "zshTest"; |
| | | |
| | | System.out.println("æµè¯åæ°:"); |
| | | System.out.println(" - é®ç®±: " + email); |
| | | System.out.println(" - å¯ç : " + password); |
| | | System.out.println(" - éªè¯ç : " + code); |
| | | System.out.println(" - æµç§°: " + nickname); |
| | | |
| | | UserRegister.RegisterResponse response = UserRegister.register(email, password, code, nickname,password); |
| | | |
| | | System.out.println("注åç»æ:"); |
| | | System.out.println(" â æå: " + response.isSuccess()); |
| | | System.out.println(" â ç¶æç : " + response.getStatusCode()); |
| | | System.out.println(" â æ¶æ¯: " + response.getMessage()); |
| | | if (response.getResponseBody() != null && !response.getResponseBody().isEmpty()) { |
| | | System.out.println(" â ååºä½: " + response.getResponseBody()); |
| | | } |
| | | System.out.println(); |
| | | } |
| | | |
| | | |
| | |
| | | List<PathSegment> zigZag = generateFixedZigZag(workArea, obstacles, bestAngle, width, currentPos); |
| | | finalPath.addAll(zigZag); |
| | | |
| | | // æ ¼å¼ååæ ï¼ä¿ç两ä½å°æ° |
| | | for (PathSegment segment : finalPath) { |
| | | segment.start.x = Math.round(segment.start.x * 100.0) / 100.0; |
| | | segment.start.y = Math.round(segment.start.y * 100.0) / 100.0; |
| | | segment.end.x = Math.round(segment.end.x * 100.0) / 100.0; |
| | | segment.end.y = Math.round(segment.end.y * 100.0) / 100.0; |
| | | } |
| | | |
| | | return finalPath; |
| | | } |
| | | |
| | |
| | | |
| | | finalPath.addAll(zigZagLines); |
| | | |
| | | // æ ¼å¼ååæ ï¼ä¿ç两ä½å°æ° |
| | | for (PathSegment segment : finalPath) { |
| | | segment.start.x = Math.round(segment.start.x * 100.0) / 100.0; |
| | | segment.start.y = Math.round(segment.start.y * 100.0) / 100.0; |
| | | segment.end.x = Math.round(segment.end.x * 100.0) / 100.0; |
| | | segment.end.y = Math.round(segment.end.y * 100.0) / 100.0; |
| | | } |
| | | |
| | | return finalPath; |
| | | } |
| | | |
| | |
| | | if (sb.length() > 0) { |
| | | sb.append(";"); |
| | | } |
| | | sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y)); |
| | | sb.append(String.format(Locale.US, "%.2f,%.2f", point.x, point.y)); |
| | | } |
| | | |
| | | /** |
| | |
| | | if (sb.length() > 0) { |
| | | sb.append(";"); |
| | | } |
| | | sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y)); |
| | | sb.append(String.format(Locale.US, "%.2f,%.2f", point.x, point.y)); |
| | | } |
| | | |
| | | /** |
| | |
| | | if (sb.length() > 0) { |
| | | sb.append(";"); |
| | | } |
| | | sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y)); |
| | | sb.append(String.format(Locale.US, "%.2f,%.2f", point.x, point.y)); |
| | | } |
| | | |
| | | /** |
| | |
| | | if (sb.length() > 0) { |
| | | sb.append(";"); |
| | | } |
| | | sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y)); |
| | | sb.append(String.format(Locale.US, "%.2f,%.2f", point.x, point.y)); |
| | | } |
| | | |
| | | // ========== UIè¾
婿¹æ³ ========== |
| | |
| | | |
| | | finalPath.addAll(scanPath); |
| | | |
| | | // 10. æ ¼å¼ååæ ï¼ä¿ç两ä½å°æ° |
| | | for (PathSegment segment : finalPath) { |
| | | segment.start.x = Math.round(segment.start.x * 100.0) / 100.0; |
| | | segment.start.y = Math.round(segment.start.y * 100.0) / 100.0; |
| | | segment.end.x = Math.round(segment.end.x * 100.0) / 100.0; |
| | | segment.end.y = Math.round(segment.end.y * 100.0) / 100.0; |
| | | } |
| | | |
| | | // 11. æå°è¾åºè·¯å¾åæ |
| | | printPathCoordinates(finalPath); |
| | | |
| | | return finalPath; |
| | | } |
| | | |
| | |
| | | return points; |
| | | } |
| | | |
| | | /** |
| | | * æå°è¾åºè·¯å¾åæ å°æ§å¶å° |
| | | */ |
| | | private static void printPathCoordinates(List<PathSegment> path) { |
| | | if (path == null || path.isEmpty()) { |
| | | System.out.println("è·¯å¾ä¸ºç©º"); |
| | | return; |
| | | } |
| | | |
| | | System.out.println("========== è·¯å¾åæ è¾åº =========="); |
| | | System.out.println("æ»è·¯å¾æ®µæ°: " + path.size()); |
| | | System.out.println(); |
| | | System.out.println("è·¯å¾åæ åºå (æ ¼å¼: x,y;x,y;...):"); |
| | | |
| | | StringBuilder sb = new StringBuilder(); |
| | | for (int i = 0; i < path.size(); i++) { |
| | | PathSegment segment = path.get(i); |
| | | if (i == 0) { |
| | | // 第ä¸ä¸ªæ®µçèµ·ç¹ |
| | | sb.append(String.format("%.2f,%.2f", segment.start.x, segment.start.y)); |
| | | } |
| | | // æ¯ä¸ªæ®µçç»ç¹ |
| | | sb.append(";"); |
| | | sb.append(String.format("%.2f,%.2f", segment.end.x, segment.end.y)); |
| | | } |
| | | |
| | | System.out.println(sb.toString()); |
| | | System.out.println(); |
| | | System.out.println("详ç»è·¯å¾ä¿¡æ¯:"); |
| | | for (int i = 0; i < path.size(); i++) { |
| | | PathSegment segment = path.get(i); |
| | | String type = segment.isMowing ? "å²è" : "空走"; |
| | | System.out.println(String.format("段 %d [%s]: (%.2f,%.2f) -> (%.2f,%.2f)", |
| | | i + 1, type, segment.start.x, segment.start.y, segment.end.x, segment.end.y)); |
| | | } |
| | | System.out.println("=================================="); |
| | | } |
| | | |
| | | public static class Point { |
| | | public double x, y; |
| | | public Point(double x, double y) { this.x = x; this.y = y; } |
| | |
| | | package lujing; |
| | | |
| | | import java.util.*; |
| | | import java.util.Set; |
| | | import java.util.HashSet; |
| | | |
| | | /** |
| | | * å¼å½¢èå°è·¯å¾è§å - å¹å¤è¾¹å½¢å
¼å®¹ä¼åç V5.0 |
| | |
| | | |
| | | finalPath.addAll(scanPath); |
| | | |
| | | // 8. æ ¼å¼ååæ ï¼ä¿ç两ä½å°æ° |
| | | for (PathSegment segment : finalPath) { |
| | | segment.start.x = Math.round(segment.start.x * 100.0) / 100.0; |
| | | segment.start.y = Math.round(segment.start.y * 100.0) / 100.0; |
| | | segment.end.x = Math.round(segment.end.x * 100.0) / 100.0; |
| | | segment.end.y = Math.round(segment.end.y * 100.0) / 100.0; |
| | | } |
| | | |
| | | return finalPath; |
| | | } |
| | | |
| | |
| | | for (PathSegment s : lineSegmentsInRow) { |
| | | if (Math.hypot(currentPos.x - s.start.x, currentPos.y - s.start.y) > 0.01) { |
| | | // 妿é´è·å¤§äº1cmï¼æ·»å ç©ºèµ°è·¯å¾ |
| | | segments.add(new PathSegment(currentPos, s.start, false)); |
| | | addSafeConnection(segments, currentPos, s.start, polygon); |
| | | } |
| | | segments.add(s); |
| | | currentPos = s.end; |
| | |
| | | |
| | | private static List<Double> getXIntersections(List<Point> rotatedPoly, double y) { |
| | | List<Double> xIntersections = new ArrayList<>(); |
| | | double tolerance = 1e-6; |
| | | |
| | | for (int i = 0; i < rotatedPoly.size(); i++) { |
| | | Point p1 = rotatedPoly.get(i); |
| | | Point p2 = rotatedPoly.get((i + 1) % rotatedPoly.size()); |
| | | if ((p1.y <= y && p2.y > y) || (p2.y <= y && p1.y > y)) { |
| | | |
| | | // è·³è¿æ°´å¹³è¾¹ï¼é¿å
䏿«æçº¿éåæ¶çç¹æ®æ
åµï¼ |
| | | if (Math.abs(p1.y - p2.y) < tolerance) { |
| | | continue; |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦ç¸äº¤ï¼ä½¿ç¨ä¸¥æ ¼ä¸çå¼é¿å
é¡¶ç¹éå¤ï¼ |
| | | if ((p1.y < y && p2.y >= y) || (p2.y < y && p1.y >= y)) { |
| | | double x = p1.x + (y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y); |
| | | // ç®åå»éï¼æ£æ¥æ¯å¦å·²åå¨ç¸è¿çç¹ |
| | | boolean isDuplicate = false; |
| | | for (double existingX : xIntersections) { |
| | | if (Math.abs(x - existingX) < tolerance) { |
| | | isDuplicate = true; |
| | | break; |
| | | } |
| | | } |
| | | if (!isDuplicate) { |
| | | xIntersections.add(x); |
| | | } |
| | | } |
| | | } |
| | | return xIntersections; |
| | | } |
| | | |
| | |
| | | return maxY - minY; |
| | | } |
| | | |
| | | private static List<Point> getInsetPolygon(List<Point> points, double margin) { |
| | | public static List<Point> getInsetPolygon(List<Point> points, double margin) { |
| | | List<Point> result = new ArrayList<>(); |
| | | int n = points.size(); |
| | | for (int i = 0; i < n; i++) { |
| | |
| | | return result; |
| | | } |
| | | |
| | | private static void addSafeConnection(List<PathSegment> segments, Point start, Point end, List<Point> polygon) { |
| | | if (isSegmentSafe(start, end, polygon)) { |
| | | segments.add(new PathSegment(start, end, false)); |
| | | } else { |
| | | List<Point> path = getBoundaryPath(start, end, polygon); |
| | | for (int i = 0; i < path.size() - 1; i++) { |
| | | segments.add(new PathSegment(path.get(i), path.get(i+1), false)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private static boolean isSegmentSafe(Point p1, Point p2, List<Point> polygon) { |
| | | Point mid = new Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2); |
| | | if (!isPointInPolygon(mid, polygon)) return false; |
| | | |
| | | for (int i = 0; i < polygon.size(); i++) { |
| | | Point a = polygon.get(i); |
| | | Point b = polygon.get((i + 1) % polygon.size()); |
| | | if (isSamePoint(p1, a) || isSamePoint(p1, b) || isSamePoint(p2, a) || isSamePoint(p2, b)) continue; |
| | | if (segmentsIntersect(p1, p2, a, b)) return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | private static boolean isSamePoint(Point a, Point b) { |
| | | return Math.abs(a.x - b.x) < 1e-4 && Math.abs(a.y - b.y) < 1e-4; |
| | | } |
| | | |
| | | private static boolean segmentsIntersect(Point a, Point b, Point c, Point d) { |
| | | return ccw(a, c, d) != ccw(b, c, d) && ccw(a, b, c) != ccw(a, b, d); |
| | | } |
| | | |
| | | private static boolean ccw(Point a, Point b, Point c) { |
| | | return (c.y - a.y) * (b.x - a.x) > (b.y - a.y) * (c.x - a.x); |
| | | } |
| | | |
| | | private static boolean isPointInPolygon(Point p, List<Point> polygon) { |
| | | boolean result = false; |
| | | for (int i = 0, j = polygon.size() - 1; i < polygon.size(); j = i++) { |
| | | if ((polygon.get(i).y > p.y) != (polygon.get(j).y > p.y) && |
| | | (p.x < (polygon.get(j).x - polygon.get(i).x) * (p.y - polygon.get(i).y) / (polygon.get(j).y - polygon.get(i).y) + polygon.get(i).x)) { |
| | | result = !result; |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | private static List<Point> getBoundaryPath(Point start, Point end, List<Point> polygon) { |
| | | int idx1 = getEdgeIndex(start, polygon); |
| | | int idx2 = getEdgeIndex(end, polygon); |
| | | |
| | | if (idx1 == -1 || idx2 == -1 || idx1 == idx2) { |
| | | return Arrays.asList(start, end); |
| | | } |
| | | |
| | | List<Point> path1 = new ArrayList<>(); |
| | | path1.add(start); |
| | | int curr = idx1; |
| | | while (curr != idx2) { |
| | | path1.add(polygon.get((curr + 1) % polygon.size())); |
| | | curr = (curr + 1) % polygon.size(); |
| | | } |
| | | path1.add(end); |
| | | |
| | | List<Point> pathRev = new ArrayList<>(); |
| | | pathRev.add(start); |
| | | curr = idx1; |
| | | while (curr != idx2) { |
| | | pathRev.add(polygon.get(curr)); |
| | | curr = (curr - 1 + polygon.size()) % polygon.size(); |
| | | } |
| | | pathRev.add(polygon.get((idx2 + 1) % polygon.size())); |
| | | pathRev.add(end); |
| | | |
| | | return getPathLength(path1) < getPathLength(pathRev) ? path1 : pathRev; |
| | | } |
| | | |
| | | private static double getPathLength(List<Point> path) { |
| | | double len = 0; |
| | | for (int i = 0; i < path.size() - 1; i++) { |
| | | len += Math.hypot(path.get(i).x - path.get(i+1).x, path.get(i).y - path.get(i+1).y); |
| | | } |
| | | return len; |
| | | } |
| | | |
| | | private static int getEdgeIndex(Point p, List<Point> poly) { |
| | | for (int i = 0; i < poly.size(); i++) { |
| | | Point p1 = poly.get(i); |
| | | Point p2 = poly.get((i + 1) % poly.size()); |
| | | if (distToSegment(p, p1, p2) < 1e-3) return i; |
| | | } |
| | | return -1; |
| | | } |
| | | |
| | | private static double distToSegment(Point p, Point s, Point e) { |
| | | double l2 = (s.x - e.x)*(s.x - e.x) + (s.y - e.y)*(s.y - e.y); |
| | | if (l2 == 0) return Math.hypot(p.x - s.x, p.y - s.y); |
| | | double t = ((p.x - s.x) * (e.x - s.x) + (p.y - s.y) * (e.y - s.y)) / l2; |
| | | t = Math.max(0, Math.min(1, t)); |
| | | return Math.hypot(p.x - (s.x + t * (e.x - s.x)), p.y - (s.y + t * (e.y - s.y))); |
| | | } |
| | | |
| | | private static Point rotatePoint(Point p, double angle) { |
| | | double cos = Math.cos(angle), sin = Math.sin(angle); |
| | | return new Point(p.x * cos - p.y * sin, p.x * sin + p.y * cos); |
| | | } |
| | | |
| | | private static void ensureCounterClockwise(List<Point> points) { |
| | | public static void ensureCounterClockwise(List<Point> points) { |
| | | double sum = 0; |
| | | for (int i = 0; i < points.size(); i++) { |
| | | Point p1 = points.get(i), p2 = points.get((i + 1) % points.size()); |
| | |
| | | |
| | | // è°ç¨Server.propertiesFileToJsonæ¹æ³çæJSONå符串 |
| | | String jsonData = propertiesFileToJson(filePath); |
| | | System.out.println("å·²æåå°Propertiesæä»¶è½¬æ¢ä¸ºJSON: " + filePath); |
| | | |
| | | // æå»ºå®æ´çURLï¼å
å«filenameåæ°ï¼è¿è¡URLç¼ç ï¼ |
| | | String encodedFilename = URLEncoder.encode(filename, StandardCharsets.UTF_8.name()); |
| | |
| | | ObjectMapper objectMapper = new ObjectMapper(); |
| | | FileUploadResponse response = objectMapper.readValue(responseJson, FileUploadResponse.class); |
| | | |
| | | System.out.println("æä»¶ä¸ä¼ æå: " + response.getSavedFilename()); |
| | | return response; |
| | | |
| | | } finally { |
| | |
| | | MqttMessage message = new MqttMessage(); |
| | | message.setPayload(messageJson.getBytes("UTF-8")); |
| | | client.publish(topic, message); |
| | | System.out.println("åéæ°æ®å°ä¸»é¢: " + topic); |
| | | } catch (MqttException e) { |
| | | throw new RuntimeException(e); |
| | | } catch (UnsupportedEncodingException e) { |
| | |
| | | * æ¾ç¤ºå½åææå±æ§å¼ |
| | | */ |
| | | public void displayProperties() { |
| | | System.out.println("å½å屿§å¼:"); |
| | | System.out.println("mowerId: " + (mowerId != null ? mowerId : "æªè®¾ç½®")); |
| | | System.out.println("cuttingWidth: " + (cuttingWidth != null ? cuttingWidth : "æªè®¾ç½®")); |
| | | System.out.println("simCardNumber: " + (simCardNumber != null ? simCardNumber : "æªè®¾ç½®")); |
| | | System.out.println("handheldMarkerId: " + (handheldMarkerId != null ? handheldMarkerId : "æªè®¾ç½®")); |
| | | System.out.println("firmwareVersion: " + (firmwareVersion != null ? firmwareVersion : "æªè®¾ç½®")); |
| | | System.out.println("appVersion: " + (appVersion != null ? appVersion : "æªè®¾ç½®")); |
| | | System.out.println("idleTrailDurationSeconds: " + idleTrailDurationSeconds); |
| | | // æ¾ç¤ºå±æ§åè½å·²ç¦ç¨ |
| | | } |
| | | |
| | | /** |
| | |
| | | ResponseData responseData = null; |
| | | try { |
| | | responseData = DeviceMessageParser.parseResponseData(responseJson); |
| | | System.out.println("åå§æ¶æ¯ID: " + responseData.getOriginalMsgId()); |
| | | } catch (JsonProcessingException e) { |
| | | e.printStackTrace(); |
| | | } catch (IllegalArgumentException e) { |
| | |
| | | " }\n" + |
| | | "}"; |
| | | try { |
| | | System.out.println("=== GPSæ°æ®è§£æç¤ºä¾ï¼æ°åè®®æ ¼å¼ï¼ ==="); |
| | | GPSData gpsData2 = DeviceMessageParser.parseGPSData(gpsJsonStr); |
| | | String string2 = gpsData2.toString(); |
| | | System.out.println(string2); |
| | | |
| | | } catch (JsonProcessingException e) { |
| | | e.printStackTrace(); |
| | |
| | | 0.5, // é度0.5ç±³/ç§ |
| | | 10 // æç»10ç§ |
| | | ); |
| | | System.out.println(json2); |
| | | } |
| | | |
| | | |
| | |
| | | ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE); |
| | | |
| | | try (DatagramSocket socket = new DatagramSocket(PORT)) { |
| | | System.out.println("UDPServer started on port " + PORT); |
| | | |
| | | while (!Thread.currentThread().isInterrupted()) { |
| | | byte[] buffer = new byte[BUFFER_SIZE]; |
| | | DatagramPacket packet = new DatagramPacket(buffer, buffer.length); |
| | |
| | | return; |
| | | } |
| | | int sequence = incrementReceivedPacketCounter(); |
| | | System.out.println("æ¶å°äºå·®åæ°æ®(" + sequence + ")ï¼" + message); |
| | | |
| | | // 使ç¨Gpstoxuzuobiaoå¤çå¹¶è·åXYåæ |
| | | double[] xy = Gpstoxuzuobiao.processGNGGAToXY(message); |
| | |
| | | |
| | | Coordinate.parseGNGGAToCoordinateList(message); |
| | | int count = Coordinate.coordinates.size(); |
| | | System.out.println("savenum:" + count); |
| | | |
| | | Device.updateFromGNGGA(message, fields[15]); |
| | | } |
| | |
| | | return; |
| | | } |
| | | int sequence = incrementReceivedPacketCounter(); |
| | | System.out.println("æ¶å°äºä¸²å£æ°æ®(" + sequence + ")ï¼" + message); |
| | | |
| | | // 使ç¨Gpstoxuzuobiaoå¤çå¹¶è·åXYåæ |
| | | double[] xy = Gpstoxuzuobiao.processGNGGAToXY(message); |
| | |
| | | |
| | | Coordinate.dellchuankougngga(message); |
| | | int count = Coordinate.coordinates.size(); |
| | | System.out.println("savenum:" + count); |
| | | |
| | | Device.updateFromSerialGNGGA(message); |
| | | } |
| | |
| | | userProperties = new Properties(); |
| | | try (FileInputStream input = new FileInputStream(PROPERTIES_FILE)) { |
| | | userProperties.load(input); |
| | | System.out.println("ç¨æ·å±æ§åå§åæåï¼"); |
| | | } catch (IOException e) { |
| | | System.err.println("åå§åå¤±è´¥ï¼æä»¶æªæ¾å°æè¯»åé误: " + e.getMessage()); |
| | | // 妿æä»¶ä¸åå¨ï¼å建é»è®¤å±æ§ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package utils; |
| | | |
| | | /** |
| | | * å·¥å
·ç±»ï¼æ£æ¥double弿¯å¦æéï¼å
¼å®¹ä½çæ¬Javaï¼ |
| | | * ç¨äºæ¿ä»£ Double.isFinite() æ¹æ³ |
| | | */ |
| | | public final class FiniteChecker { |
| | | private FiniteChecker() { |
| | | // å·¥å
·ç±»ï¼ä¸å
许å®ä¾å |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥double弿¯å¦æéï¼ä¸æ¯NaNææ ç©·å¤§ï¼ |
| | | * @param value è¦æ£æ¥çdoubleå¼ |
| | | * @return true妿弿¯æéçï¼false妿æ¯NaNææ ç©·å¤§ |
| | | */ |
| | | public static boolean isFinite(double value) { |
| | | return !Double.isNaN(value) && !Double.isInfinite(value); |
| | | } |
| | | } |
| | |
| | | nextForward = clampSpeed(nextForward); |
| | | byte[] payload = buildSteeringCommandBytes((byte) nextSteering, (byte) nextForward); |
| | | |
| | | // è°è¯ï¼æå°åéçæ°æ® |
| | | System.out.println("åé转åæä»¤: " + bytesToHex(payload)); |
| | | |
| | | boolean success = sendmessage.sendViaActive(payload); |
| | | if (success) { |
| | | currentSteeringSpeed = nextSteering; |
| | |
| | | * æµè¯å½æ°ï¼éªè¯è½¬åæä»¤æå»º |
| | | */ |
| | | public static void testBuildSteeringCommand() { |
| | | System.out.println("=== æµè¯ä¿®æ£åç转åæä»¤æå»º ==="); |
| | | |
| | | // æµè¯1ï¼ç´è¡åè¿ |
| | | byte[] cmd1 = buildSteeringCommandBytes((byte)0, (byte)50); |
| | | System.out.println("ç´è¡åè¿50: " + bytesToHex(cmd1)); |
| | | |
| | | // æµè¯2ï¼å·¦è½¬åè¿ |
| | | byte[] cmd2 = buildSteeringCommandBytes((byte)-30, (byte)40); |
| | | System.out.println("左转åè¿: " + bytesToHex(cmd2)); |
| | | |
| | | // æµè¯3ï¼å³è½¬åé |
| | | byte[] cmd3 = buildSteeringCommandBytes((byte)20, (byte)-60); |
| | | System.out.println("å³è½¬åé: " + bytesToHex(cmd3)); |
| | | |
| | | // æµè¯4ï¼åæ¢ |
| | | byte[] cmd4 = buildSteeringCommandBytes((byte)0, (byte)0); |
| | | System.out.println("忢: " + bytesToHex(cmd4)); |
| | | } |
| | | |
| | | } |
| | |
| | | } |
| | | byte[] payload = buildPowerCommandBytes(powerValue); |
| | | |
| | | // è°è¯ï¼æå°åéçæ°æ® |
| | | System.out.println("åéçµæºæ§å¶æä»¤: " + bytesToHex(payload)); |
| | | |
| | | return sendmessage.sendViaActive(payload); |
| | | } |
| | | |
| | |
| | | * æµè¯å½æ°ï¼éªè¯çµæºæ§å¶æä»¤æå»º |
| | | */ |
| | | public static void testBuildPowerCommand() { |
| | | System.out.println("=== æµè¯çµæºæ§å¶æä»¤æå»º ==="); |
| | | |
| | | // æµè¯1ï¼å¯å¨æä»¤ |
| | | byte[] cmd1 = buildPowerCommandBytes((byte)1); |
| | | System.out.println("å¯å¨æºå¨: " + bytesToHex(cmd1)); |
| | | |
| | | // æµè¯2ï¼å
³éæä»¤ |
| | | byte[] cmd2 = buildPowerCommandBytes((byte)0); |
| | | System.out.println("å
³éæºå¨: " + bytesToHex(cmd2)); |
| | | } |
| | | } |
| | |
| | | } |
| | | byte[] payload = buildBladeCommandBytes((byte) targetHeight); |
| | | |
| | | // è°è¯ï¼æå°åéçæ°æ® |
| | | System.out.println("åéåçåéæä»¤: " + bytesToHex(payload)); |
| | | |
| | | boolean success = sendmessage.sendViaActive(payload); |
| | | if (success) { |
| | |
| | | * æµè¯å½æ°ï¼éªè¯åçåéæä»¤æå»º |
| | | */ |
| | | public static void testBuildBladeCommand() { |
| | | System.out.println("=== æµè¯åçåéæä»¤æå»º ==="); |
| | | |
| | | // æµè¯1ï¼æåæä»¤ |
| | | byte[] cmd1 = buildBladeCommandBytes((byte)50); |
| | | System.out.println("æå50%: " + bytesToHex(cmd1)); |
| | | |
| | | // æµè¯2ï¼é使令 |
| | | byte[] cmd2 = buildBladeCommandBytes((byte)-30); |
| | | System.out.println("éä½30%: " + bytesToHex(cmd2)); |
| | | |
| | | // æµè¯3ï¼å½é¶æä»¤ |
| | | byte[] cmd3 = buildBladeCommandBytes((byte)0); |
| | | System.out.println("å½é¶: " + bytesToHex(cmd3)); |
| | | } |
| | | } |
| | |
| | | } |
| | | byte[] payload = buildLightCommandBytes(lightValue); |
| | | |
| | | // è°è¯ï¼æå°åéçæ°æ® |
| | | System.out.println("åéå¤§ç¯æ§å¶æä»¤: " + bytesToHex(payload)); |
| | | |
| | | return sendmessage.sendViaActive(payload); |
| | | } |
| | | |
| | |
| | | * æµè¯å½æ°ï¼éªè¯å¤§ç¯æ§å¶æä»¤æå»º |
| | | */ |
| | | public static void testBuildLightCommand() { |
| | | System.out.println("=== æµè¯å¤§ç¯æ§å¶æä»¤æå»º ==="); |
| | | |
| | | // æµè¯1ï¼å¼ç¯æä»¤ |
| | | byte[] cmd1 = buildLightCommandBytes((byte)1); |
| | | System.out.println("å¼å¯å¤§ç¯: " + bytesToHex(cmd1)); |
| | | |
| | | // æµè¯2ï¼å
³ç¯æä»¤ |
| | | byte[] cmd2 = buildLightCommandBytes((byte)0); |
| | | System.out.println("å
³é大ç¯: " + bytesToHex(cmd2)); |
| | | } |
| | | } |
| | |
| | | // 使ç¨ä¿®æ£åçæ¹æ³æå»ºæä»¤ |
| | | byte[] commandBytes = buildSteeringCommandBytes(steeringSpeed, forwardSpeed); |
| | | |
| | | // è°è¯ï¼æå°åéçæ°æ® |
| | | System.out.println("åéä¿®æ£åç转åæä»¤: " + bytesToHex(commandBytes)); |
| | | |
| | | // åéæ°æ® |
| | | outputStream.write(commandBytes); |
| | | outputStream.flush(); |
| | |
| | | String line; |
| | | StringBuilder gnggaData = new StringBuilder(); |
| | | |
| | | System.out.println("å¼å§è¯»åGNGGAæä»¶: " + file.getAbsolutePath()); |
| | | |
| | | while ((line = reader.readLine()) != null) { |
| | | // æ¸
çæ°æ®ï¼ç§»é¤å¤ä½çç©ºæ ¼åæ¢è¡ |
| | | line = line.trim(); |
| | |
| | | if (gnggaData.length() > 0) { |
| | | parseGNGGAToCoordinateList(gnggaData.toString()); |
| | | loadedCount = coordinates.size(); |
| | | System.out.println("æåå è½½ " + loadedCount + " ä¸ªåæ ç¹"); |
| | | |
| | | // è¾åºç»è®¡ä¿¡æ¯ |
| | | if (loadedCount > 0) { |
| | | double[] elevationRange = getElevationRange(); |
| | | double avgElevation = getAverageElevation(); |
| | | System.out.println("æµ·æç»è®¡: èå´=" + String.format("%.2f", elevationRange[0]) + |
| | | " - " + String.format("%.2f", elevationRange[1]) + "ç±³, å¹³å=" + |
| | | String.format("%.2f", avgElevation) + "ç±³"); |
| | | } |
| | | } else { |
| | | System.out.println("æä»¶ä¸æªæ¾å°ææçGNGGAæ°æ®"); |
| | | } |
| | | |
| | | } catch (IOException e) { |
| | |
| | | import java.util.List; |
| | | import java.util.Locale; |
| | | import java.util.Set; |
| | | import java.util.function.Consumer; |
| | | import java.io.File; |
| | | import set.Setsys; |
| | | import gecaoji.Device; |
| | |
| | | * æ·»å 导èªé¢è§è½¨è¿¹ç¹ |
| | | */ |
| | | public void addNavigationPreviewTrackPoint(Point2D.Double point) { |
| | | if (point != null && Double.isFinite(point.x) && Double.isFinite(point.y)) { |
| | | if (point != null && isFinite(point.x) && isFinite(point.y)) { |
| | | navigationPreviewTrack.add(new Point2D.Double(point.x, point.y)); |
| | | if (visualizationPanel != null) { |
| | | visualizationPanel.repaint(); |
| | |
| | | return; |
| | | } |
| | | Point2D.Double position = mower.getPosition(); |
| | | if (position == null || !Double.isFinite(position.x) || !Double.isFinite(position.y)) { |
| | | if (position == null || !isFinite(position.x) || !isFinite(position.y)) { |
| | | pendingTrackBreak = true; |
| | | return; |
| | | } |
| | |
| | | } |
| | | |
| | | realtimeMowingTrack.add(candidate); |
| | | if (!pendingTrackBreak && lastPoint != null && Double.isFinite(distance)) { |
| | | if (!pendingTrackBreak && lastPoint != null && isFinite(distance)) { |
| | | trackLengthMeters += distance; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | Point2D.Double position = mower.getPosition(); |
| | | if (position == null || !Double.isFinite(position.x) || !Double.isFinite(position.y)) { |
| | | if (position == null || !isFinite(position.x) || !isFinite(position.y)) { |
| | | return; |
| | | } |
| | | |
| | |
| | | // å·æ°mowerä½ç½®ï¼ä½¿ç¨ææ°çDeviceæ°æ® |
| | | mower.refreshFromDevice(); |
| | | Point2D.Double position = mower.getPosition(); |
| | | if (position == null || !Double.isFinite(position.x) || !Double.isFinite(position.y)) { |
| | | if (position == null || !isFinite(position.x) || !isFinite(position.y)) { |
| | | return; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | private String formatTrackCoordinate(double value) { |
| | | if (!Double.isFinite(value)) { |
| | | if (!isFinite(value)) { |
| | | return "0"; |
| | | } |
| | | return String.format(Locale.US, "%.3f", value); |
| | |
| | | try { |
| | | double x = Double.parseDouble(parts[0].trim()); |
| | | double y = Double.parseDouble(parts[1].trim()); |
| | | if (!Double.isFinite(x) || !Double.isFinite(y)) { |
| | | if (!isFinite(x) || !isFinite(y)) { |
| | | continue; |
| | | } |
| | | Point2D.Double current = new Point2D.Double(x, y); |
| | |
| | | String safetyDistance = null; |
| | | String obstaclesCoords = null; |
| | | String mowingPattern = null; |
| | | String plannedPathStr = null; |
| | | |
| | | // ä»å½åå°åç¼å·è·åå°åä¿¡æ¯ |
| | | if (currentBoundaryLandNumber != null) { |
| | |
| | | mowingWidth = landData.getMowingWidth(); |
| | | safetyDistance = landData.getMowingSafetyDistance(); |
| | | mowingPattern = landData.getMowingPattern(); |
| | | // ä»å°åè·åplannedPath屿§å¼ä½ä¸ºè·¯å¾ |
| | | plannedPathStr = landData.getPlannedPath(); |
| | | |
| | | // è·åéç¢ç©åæ |
| | | try { |
| | |
| | | } |
| | | } |
| | | |
| | | // 妿ä»å°åè·åå°äºè·¯å¾ï¼ä½¿ç¨å°åçè·¯å¾ï¼å¦å使ç¨currentPlannedPath |
| | | List<Point2D.Double> pathToDraw = currentPlannedPath; |
| | | if (plannedPathStr != null && !plannedPathStr.trim().isEmpty() && !"-1".equals(plannedPathStr.trim())) { |
| | | // ä»å°åè·åçè·¯å¾ |
| | | pathToDraw = lujingdraw.parsePlannedPath(plannedPathStr); |
| | | } |
| | | |
| | | // è°ç¨å¸¦å°åä¿¡æ¯çç»å¶æ¹æ³ |
| | | lujingdraw.drawPlannedPath(g2d, currentPlannedPath, scale, arrowScale, |
| | | if (pathToDraw != null && pathToDraw.size() >= 2) { |
| | | lujingdraw.drawPlannedPath(g2d, pathToDraw, scale, arrowScale, |
| | | boundaryCoords, mowingWidth, safetyDistance, obstaclesCoords, mowingPattern); |
| | | } |
| | | } |
| | | |
| | | private void drawCircleSampleMarkers(Graphics2D g2d, List<double[]> markers, double scale) { |
| | | if (markers == null || markers.isEmpty()) { |
| | |
| | | FontMetrics metrics = g2d.getFontMetrics(labelFont); |
| | | |
| | | for (double[] pt : markers) { |
| | | if (pt == null || pt.length < 2 || !Double.isFinite(pt[0]) || !Double.isFinite(pt[1])) { |
| | | if (pt == null || pt.length < 2 || !isFinite(pt[0]) || !isFinite(pt[1])) { |
| | | continue; |
| | | } |
| | | double x = pt[0]; |
| | |
| | | } |
| | | double x = pt[0]; |
| | | double y = pt[1]; |
| | | if (!Double.isFinite(x) || !Double.isFinite(y)) { |
| | | if (!isFinite(x) || !isFinite(y)) { |
| | | continue; |
| | | } |
| | | circleSampleMarkers.add(new double[]{x, y}); |
| | |
| | | private double computeSelectionThresholdPixels() { |
| | | double scaleFactor = Math.max(0.5, scale); |
| | | double diameterScale = boundaryPointSizeScale * (previewSizingEnabled ? PREVIEW_BOUNDARY_MARKER_SCALE : 1.0d); |
| | | if (!Double.isFinite(diameterScale) || diameterScale <= 0.0d) { |
| | | if (!isFinite(diameterScale) || diameterScale <= 0.0d) { |
| | | diameterScale = 1.0d; |
| | | } |
| | | double markerDiameterWorld = Math.max(1.0, (10.0 / scaleFactor) * 0.2 * diameterScale); |
| | |
| | | } |
| | | |
| | | private boolean isPointInsideActiveBoundary(Point2D.Double point) { |
| | | if (point == null || !Double.isFinite(point.x) || !Double.isFinite(point.y)) { |
| | | if (point == null || !isFinite(point.x) || !isFinite(point.y)) { |
| | | return false; |
| | | } |
| | | if (realtimeTrackLandNumber == null) { |
| | |
| | | } |
| | | |
| | | private boolean isPointInsideBoundary(Point2D.Double point, Path2D.Double path) { |
| | | if (point == null || path == null || !Double.isFinite(point.x) || !Double.isFinite(point.y)) { |
| | | if (point == null || path == null || !isFinite(point.x) || !isFinite(point.y)) { |
| | | return false; |
| | | } |
| | | if (path.contains(point.x, point.y)) { |
| | |
| | | Path2D.Double path = new Path2D.Double(); |
| | | boolean started = false; |
| | | for (Point2D.Double point : boundary) { |
| | | if (point == null || !Double.isFinite(point.x) || !Double.isFinite(point.y)) { |
| | | if (point == null || !isFinite(point.x) || !isFinite(point.y)) { |
| | | continue; |
| | | } |
| | | if (!started) { |
| | |
| | | // 设置ç¹ç大å°ï¼é缩æ¾ååï¼ |
| | | double scaleFactor = Math.max(0.5, scale); |
| | | double clampedScale = boundaryPointSizeScale * (previewSizingEnabled ? PREVIEW_BOUNDARY_MARKER_SCALE : 1.0d); |
| | | if (!Double.isFinite(clampedScale) || clampedScale <= 0.0d) { |
| | | if (!isFinite(clampedScale) || clampedScale <= 0.0d) { |
| | | clampedScale = 1.0d; |
| | | } |
| | | double minimumDiameter = clampedScale < 1.0 ? 0.5 : 1.0; |
| | |
| | | } |
| | | double x = coord.getX(); |
| | | double y = coord.getY(); |
| | | if (!Double.isFinite(x) || !Double.isFinite(y)) { |
| | | if (!isFinite(x) || !isFinite(y)) { |
| | | continue; |
| | | } |
| | | copy.add(new Obstacledge.XYCoordinate(x, y)); |
| | |
| | | } |
| | | |
| | | public void setBoundaryPointSizeScale(double sizeScale) { |
| | | double normalized = (Double.isFinite(sizeScale) && sizeScale > 0.0d) ? sizeScale : 1.0d; |
| | | double normalized = (isFinite(sizeScale) && sizeScale > 0.0d) ? sizeScale : 1.0d; |
| | | if (Math.abs(boundaryPointSizeScale - normalized) < 1e-6) { |
| | | return; |
| | | } |
| | |
| | | } |
| | | |
| | | public void setBoundaryPreviewMarkerScale(double markerScale) { |
| | | double normalized = Double.isFinite(markerScale) && markerScale > 0.0d ? markerScale : 1.0d; |
| | | double normalized = isFinite(markerScale) && markerScale > 0.0d ? markerScale : 1.0d; |
| | | if (Math.abs(boundaryPreviewMarkerScale - normalized) < 1e-6) { |
| | | return; |
| | | } |
| | |
| | | } |
| | | |
| | | public void addHandheldBoundaryPoint(double x, double y) { |
| | | if (!Double.isFinite(x) || !Double.isFinite(y)) { |
| | | if (!isFinite(x) || !isFinite(y)) { |
| | | return; |
| | | } |
| | | if (!handheldBoundaryPreviewActive) { |
| | |
| | | |
| | | Point2D.Double mowerPosition = mower.getPosition(); |
| | | if (mowerPosition == null |
| | | || !Double.isFinite(mowerPosition.x) |
| | | || !Double.isFinite(mowerPosition.y)) { |
| | | || !isFinite(mowerPosition.x) |
| | | || !isFinite(mowerPosition.y)) { |
| | | return expanded; |
| | | } |
| | | |
| | |
| | | /** |
| | | * 设置边çé¢è§æ´æ°åè° |
| | | */ |
| | | private java.util.function.Consumer<String> boundaryPreviewUpdateCallback; |
| | | private Consumer<String> boundaryPreviewUpdateCallback; |
| | | |
| | | public void setBoundaryPreviewUpdateCallback(java.util.function.Consumer<String> callback) { |
| | | public void setBoundaryPreviewUpdateCallback(Consumer<String> callback) { |
| | | this.boundaryPreviewUpdateCallback = callback; |
| | | } |
| | | |
| | |
| | | fitBoundsToView(bounds); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥double弿¯å¦æéï¼ä¸æ¯NaNææ ç©·å¤§ï¼ |
| | | * å
¼å®¹ä½çæ¬Java |
| | | */ |
| | | private static boolean isFinite(double value) { |
| | | return !Double.isNaN(value) && !Double.isInfinite(value); |
| | | } |
| | | } |
| | |
| | | public class ShouyeLauncher { |
| | | public static void main(String[] args) { |
| | | SwingUtilities.invokeLater(() -> { |
| | | System.out.println("Starting Shouye via Launcher..."); |
| | | JFrame frame = new JFrame("AutoMow - é¦é¡µ"); |
| | | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
| | | frame.setSize(400, 800); |
| | |
| | | |
| | | double lat = helper.parseDMToDecimal(latest.getLatitude(), latest.getLatDirection()); |
| | | double lon = helper.parseDMToDecimal(latest.getLongitude(), latest.getLonDirection()); |
| | | if (!Double.isFinite(lat) || !Double.isFinite(lon)) { |
| | | if (!isFinite(lat) || !isFinite(lon)) { |
| | | return; |
| | | } |
| | | |
| | | double[] local = helper.convertLatLonToLocal(lat, lon, baseLatLon[0], baseLatLon[1]); |
| | | Point2D.Double candidate = new Point2D.Double(local[0], local[1]); |
| | | if (!Double.isFinite(candidate.x) || !Double.isFinite(candidate.y)) { |
| | | if (!isFinite(candidate.x) || !isFinite(candidate.y)) { |
| | | return; |
| | | } |
| | | |
| | |
| | | g2d.setStroke(new BasicStroke(dashWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 10.0f, dashPattern, 0.0f)); |
| | | g2d.draw(path); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥double弿¯å¦æéï¼ä¸æ¯NaNææ ç©·å¤§ï¼ |
| | | * å
¼å®¹ä½çæ¬Java |
| | | */ |
| | | private static boolean isFinite(double value) { |
| | | return !Double.isNaN(value) && !Double.isInfinite(value); |
| | | } |
| | | } |
| | |
| | | // è¿æ»¤ææç¹ |
| | | List<Point2D.Double> validPoints = new java.util.ArrayList<>(); |
| | | for (Point2D.Double point : previewPoints) { |
| | | if (point != null && Double.isFinite(point.x) && Double.isFinite(point.y)) { |
| | | if (point != null && isFinite(point.x) && isFinite(point.y)) { |
| | | validPoints.add(point); |
| | | } |
| | | } |
| | |
| | | |
| | | double effectiveScale = Math.max(0.01d, scale); |
| | | double markerSize = cachedMarkerPixelDiameter / effectiveScale; |
| | | double normalizedScale = Double.isFinite(diameterScale) && diameterScale > 0.0d ? diameterScale : 1.0d; |
| | | double normalizedScale = isFinite(diameterScale) && diameterScale > 0.0d ? diameterScale : 1.0d; |
| | | markerSize *= normalizedScale; |
| | | double markerRadius = markerSize / 2.0d; |
| | | |
| | | for (Point2D.Double point : previewPoints) { |
| | | if (point == null || !Double.isFinite(point.x) || !Double.isFinite(point.y)) { |
| | | if (point == null || !isFinite(point.x) || !isFinite(point.y)) { |
| | | continue; |
| | | } |
| | | Shape marker = new Ellipse2D.Double(point.x - markerRadius, point.y - markerRadius, markerSize, markerSize); |
| | |
| | | g2d.setStroke(originalStroke); |
| | | g2d.setColor(originalColor); |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥double弿¯å¦æéï¼ä¸æ¯NaNææ ç©·å¤§ï¼ |
| | | * å
¼å®¹ä½çæ¬Java |
| | | */ |
| | | private static boolean isFinite(double value) { |
| | | return !Double.isNaN(value) && !Double.isInfinite(value); |
| | | } |
| | | } |
| | |
| | | double boundaryLineWidth = 3.0 / scaleFactor; // è¾¹ç线宽度 |
| | | double markerDiameter = boundaryLineWidth * 2.0; // æç¹ç´å¾ï¼è¾¹ç线宽度ç2åï¼ |
| | | // åºç¨ç´å¾ç¼©æ¾å å |
| | | if (diameterScale > 0.0 && Double.isFinite(diameterScale)) { |
| | | if (diameterScale > 0.0 && isFinite(diameterScale)) { |
| | | markerDiameter *= diameterScale; |
| | | } |
| | | double markerRadius = markerDiameter / 2.0; // åå¾ |
| | |
| | | double dy = a.y - b.y; // Yå·®å¼ |
| | | return Math.hypot(dx, dy) <= threshold; // è·ç¦»å¤æ |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥double弿¯å¦æéï¼ä¸æ¯NaNææ ç©·å¤§ï¼ |
| | | * å
¼å®¹ä½çæ¬Java |
| | | */ |
| | | private static boolean isFinite(double value) { |
| | | return !Double.isNaN(value) && !Double.isInfinite(value); |
| | | } |
| | | } |
| | |
| | | continue; |
| | | } |
| | | Point2D.Double point = sample.getPoint(); |
| | | if (point == null || !Double.isFinite(point.x) || !Double.isFinite(point.y)) { |
| | | if (point == null || !isFinite(point.x) || !isFinite(point.y)) { |
| | | continue; |
| | | } |
| | | if (!started) { |
| | |
| | | return point; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥double弿¯å¦æéï¼ä¸æ¯NaNææ ç©·å¤§ï¼ |
| | | * å
¼å®¹ä½çæ¬Java |
| | | */ |
| | | private static boolean isFinite(double value) { |
| | | return !Double.isNaN(value) && !Double.isInfinite(value); |
| | | } |
| | | } |
| | |
| | | #Updated User Properties |
| | | #Fri Dec 26 19:12:46 CST 2025 |
| | | email=981894274@qq.com |
| | | language=zh |
| | | #Sat Dec 27 20:42:59 GMT+08:00 2025 |
| | | registrationTime=-1 |
| | | lastLoginTime=1766747566698 |
| | | password=123456 |
| | | registrationTime=-1 |
| | | rememberPassword=1 |
| | | status=-1 |
| | | userId=-1 |
| | | rememberPassword=0 |
| | | language=zh |
| | | userName=981894274@qq.com |
| | | userId=-1 |
| | | email=981894274@qq.com |
| | | status=-1 |