-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDistanceBetweenPointAndSegmentIn3D_v2.java
More file actions
150 lines (122 loc) · 4.19 KB
/
DistanceBetweenPointAndSegmentIn3D_v2.java
File metadata and controls
150 lines (122 loc) · 4.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import java.util.Scanner;
class Vector {
double x;
double y;
double z;
Vector (Point3D a, Point3D b) {
this.x = b.x - a.x;
this.y = b.y - a.y;
this.z = b.z - a.z;
}
public double vectorLength() {
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
}
}
class Point3D {
public double x;
public double y;
public double z;
Point3D(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point3D point3D = (Point3D) o;
if (Double.compare(point3D.x, x) != 0) return false;
if (Double.compare(point3D.y, y) != 0) return false;
return Double.compare(point3D.z, z) == 0;
}
}
enum PointDispositionCase {
ON_SEGMENT,
PERPENDICULAR_POSSIBLE,
PERPENDICULAR_IMPOSSIBLE,
BEGIN_AND_END_ARE_SAME,
}
class DistanceBetweenPointAndSegmentIn3DT {
static public double findDistance(Point3D P, Point3D B, Point3D E) {
PointDispositionCase pointDispositionCase =
findPointDispositionCase(P, B , E);
switch (pointDispositionCase) {
case ON_SEGMENT:
return 0;
case BEGIN_AND_END_ARE_SAME:
return segmentLength(P, B);
case PERPENDICULAR_IMPOSSIBLE:
return Math.min(
segmentLength(P, E),
segmentLength(P, B)
);
case PERPENDICULAR_POSSIBLE:
return findDistanceByTriangleSquare(P, B, E);
}
return -1;
}
static private PointDispositionCase findPointDispositionCase(Point3D P, Point3D B, Point3D E) {
double BE = segmentLength(B, E);
double PE = segmentLength(P, E);
double BP = segmentLength(B, P);
if (BP + PE == BE) {
return PointDispositionCase.ON_SEGMENT;
}
if (B.equals(E)) {
return PointDispositionCase.BEGIN_AND_END_ARE_SAME;
}
double cosPEB = findCos(
new Vector(E, P),
new Vector(E, B)
);
double cosPBE = findCos(
new Vector(B, P),
new Vector(B, E)
);
if (cosPBE <= 0 || cosPEB <= 0) {
return PointDispositionCase.PERPENDICULAR_IMPOSSIBLE;
}
return PointDispositionCase.PERPENDICULAR_POSSIBLE;
}
static private double segmentLength(Point3D a, Point3D b) {
return Math.sqrt(
(b.x - a.x) * (b.x - a.x)
+ (b.y - a.y) * (b.y - a.y)
+ (b.z - a.z) * (b.z - a.z)
);
}
static private double findCos(Vector a, Vector b) {
return (a.x * b.x + a.y * b.y + a.z * b.z) /
(a.vectorLength() + b.vectorLength());
}
static private double findDistanceByTriangleSquare(Point3D P, Point3D B, Point3D E) {
double a = segmentLength(B, E);
double b = segmentLength(B, P);
double c = segmentLength(E, P);
double p = (a + b + c) / 2;
return 2 / a * Math.sqrt(p * (p - a) * (p - b) * (p - c));
}
}
class DistanceBetweenPointAndSegmentIn3D {
public static void main(String[] args) {
Scanner inputStream = new Scanner(System.in);
Point3D point = new Point3D(
inputStream.nextDouble(),
inputStream.nextDouble(),
inputStream.nextDouble()
);
Point3D begin = new Point3D(
inputStream.nextDouble(),
inputStream.nextDouble(),
inputStream.nextDouble()
);
Point3D end = new Point3D(
inputStream.nextDouble(),
inputStream.nextDouble(),
inputStream.nextDouble()
);
double result = DistanceBetweenPointAndSegmentIn3DT.findDistance(point, begin, end);
System.out.print(result);
}
}