-
Notifications
You must be signed in to change notification settings - Fork 2
/
box.fs
170 lines (155 loc) · 4.97 KB
/
box.fs
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
FeatureScript ✨; /* Automatically generated version */
// This module is part of the FeatureScript Standard Library and is distributed under the MIT License.
// See the LICENSE tab for the license text.
// Copyright (c) 2013-Present PTC Inc.
/**
* This module refers to 3D bounding boxes, e.g. the result of a call to `evBox3d`.
*
* This is not to be confused with the [box](/FsDoc/variables.html#box) standard type used for references.
*/
import(path : "onshape/std/units.fs", version : "✨");
import(path : "onshape/std/vector.fs", version : "✨");
import(path : "onshape/std/containers.fs", version : "✨");
import(path : "onshape/std/transform.fs", version : "✨");
/**
* A three-dimensional bounding box.
*
* @type {{
* @field minCorner {Vector}: A 3D position representing the corner with the smallest x, y, and z coordinates.
* @field maxCorner {Vector}: A 3D position representing the corner with the largest x, y, and z coordinates.
* }}
*/
export type Box3d typecheck canBeBox3d;
/** Typecheck for [Box3d] */
export predicate canBeBox3d(value)
{
value is map;
is3dLengthVector(value.minCorner);
is3dLengthVector(value.maxCorner);
for (var dim in [0, 1, 2])
value.minCorner[dim] <= value.maxCorner[dim];
}
/**
* Construct a bounding box from two opposite corners.
*/
export function box3d(minCorner is Vector, maxCorner is Vector) returns Box3d
{
for (var dim in [0, 1, 2])
{
if (minCorner[dim] > maxCorner[dim])
{
var tmp = maxCorner[dim];
maxCorner[dim] = minCorner[dim];
minCorner[dim] = tmp;
}
}
return { 'minCorner' : minCorner, 'maxCorner' : maxCorner } as Box3d;
}
/**
* Construct a bounding box containing all points in pointArray
* @param pointArray {array}
*/
export function box3d(pointArray is array) returns Box3d
precondition
{
size(pointArray) > 0;
for (var point in pointArray)
{
is3dLengthVector(point);
}
}
{
var minPoint = pointArray[0];
var maxPoint = minPoint;
for (var i = 1; i < size(pointArray); i += 1)
{
for (var j = 0; j < 3; j += 1)
{
const pointCoord = pointArray[i][j];
if (minPoint[j] > pointCoord)
{
minPoint[j] = pointCoord;
}
else if (maxPoint[j] < pointCoord)
{
maxPoint[j] = pointCoord;
}
}
}
return box3d(minPoint, maxPoint);
}
/**
* Return a box aligned with transformed coordinate system containing the input box
* @param boxIn {Box3d}
* @param transformation {Transform}
*/
export function transformBox3d(boxIn is Box3d, transformation is Transform) returns Box3d
{
var transformedPoints = [];
var coords = makeArray(3, undefined);
for (var i = 0; i < 3; i += 1)
{
coords[i] = [boxIn.minCorner[i], boxIn.maxCorner[i]];
}
for (var x in coords[0])
{
for (var y in coords[1])
{
for (var z in coords[2])
{
transformedPoints = append(transformedPoints, transformation * vector(x, y, z));
}
}
}
return box3d(transformedPoints);
}
/**
* Return an enlarged bounding box. The box is scaled by `1 + factor` around its midpoint, and then each face is
* moved outward by `absoluteValue` (inward if `absoluteValue` is negative).
* @param bBox {Box3d}
* @param absoluteValue {ValueWithUnits} : The absolute distance to move
* each face of the box. The corners move `sqrt(3)` times as far.
* @param factor {number} : The relative amount to expand the box, with
* `0` leaving it unchanged.
*/
export function extendBox3d(bBox is Box3d, absoluteValue is ValueWithUnits, factor is number) returns Box3d
precondition
{
isLength(absoluteValue);
}
{
const midPoint is Vector = box3dCenter(bBox);
const halfDiagonal is Vector = (bBox.maxCorner - bBox.minCorner) * 0.5;
const absoluteIncrement is Vector = vector(absoluteValue, absoluteValue, absoluteValue);
return box3d(midPoint - absoluteIncrement - halfDiagonal * (1 + factor),
midPoint + absoluteIncrement + halfDiagonal * (1 + factor));
}
/**
* Return the center of the bounding box.
* @param bBox {Box3d}
*/
export function box3dCenter(bBox is Box3d) returns Vector
{
return ((bBox.maxCorner + bBox.minCorner) / 2);
}
/**
* Return the length of the diagonal from the `minCorner` to the `maxCorner` of the bounding box.
*/
export function box3dDiagonalLength(bBox is Box3d) returns ValueWithUnits
{
return norm(bBox.maxCorner - bBox.minCorner);
}
/**
* Whether the specified point is within the bounding box.
* @param point {Vector}
* @param bBox {Box3d}
*/
export predicate insideBox3d(point is Vector, bBox is Box3d)
{
is3dLengthVector(point);
for (var dim in [0, 1, 2])
{
tolerantEquals(point[dim], bBox.minCorner[dim]) || point[dim] > bBox.minCorner[dim];
tolerantEquals(point[dim], bBox.maxCorner[dim]) || point[dim] < bBox.maxCorner[dim];
}
}