mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-06 12:01:10 +00:00
Kernel tests, fillet rig: a chamfer as wide as its rim builds
The owner's ruling of 2026-10-30 (d7): a chamfer that reaches or runs
past a rim builds, everywhere. The earlier rule refused a full-width
chamfer, naming the largest size that fits. SolidCraft has no such
refusal of its own (a blend's TooLarge is SMLib's SMLIB_ERR_NO_ROOM,
and the doc layer only names the largest fit), and SMLib already builds
these, so only the expectations change, each from a closed form or an
exact quadrature:
- chamfer_wider_than_sloped_basin_rim_is_refused's full widths become
chamfer_as_wide_as_sloped_basin_rim_builds: the whole triangle,
d drop / 2 (60 - drop / 3), drop = 20 d / sqrt((20 - margin)^2 + 400)
(shoelace over the section, its length 30 + z between the sloped end
walls): 21.662379 (1 on 1 mm), 5.359321 (0.5 on 0.5 mm). The basin and
the removal move into sloped_basin and sloped_basin_rim_chamfer_removed.
- fillets/1080-chamfer-sloped-basin-{1,0-5}-mm-rim-as-wide-as-the-rim:
V = 144511.670954, 144261.307346.
- fillets/every-chamfer-pocket-rim-5-full-depth: 50 d^2 + (4/3) d^3 at
d = 5, V = 19583.333333, 11 faces (the walls used up).
- fillets/every-hole-top-rim-chamfer-10-full-depth: the triangle 10^2/2
revolved at rho = 5 + 10/3 (Pappus), V = 16000 - 3250 pi / 3 =
12596.607959, 7 faces.
- fillets/1113-chamfer-arc-top-edge-full-wall-height: the 9.5 case's
Int rho asin(21/rho) h(rho) drho at s = 10, by Gauss-Legendre in
u = asin(21/rho), 1303.400331, V = 8287.993768.
Each drops "-refused" from its id and its KNOWN_FAILING line goes: all
five pass on SMLib 985faaee.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+54
-23
@@ -1104,31 +1104,62 @@ fn chamfer_sloped_basin_rim() {
|
||||
assert!(mesh.contains(Vec3::new(50.0, 3.5, 28.0)));
|
||||
}
|
||||
|
||||
/// A chamfer wider than a basin's thin rim (`chamfer_sloped_basin_rim`'s basin with the rim
|
||||
/// `margin` wide at the top) would run its leg off the rim's top, over the slab's front edge; as
|
||||
/// wide as the rim it would use the rim's top up. Both are refused as too large, the kind a fit
|
||||
/// can reduce, the body unchanged (the owner's blend-overflow ruling, 2026-10-30). The largest
|
||||
/// size that fits is named by the doc layer (`with_largest_fit`) and graded, with the chamfers
|
||||
/// that fit, by the rig's fillets/1080-chamfer-sloped-basin-* cases.
|
||||
#[test]
|
||||
fn chamfer_wider_than_sloped_basin_rim_is_refused() {
|
||||
/// `chamfer_sloped_basin_rim`'s basin with its front rim `margin` wide at the top.
|
||||
fn sloped_basin(margin: f64) -> Body {
|
||||
let rectangle = |x0, y0, x1, y1| Loop2::polygon(&[Vec2::new(x0, y0), Vec2::new(x1, y0), Vec2::new(x1, y1), Vec2::new(x0, y1)]);
|
||||
let basin = |margin: f64| {
|
||||
let slab = box_solid(Vec3::ZERO, Vec3::new(100.0, 60.0, 30.0)).unwrap();
|
||||
let pocket =
|
||||
loft(&[(Plane::XY.offset(30.0), rectangle(20.0, margin, 80.0, 50.0)), (Plane::XY.offset(10.0), rectangle(30.0, 20.0, 70.0, 40.0))])
|
||||
.unwrap();
|
||||
boolean(&slab, &pocket, BoolOp::Cut).unwrap().unwrap()
|
||||
let slab = box_solid(Vec3::ZERO, Vec3::new(100.0, 60.0, 30.0)).unwrap();
|
||||
let pocket =
|
||||
loft(&[(Plane::XY.offset(30.0), rectangle(20.0, margin, 80.0, 50.0)), (Plane::XY.offset(10.0), rectangle(30.0, 20.0, 70.0, 40.0))])
|
||||
.unwrap();
|
||||
boolean(&slab, &pocket, BoolOp::Cut).unwrap().unwrap()
|
||||
}
|
||||
|
||||
/// What an equal-distance chamfer `d` of [`sloped_basin`]'s rim edge at y = `margin` takes, built
|
||||
/// as if the top went on past the slab's front face y = 0 and then cut by it (the owner's ruling
|
||||
/// of 2026-10-30, d7: a chamfer that reaches or runs past a rim builds). Its section in (y, z) is
|
||||
/// the triangle of the edge (margin, 30), the top's contact (margin − d, 30) and the wall's
|
||||
/// contact d down the wall towards (20, 10) (run 20 − margin over the drop 20), clipped to
|
||||
/// y >= 0. At height z it runs between the sloped end walls x = 20 + (30 − z)/2 and
|
||||
/// 80 − (30 − z)/2 (planar, x by z alone), which cut it, so its length there is 30 + z: it takes
|
||||
/// ∬ (30 + z) dy dz over the clipped section, area · 30 + ∬ z, both exact by the shoelace sums
|
||||
/// over the polygon (the first moment Σ (z₀ + z₁)(y₀ z₁ − y₁ z₀) / 6).
|
||||
fn sloped_basin_rim_chamfer_removed(margin: f64, d: f64) -> f64 {
|
||||
let len = ((20.0 - margin).powi(2) + 400.0).sqrt();
|
||||
let (e, t) = ((margin, 30.0), (margin - d, 30.0));
|
||||
let w = (margin + d * (20.0 - margin) / len, 30.0 - d * 20.0 / len);
|
||||
let poly = if t.0 >= 0.0 {
|
||||
vec![e, t, w]
|
||||
} else {
|
||||
let s = -t.0 / (w.0 - t.0);
|
||||
vec![e, (0.0, 30.0), (0.0, t.1 + s * (w.1 - t.1)), w]
|
||||
};
|
||||
for (margin, distance) in [(1.0, 2.0), (1.0, 3.0), (0.5, 4.0), (0.5, 0.5), (1.0, 1.0)] {
|
||||
let b = basin(margin);
|
||||
let before = measure(&b).unwrap().volume;
|
||||
match chamfer(&b, &[Vec3::new(50.0, margin, 30.0)], distance) {
|
||||
Err(KernelError::TooLarge(_)) => {}
|
||||
Err(e) => panic!("{margin}, {distance}: refused, but not as too large: {e}"),
|
||||
Ok(_) => panic!("{margin}, {distance}: a chamfer whose leg runs off the rim was built"),
|
||||
}
|
||||
assert_eq!(measure(&b).unwrap().volume, before);
|
||||
let (mut area, mut moment) = (0.0, 0.0);
|
||||
for i in 0..poly.len() {
|
||||
let ((y0, z0), (y1, z1)) = (poly[i], poly[(i + 1) % poly.len()]);
|
||||
let c = y0 * z1 - y1 * z0;
|
||||
area += c / 2.0;
|
||||
moment += (z0 + z1) * c / 6.0;
|
||||
}
|
||||
area.abs() * 30.0 + moment.abs()
|
||||
}
|
||||
|
||||
/// A chamfer as wide as a basin's thin rim (`chamfer_sloped_basin_rim`'s basin with the rim
|
||||
/// `margin` wide at the top) uses the rim's top up, its leg ending on the slab's front edge:
|
||||
/// it builds (the owner's ruling of 2026-10-30, d7), taking the whole triangle
|
||||
/// ([`sloped_basin_rim_chamfer_removed`]: unclipped, d · drop / 2 · (60 − drop / 3) with
|
||||
/// drop = 20 d / √((20 − margin)² + 400)): 21.662379 at 1 on the 1 mm rim, 5.359321 at 0.5 on
|
||||
/// the 0.5 mm one.
|
||||
#[test]
|
||||
fn chamfer_as_wide_as_sloped_basin_rim_builds() {
|
||||
// The formula reads the fitting chamfer of `chamfer_sloped_basin_rim` as that test does.
|
||||
let drop = 2.0 / (1.0 + 0.8f64.powi(2)).sqrt();
|
||||
assert!(rel(sloped_basin_rim_chamfer_removed(4.0, 2.0), drop * (60.0 - drop / 3.0)) < 1e-12);
|
||||
for margin in [0.5, 1.0] {
|
||||
let b = sloped_basin(margin);
|
||||
let made = chamfer(&b, &[Vec3::new(50.0, margin, 30.0)], margin).unwrap_or_else(|e| panic!("{margin}: {e}"));
|
||||
assert!(made.validity().is_empty(), "{margin}: {:?}", made.validity());
|
||||
let want = measure(&b).unwrap().volume - sloped_basin_rim_chamfer_removed(margin, margin);
|
||||
assert!(rel(measure(&made).unwrap().volume, want) < 1e-8, "{margin}: {} vs {want}", measure(&made).unwrap().volume);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"sources": [
|
||||
"tangency-labs/solidcraft#1080"
|
||||
],
|
||||
"what": "the 0.5 mm front rim of a sloped basin's top chamfered 0.5: as wide as the rim, the chamfer would use the rim's top up: refused",
|
||||
"source": "analytic",
|
||||
"method": "slab 100 x 60 x 30 less the loft from the rectangle (20, 0.5)-(80, 50) at z = 30 to (30, 20)-(70, 40) at z = 10 (planar walls, a prismatoid: 20/6 (A_top + A_bottom + 4 A_mid)): V0 = 144266.666667. A chamfer as wide as the face beside its edge uses it up: full-width chamfers are refused (the owner's ruling of 2026-10-30).",
|
||||
"outcome": "refused",
|
||||
"refusal": "the largest distance that fits is"
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"sources": [
|
||||
"tangency-labs/solidcraft#1080"
|
||||
],
|
||||
"what": "the 0.5 mm front rim of a sloped basin's top chamfered 0.5, as wide as the rim: its leg on the top ends on the slab's front edge, using the rim's top up, and it builds",
|
||||
"source": "analytic",
|
||||
"method": "slab 100 x 60 x 30 less the loft from the rectangle (20, 0.5)-(80, 50) at z = 30 to (30, 20)-(70, 40) at z = 10 (planar walls, a prismatoid: 20/6 (A_top + A_bottom + 4 A_mid)): V0 = 144266.666667. The chamfer's triangle in (y, z): the edge (0.5, 30), its leg on the top to (0, 30), the slab's front edge, and d down the wall to (0.5 + d (20-0.5)/L, 30 - 20 d/L), L = sqrt((20-0.5)^2 + 400) (the owner's ruling of 2026-10-30 (d7): a chamfer that reaches or runs past a rim builds). At height z the blend runs between the sloped end walls x = 20 + (30-z)/2 and 80 - (30-z)/2 extended, which cut it: its length there is 30 + z, so it takes Int Int (30 + z) dy dz over its section (y, z). Removed (shoelace for the area and its first moment) 5.359321. V = 144261.307346",
|
||||
"body_count": 1,
|
||||
"volume_mm3": 144261.307345957,
|
||||
"bbox": {
|
||||
"min": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"max": [
|
||||
100,
|
||||
60,
|
||||
30
|
||||
]
|
||||
},
|
||||
"tolerance": {
|
||||
"rel": 1e-06
|
||||
}
|
||||
}
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"sources": [
|
||||
"tangency-labs/solidcraft#1080"
|
||||
],
|
||||
"what": "the 1 mm front rim of a sloped basin's top chamfered 1: as wide as the rim, the chamfer would use the rim's top up: refused",
|
||||
"source": "analytic",
|
||||
"method": "slab 100 x 60 x 30 less the loft from the rectangle (20, 1)-(80, 50) at z = 30 to (30, 20)-(70, 40) at z = 10 (planar walls, a prismatoid: 20/6 (A_top + A_bottom + 4 A_mid)): V0 = 144533.333333. A chamfer as wide as the face beside its edge uses it up: full-width chamfers are refused (the owner's ruling of 2026-10-30).",
|
||||
"outcome": "refused",
|
||||
"refusal": "the largest distance that fits is"
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"sources": [
|
||||
"tangency-labs/solidcraft#1080"
|
||||
],
|
||||
"what": "the 1 mm front rim of a sloped basin's top chamfered 1, as wide as the rim: its leg on the top ends on the slab's front edge, using the rim's top up, and it builds",
|
||||
"source": "analytic",
|
||||
"method": "slab 100 x 60 x 30 less the loft from the rectangle (20, 1)-(80, 50) at z = 30 to (30, 20)-(70, 40) at z = 10 (planar walls, a prismatoid: 20/6 (A_top + A_bottom + 4 A_mid)): V0 = 144533.333333. The chamfer's triangle in (y, z): the edge (1, 30), its leg on the top to (0, 30), the slab's front edge, and d down the wall to (1 + d (20-1)/L, 30 - 20 d/L), L = sqrt((20-1)^2 + 400) (the owner's ruling of 2026-10-30 (d7): a chamfer that reaches or runs past a rim builds). At height z the blend runs between the sloped end walls x = 20 + (30-z)/2 and 80 - (30-z)/2 extended, which cut it: its length there is 30 + z, so it takes Int Int (30 + z) dy dz over its section (y, z). Removed (shoelace for the area and its first moment) 21.662379. V = 144511.670954",
|
||||
"body_count": 1,
|
||||
"volume_mm3": 144511.67095435527,
|
||||
"bbox": {
|
||||
"min": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"max": [
|
||||
100,
|
||||
60,
|
||||
30
|
||||
]
|
||||
},
|
||||
"tolerance": {
|
||||
"rel": 1e-06
|
||||
}
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"sources": [
|
||||
"tangency-labs/solidcraft#1113",
|
||||
"tangency-labs/solidcraft#851"
|
||||
],
|
||||
"what": "the top edge of #851's concave R21 wall chamfered 10, the wall's full height: refused as too large",
|
||||
"source": "analytic",
|
||||
"method": "a chamfer as tall as the wall would leave the wall a face of no area (its two boundary arcs on one line): refused as too large (#1113), naming the largest distance that fits",
|
||||
"outcome": "refused",
|
||||
"refusal": "the largest distance that fits is"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"sources": [
|
||||
"tangency-labs/solidcraft#1113",
|
||||
"tangency-labs/solidcraft#851"
|
||||
],
|
||||
"what": "the top edge of #851's concave R21 wall chamfered 10, the wall's full height: its leg down the wall ends on the wall's bottom edge, using the wall up, and it builds",
|
||||
"source": "analytic",
|
||||
"method": "plate x 0..41.1667, y -21..0 and the corner x 41.1667..62.1667 less the cylinder r 21 about (62.1667, -21), 10 high (tessellation/1263): V0 = 10 (62.1667 x 21 - pi 21^2/4) = 9591.394099. s = 10, the wall's full height (the owner's ruling of 2026-10-30 (d7): a chamfer that reaches or runs past a rim builds). The blend's section in (rho, z) about the wall's axis, the triangle (rho - 21) + (10 - z) <= s, is swept round it from the front face (square to the arc) to the back face y = 0, which the arc runs into tangent at the tip: at radius rho the part spans the angle asin(21/rho), so the blend takes Int_21^31 rho asin(21/rho) h(rho) drho with h(rho) = s - (rho - 21), integrated as Int u (21/sin u) h(21/sin u) 21 cos u / sin^2 u du over u = asin(21/rho) in [asin(21/31), pi/2] (smooth there), Gauss-Legendre 30 points on 64 pieces, converged to the last digit: 1303.400331. V = 8287.993768",
|
||||
"body_count": 1,
|
||||
"volume_mm3": 8287.993767991788,
|
||||
"bbox": null,
|
||||
"continuity": {
|
||||
"order": "g0"
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,6 @@
|
||||
# rig gate (.github/workflows/fillet-rig.yml) fails on a case that fails and is not listed here,
|
||||
# and on a listed case that passes: a fix removes its line in the same pull request.
|
||||
# Baseline: develop 242bbc89f with the SMLib fixes of 2026-10-29 (integration-overnight + b78bd4a), aarch64 Linux.
|
||||
1080-chamfer-sloped-basin-0-5-mm-rim-as-wide-as-the-rim-refused builds the full-width chamfer where it should be refused, naming the largest that fits
|
||||
1080-chamfer-sloped-basin-1-mm-rim-as-wide-as-the-rim-refused builds the full-width chamfer where it should be refused, naming the largest that fits
|
||||
1080-fillet-equal-slope-basin-1-mm-rim-loop-0-5 SMLib's check refuses the round: SmSurfOfRevolution Test #7, polar curve intervals do not match the surface's domain
|
||||
1080-fillet-equal-slope-basin-1-mm-rim-loop-4 not supported yet: a convex round past its face is not yet built by subtraction
|
||||
1080-fillet-notched-block-top-outline-r8 not supported yet: a convex round past its face is not yet built by subtraction (largest that fits named 7 mm)
|
||||
@@ -13,7 +11,6 @@
|
||||
1080-fillet-sloped-basin-1-mm-rim-r4 not supported yet: a convex round past its face is not yet built by subtraction (largest that fits named 2.329 mm)
|
||||
1080-fillet-sloped-basin-1-mm-rim-r4-2-edges not supported yet: a convex round past its face is not yet built by subtraction
|
||||
1080-fillet-sloped-basin-1-mm-rim-r4-4-edges not supported yet: a convex round past its face is not yet built by subtraction
|
||||
1113-chamfer-arc-top-edge-full-wall-height-refused builds the chamfer as tall as the wall where it should be refused as too large
|
||||
1207-fillet-bar-top-edge-after-boss-arc-round-r0-5 SMLib's check refuses the round: internal coincident control points in a B-spline curve (an internal pole)
|
||||
1668-fillet-outer-top-edge-of-thin-wall-r7-past-inside-corner a slit along the hollow, 0.507 mm^3 off: 38458.389 is V0 less the round's whole section along 104, so the section's part over the hollow (0.005068 mm^2 along 100), which is not material, is taken anyway
|
||||
190-fillet-disc-rim-past-its-2mm-wall SMLib status 1001: a convex round past its face is not yet built by subtraction
|
||||
@@ -40,8 +37,6 @@ cov-chamfer-outer-corner-edge-of-a-shelled-box-with-a-lip SMLib's chamfer result
|
||||
cov-fillet-arc-edge-on-an-oblique-cut-of-a-bar SMLib's check refuses the round: internal coincident control points in a B-spline curve
|
||||
every-block-cylinder-crease-top-edge-after-arc-round-r1 the r1 round's contact seam with the block's side face reads 60 degrees (the cylinder wall's normal) at its end on the crease (8.660, 5, 15.284): G0 where the round is built tangent
|
||||
every-chamfer-pocket-rim-5-5-refused refused naming 5 mm as the largest distance: the full-width chamfer (legs as deep as the 5 mm walls) builds instead of being refused
|
||||
every-chamfer-pocket-rim-5-full-depth-refused the full-width chamfer (legs as deep as the 5 mm walls) builds instead of being refused
|
||||
every-hole-top-rim-chamfer-10-full-depth-refused the full-width chamfer (leg as deep as the 10 mm plate) builds instead of being refused
|
||||
every-hole-top-rim-r12-past-plate-bottom SMLib status 1001: a convex round past its face on the tangent side is not yet built by subtraction
|
||||
every-pocket-floor-and-rim-edges-r2 a corner patch where two rim rounds meet at each concave pocket corner (23 faces, not 19) instead of the mitre the rounds make running into each other
|
||||
every-pocket-rim-edges-r2 a corner patch where two rim rounds meet at each concave pocket corner (19 faces, not 15) instead of the mitre the rounds make running into each other
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"sources": [],
|
||||
"what": "a 5 mm deep pocket's rim edges chamfered 5: the legs would use the whole walls: refused, naming the largest distance that fits",
|
||||
"source": "invariants",
|
||||
"method": "owner rule: a chamfer whose leg runs off the face beside its edge over another face is refused, naming the largest size that fits, and a full-width chamfer stays refused. The walls are 5 deep, so every distance below 5 fits (every-chamfer-pocket-rim-4-9-fits) and 5 does not; the search names the largest at the request's three significant digits (step 0.001): 4.999.",
|
||||
"outcome": "refused",
|
||||
"refusal": "the largest distance that fits is 4.999 mm"
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"sources": [],
|
||||
"what": "a 5 mm deep pocket's rim edges chamfered 5: the legs use the whole walls, ending on the floor's edges, and it builds",
|
||||
"source": "analytic",
|
||||
"method": "plate 60x40x10 with the pocket 30x20x5 (x 15..45, y 10..30, floor z = 5, sharp vertical corners): V0 = 24000 - 3000 = 21000. Each convex rim edge loses the triangle d^2/2 along its length (100 in all); at each pocket corner the two chamfers run on past it and meet in a mitre, the quadrant losing what both remove: points (s, t) past both walls with s + u < d and t + u < d (u the depth), int_0^d (d-u)^2 du = d^3/3: removed = 50 d^2 + (4/3) d^3. d = 5, the walls' full depth (the owner's ruling of 2026-10-30 (d7): a chamfer that reaches or runs past a rim builds): the walls are used up, the chamfers meeting the floor along its edges, so the faces are the plate's 6, the floor and the 4 chamfers: 11. Removed 1416.666667. V = 19583.333333.",
|
||||
"body_count": 1,
|
||||
"volume_mm3": 19583.333333333332,
|
||||
"faces": 11,
|
||||
"bbox": {
|
||||
"min": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"max": [
|
||||
60,
|
||||
40,
|
||||
10
|
||||
]
|
||||
},
|
||||
"continuity": {
|
||||
"order": "g0"
|
||||
}
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"sources": [],
|
||||
"what": "the top rim of a hole through a 10 mm plate chamfered 10: its leg would use the hole's whole wall: refused, naming the largest distance that fits",
|
||||
"source": "invariants",
|
||||
"method": "owner rule: a chamfer whose leg runs off the face beside its edge is refused, and a full-width chamfer stays refused (it would replace the wall and turn the bottom rim into the chamfer's edge, changing the user's geometry). The wall is 10 tall, so every distance below 10 fits; the search names the largest at the request's three significant digits (step 0.01): 9.99.",
|
||||
"outcome": "refused",
|
||||
"refusal": "the largest distance that fits is 9.99 mm"
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"sources": [],
|
||||
"what": "the top rim of a hole through a 10 mm plate chamfered 10: its leg uses the hole's whole wall, ending on the bottom rim, and it builds (a cone from the top to the bottom rim)",
|
||||
"source": "analytic",
|
||||
"method": "plate 40x40x10 with a through hole R5 at (20, 20): V0 = 16000 - 250 pi = 15214.6018. The chamfer's legs are 10 along the top face (to rho = 15, inside the plate's 20 to its sides) and 10 down the wall, its whole height (the owner's ruling of 2026-10-30 (d7): a chamfer that reaches or runs past a rim builds): the triangle 10^2/2 at centroid rho = 5 + 10/3, revolved once (Pappus): 2500 pi / 3 = 2617.9939. V = 16000 - 3250 pi / 3 = 12596.6080. The wall is used up: the faces are the plate's 6 and the cone: 7.",
|
||||
"body_count": 1,
|
||||
"volume_mm3": 12596.607958611057,
|
||||
"faces": 7,
|
||||
"bbox": {
|
||||
"min": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"max": [
|
||||
40,
|
||||
40,
|
||||
10
|
||||
]
|
||||
},
|
||||
"continuity": {
|
||||
"order": "g0"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user