|
@@ -0,0 +1,264 @@
|
|
1
|
+package com.szls.nstths.service.impl;
|
|
2
|
+
|
|
3
|
+import java.math.BigDecimal;
|
|
4
|
+import java.util.ArrayList;
|
|
5
|
+import java.util.Collections;
|
|
6
|
+import java.util.List;
|
|
7
|
+
|
|
8
|
+import org.junit.jupiter.api.Test;
|
|
9
|
+
|
|
10
|
+public class Algorithm {
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+ /**
|
|
14
|
+ * 打点要发送的角度
|
|
15
|
+ * @param diameter
|
|
16
|
+ * @param high
|
|
17
|
+ * @return
|
|
18
|
+ */
|
|
19
|
+ public static String getAveragePosition(double diameter, double high) {
|
|
20
|
+ StringBuffer sb = new StringBuffer();
|
|
21
|
+
|
|
22
|
+ double x1 = 0;
|
|
23
|
+ double y1 = 0;
|
|
24
|
+ //打出来三角形的底边AB 实际是平面上点的斜边
|
|
25
|
+ double AB = 0; //理想状态
|
|
26
|
+ double x = 0;
|
|
27
|
+ double y = 0;
|
|
28
|
+ double BC = 0;
|
|
29
|
+ double vertical_angle = 0;//垂直的角度
|
|
30
|
+ double level_angle = 0;//水平的角度
|
|
31
|
+ /*double vertical_step = 0;//垂直的步长
|
|
32
|
+ double level_step = 0;//水平的步长
|
|
33
|
+*/
|
|
34
|
+ //根据直径判断半径是整数还是非整数 如果是非整数 则向下取整
|
|
35
|
+ double r = Math.floor(diameter / 2); //最大的半径 即一共有多少个圆圈
|
|
36
|
+
|
|
37
|
+ //一共有多少个圆圈
|
|
38
|
+ int circleNumber = (int) r;
|
|
39
|
+
|
|
40
|
+ for (int i = 1; i <= circleNumber; i++) {
|
|
41
|
+ //每一个圆一共有多少个的点 此时的半径长就是i
|
|
42
|
+ int pointCount = (int) ((2 * Math.PI * i) / 1.57);
|
|
43
|
+
|
|
44
|
+ for (int j = 0; j < pointCount; j++) {
|
|
45
|
+
|
|
46
|
+ /**
|
|
47
|
+ * 以其他点为圆心的圆 r是i degrees是以圆心为中心转动的角度 其坐标x1、y1则是
|
|
48
|
+ */
|
|
49
|
+ double degrees = (360 / pointCount) * j;
|
|
50
|
+ //System.out.println(degrees+"度数");
|
|
51
|
+ double radians = Math.toRadians(degrees);//转化为弧度
|
|
52
|
+ String strx = String.format("%.2f%n", Math.cos(radians) * i);//计算横坐标的值
|
|
53
|
+ x1 = new Double(strx);
|
|
54
|
+ String stry = String.format("%.2f%n", Math.sin(radians) * i);//计算纵坐标的值
|
|
55
|
+ y1 = new Double(stry);
|
|
56
|
+
|
|
57
|
+ /**
|
|
58
|
+ * 以设备为中心,把圆上的点分为上下两半,
|
|
59
|
+ * 新的圆 是旧的圆向左平移了(diameter/2-i)+i 个长度 得到的
|
|
60
|
+ * (设备在新的圆的最左边上,设备是坐标系的原点)
|
|
61
|
+ * 所以 横坐标加上这个长度 纵坐标不变
|
|
62
|
+ */
|
|
63
|
+
|
|
64
|
+ //纵坐标 无论是处于上半部分还是下半部分 其纵坐标是不变的
|
|
65
|
+ x = x1 + (diameter / 2 - i) + i;
|
|
66
|
+ y = y1;
|
|
67
|
+ //System.out.print("["+x+","+y+"]"+",");
|
|
68
|
+ //底面三角形的斜边
|
|
69
|
+ AB = Math.sqrt(x * x + y * y);
|
|
70
|
+ //垂直三角形的斜边
|
|
71
|
+ BC = Math.sqrt(AB * AB + high * high);
|
|
72
|
+ if (x == 0 && y == 0) {//圆 点
|
|
73
|
+ level_angle = 0;
|
|
74
|
+ vertical_angle = 0;
|
|
75
|
+
|
|
76
|
+ } else if (y < 0) {//反向转
|
|
77
|
+ level_angle = -Math.toDegrees(Math.acos(Math.abs(y) / AB));
|
|
78
|
+ vertical_angle = -(Math.toDegrees(Math.acos(high / BC)));
|
|
79
|
+
|
|
80
|
+ } else {//正向转
|
|
81
|
+ level_angle = Math.toDegrees(Math.acos(y / AB));
|
|
82
|
+ vertical_angle = Math.toDegrees(Math.acos(high / BC));
|
|
83
|
+
|
|
84
|
+ }
|
|
85
|
+
|
|
86
|
+ sb.append(Math.round(level_angle));
|
|
87
|
+ sb.append(",");
|
|
88
|
+ sb.append(Math.round(vertical_angle));
|
|
89
|
+ sb.append("-");
|
|
90
|
+ // sb.append("\n");
|
|
91
|
+ }
|
|
92
|
+ }
|
|
93
|
+
|
|
94
|
+ /**
|
|
95
|
+ * 追加一个圆筒仓中心的点,其坐标是(diameter/2,0) 水平转动90度 步长为2167
|
|
96
|
+ */
|
|
97
|
+ AB = diameter / 2;//垂直三角形的底边
|
|
98
|
+ BC = Math.sqrt(AB * AB + high * high);//垂直三角形的斜边
|
|
99
|
+ vertical_angle = Math.toDegrees(Math.acos(high / BC));
|
|
100
|
+ sb.append(90);
|
|
101
|
+ sb.append(",");
|
|
102
|
+ sb.append(Math.round(vertical_angle));
|
|
103
|
+ // sb.append("\n");
|
|
104
|
+ //System.out.println(Math.round(level_step)+","+Math.round(vertical_step)+"");
|
|
105
|
+ //System.out.println(sb);
|
|
106
|
+ System.out.println(sb);
|
|
107
|
+ return sb.toString();
|
|
108
|
+
|
|
109
|
+ }
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+ /**
|
|
113
|
+ * 计算 以粮面为基准面的高
|
|
114
|
+ * @param list
|
|
115
|
+ * @return
|
|
116
|
+ */
|
|
117
|
+ public static double zHeight(String rotationxy,double diameter, double high) {
|
|
118
|
+
|
|
119
|
+ List<Double> zList = new ArrayList<Double>();
|
|
120
|
+
|
|
121
|
+ // logger.info("zHeight - list",list);
|
|
122
|
+ double AC = high;
|
|
123
|
+ double B1C = 0;//设备和粮面点之间的距离
|
|
124
|
+ double A1B1 = 0;//粮面到设备的水平距离
|
|
125
|
+ double z = 0; //实际点的坐标的z轴
|
|
126
|
+ double zHigh = 0;//以粮面为基准面的高
|
|
127
|
+ double zMax = 0;//最高的点
|
|
128
|
+ double verticalAngle = 0;//垂直角度
|
|
129
|
+ double levelAngle = 0;//水平角度
|
|
130
|
+ double realHypotenuse = 0;//返回的距离
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+ // "18,7,17.88 - 19,6,28.88 - 17,4,39.88" 水平角度,垂直角度,返回距离 -
|
|
134
|
+ String[] split = rotationxy.split("-");
|
|
135
|
+ for (int i = 0; i < split.length; i++) {
|
|
136
|
+ String[] split1 = split[i].split(",");
|
|
137
|
+ levelAngle = Double.parseDouble(split1[0]);
|
|
138
|
+ verticalAngle = Double.parseDouble(split1[1]);
|
|
139
|
+ realHypotenuse = Double.parseDouble(split1[2]);
|
|
140
|
+
|
|
141
|
+ //将垂直的角度转化为弧度
|
|
142
|
+ double verticalAngleRadians = Math.toRadians(verticalAngle);
|
|
143
|
+ String verticalAngleS = String.format("%.2f%n", Math.sin(verticalAngleRadians));
|
|
144
|
+ double sinc = new Double(verticalAngleS);
|
|
145
|
+ //B1C = realHypotenuse;
|
|
146
|
+ A1B1 = realHypotenuse * sinc; //即 平面三角形的斜边
|
|
147
|
+
|
|
148
|
+ //logger.info("zHeight - A1B1 {} ",A1B1);
|
|
149
|
+
|
|
150
|
+ String sinLevel = String.format("%.2f%n", Math.sin(Math.abs(levelAngle)));
|
|
151
|
+ double sinLevelc = new Double(sinLevel);
|
|
152
|
+
|
|
153
|
+ /*
|
|
154
|
+ * 对比实际的A1B1与打到墙上时最大的这个边进行比较 如果A1B1小于这个最大边则可取
|
|
155
|
+ * 如果A1B1大于或等于这个最大的边 则打到了墙上 舍去
|
|
156
|
+ * */
|
|
157
|
+ //打到墙上 最大的边
|
|
158
|
+ double maxLength = sinLevelc * diameter;
|
|
159
|
+
|
|
160
|
+ if (A1B1 < maxLength) {
|
|
161
|
+ //实际打在粮面上的点的坐标
|
|
162
|
+ String verticalAngleC = String.format("%.2f%n", Math.cos(verticalAngleRadians));
|
|
163
|
+ double cosc = new Double(verticalAngleC);
|
|
164
|
+ double A1C = realHypotenuse * cosc;
|
|
165
|
+ z = AC - A1C;
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+ // logger.info("zHeight - z√√√√√√z z z z z {} ",z);
|
|
169
|
+
|
|
170
|
+ zList.add(z);
|
|
171
|
+ }
|
|
172
|
+ }
|
|
173
|
+
|
|
174
|
+ zMax = Collections.max(zList);
|
|
175
|
+ zHigh = AC - zMax;
|
|
176
|
+ return zHigh;
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+ /*
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+ for (ReceiveData angleObject : list) {
|
|
184
|
+ verticalAngle = angleObject.getVerticalAngle();
|
|
185
|
+ levelAngle = angleObject.getLevelAngle();
|
|
186
|
+ realHypotenuse = angleObject.getRealHypotenuse();
|
|
187
|
+ //logger.info("zHeight - realHypotenuse {} ",realHypotenuse);
|
|
188
|
+
|
|
189
|
+ //将垂直的角度转化为弧度
|
|
190
|
+ double verticalAngleRadians = Math.toRadians(verticalAngle);
|
|
191
|
+ String verticalAngleS = String.format("%.2f%n", Math.sin(verticalAngleRadians));
|
|
192
|
+ double sinc = new Double(verticalAngleS);
|
|
193
|
+ //B1C = realHypotenuse;
|
|
194
|
+ A1B1 = realHypotenuse * sinc; //即 平面三角形的斜边
|
|
195
|
+
|
|
196
|
+ //logger.info("zHeight - A1B1 {} ",A1B1);
|
|
197
|
+
|
|
198
|
+ String sinLevel = String.format("%.2f%n", Math.sin(Math.abs(levelAngle)));
|
|
199
|
+ double sinLevelc = new Double(sinLevel);
|
|
200
|
+
|
|
201
|
+ *//**
|
|
202
|
+ * 对比实际的A1B1与打到墙上时最大的这个边进行比较 如果A1B1小于这个最大边则可取
|
|
203
|
+ * 如果A1B1大于或等于这个最大的边 则打到了墙上 舍去
|
|
204
|
+ *//*
|
|
205
|
+ //打到墙上 最大的边
|
|
206
|
+ double maxLength = sinLevelc * diameter;
|
|
207
|
+
|
|
208
|
+ if (A1B1 < maxLength) {
|
|
209
|
+ //实际打在粮面上的点的坐标
|
|
210
|
+ String verticalAngleC = String.format("%.2f%n", Math.cos(verticalAngleRadians));
|
|
211
|
+ double cosc = new Double(verticalAngleC);
|
|
212
|
+ double A1C = realHypotenuse * cosc;
|
|
213
|
+ z = AC - A1C;
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+ // logger.info("zHeight - z√√√√√√z z z z z {} ",z);
|
|
217
|
+
|
|
218
|
+ zList.add(z);
|
|
219
|
+ }
|
|
220
|
+ }
|
|
221
|
+ zMax = Collections.max(zList);
|
|
222
|
+ zHigh = AC - zMax;
|
|
223
|
+ return zHigh;
|
|
224
|
+*/
|
|
225
|
+ }
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+ /**
|
|
230
|
+ * 计算体积
|
|
231
|
+ *
|
|
232
|
+ * @param zList 粮面高集合(z值的集合)
|
|
233
|
+ */
|
|
234
|
+ public static double calculateVolume(List<Double> zList,double diameter,double h1,double h2) {
|
|
235
|
+
|
|
236
|
+ //17.1 18.3 19.2 18.3 20.1 16.4 19.8 16.7 19.0 18.9
|
|
237
|
+ Double zMin = Collections.min(zList); //z的最小值
|
|
238
|
+
|
|
239
|
+ double sum = 0;
|
|
240
|
+ double zHeigh = 0;//每一个z与最低点的z差值
|
|
241
|
+ for (int i = 0; i < zList.size(); i++) {
|
|
242
|
+ //sum = zList.get(i)+sum;
|
|
243
|
+ zHeigh = zList.get(i) - zMin;
|
|
244
|
+ sum += zHeigh;
|
|
245
|
+
|
|
246
|
+ }
|
|
247
|
+ /** v 是总体积
|
|
248
|
+ * v1 最上面的那一部分
|
|
249
|
+ * v2 是中间的圆柱
|
|
250
|
+ * v3 是 圆锥
|
|
251
|
+ *
|
|
252
|
+ * h1 圆锥的高
|
|
253
|
+ * h2 水平地面到圆锥尖的高
|
|
254
|
+ */
|
|
255
|
+
|
|
256
|
+ double v1 = 3.14 * (diameter / 2) * (diameter / 2) * (sum / zList.size());
|
|
257
|
+ double v2 = 3.14 * (diameter / 2) * (diameter / 2) * (zMin - h2 - h1);
|
|
258
|
+ double v3 = (3.14 * (diameter / 2) * (diameter / 2) * h1) / 3;
|
|
259
|
+ double vv = v1 + v2 + v3;
|
|
260
|
+ BigDecimal bdv = new BigDecimal(vv);
|
|
261
|
+ double v = bdv.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
|
|
262
|
+ return v;
|
|
263
|
+ }
|
|
264
|
+}
|