Intersection edge nodes advance along the curve at fine display qualities (#1615)
Thanks @jyviko.
This commit is contained in:
1 parent
61678654c2
commit
f57a62deb7
4 files changed
+1243
-15
No files matched your search
@@ -288,3 +288,27 @@ fn cut_of_a_whole_face_beside_round_corners_after_a_chamfer() {
|
|||||||
let top = mesh.bounds().max.z;
|
let top = mesh.bounds().max.z;
|
||||||
assert!((top - 15.0).abs() < 1e-6, "top at {top}");
|
assert!((top - 15.0).abs() < 1e-6, "top at {top}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The display tessellation of loft bodies joined into a bike frame plans at every display
|
||||||
|
/// quality and every refinement step. The edge nodes on an intersection of two lofts once
|
||||||
|
/// stepped back along the curve (the edge's fit rang where truck's parameter changes speed, and
|
||||||
|
/// took a leader point off the curve past a vertex), so a face's boundary crossed itself and
|
||||||
|
/// the body fell back to the reference mesher, which drew a sheet across the down tube.
|
||||||
|
#[test]
|
||||||
|
fn joined_loft_frames_plan_their_display_at_every_quality() {
|
||||||
|
use solidcraft_doc::display_quality::{DisplayQuality, MAX_REFINE};
|
||||||
|
for (script, name) in [
|
||||||
|
(include_str!("../../../examples/regressions/loft_join_bracket_hull_triangle.json"), "DT2"),
|
||||||
|
(include_str!("../../../examples/regressions/front_triangle_hull_triangle.json"), "FrontTriangle"),
|
||||||
|
] {
|
||||||
|
let s = replay(script);
|
||||||
|
let state = s.model.state();
|
||||||
|
let body = &state.body(name).unwrap().body;
|
||||||
|
for q in DisplayQuality::ALL {
|
||||||
|
for k in 0..=MAX_REFINE {
|
||||||
|
let plan = body.display_plan_angular(q.refined_chord(body.size(), k), q.refined_angle(k));
|
||||||
|
assert!(plan.is_ok(), "{name} at {} + {k}: {:?}", q.id(), plan.err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,8 +5,13 @@
|
|||||||
//! each surface in turn from no starting guess: a nearest-point search per surface per point.
|
//! each surface in turn from no starting guess: a nearest-point search per surface per point.
|
||||||
//! Here the intersection is solved exactly at a set of leader parameters, and a cubic B-spline
|
//! Here the intersection is solved exactly at a set of leader parameters, and a cubic B-spline
|
||||||
//! is fitted through those points together with both surfaces' parameters there (a smooth
|
//! is fitted through those points together with both surfaces' parameters there (a smooth
|
||||||
//! leader with its curves on both surfaces). Each point is then refined from the B-spline by
|
//! leader with its curves on both surfaces). The B-spline runs over the chord length of the
|
||||||
//! Newton's method on the four unknowns (u1, v1, u2, v2): S1(u1, v1) = S2(u2, v2), held on the
|
//! solved points, never over the curve's own parameter: truck's parameter can change speed
|
||||||
|
//! abruptly (a polyline leader with short and long spans), and a cubic interpolated over it
|
||||||
|
//! rings there, stepping back along the curve (Lee, "Choosing nodes in parametric curve
|
||||||
|
//! interpolation", CAD 21, 1989). The curve's parameter reaches the chord length through the
|
||||||
|
//! piecewise-linear map between the seeds, which is monotone. Each point is then refined from
|
||||||
|
//! the B-spline by Newton's method on the four unknowns (u1, v1, u2, v2): S1(u1, v1) = S2(u2, v2), held on the
|
||||||
//! plane through the B-spline point normal to the B-spline (Barnhill & Kersey, "A marching
|
//! plane through the B-spline point normal to the B-spline (Barnhill & Kersey, "A marching
|
||||||
//! method for parametric surface/surface intersection", CAGD 7, 1990; Patrikalakis & Maekawa,
|
//! method for parametric surface/surface intersection", CAGD 7, 1990; Patrikalakis & Maekawa,
|
||||||
//! "Shape Interrogation for CAD/CAM", 2002, ch. 5). Every point is independent once seeded. Where the surfaces are close to
|
//! "Shape Interrogation for CAD/CAM", 2002, ch. 5). Every point is independent once seeded. Where the surfaces are close to
|
||||||
@@ -34,9 +39,11 @@ const MIN_SIN: f64 = 0.05;
|
|||||||
pub(crate) struct Intersection {
|
pub(crate) struct Intersection {
|
||||||
surfaces: [EvalSurface; 2],
|
surfaces: [EvalSurface; 2],
|
||||||
domains: [Domain; 2],
|
domains: [Domain; 2],
|
||||||
/// The smooth leader over the curve's parameter: the intersection point (x, y, z) and both
|
/// The smooth leader over the chord length of the seeds: the intersection point (x, y, z)
|
||||||
/// surfaces' parameters (u1, v1, u2, v2), periodic directions unwrapped along it.
|
/// and both surfaces' parameters (u1, v1, u2, v2), periodic directions unwrapped along it.
|
||||||
leader: CurveN<7>,
|
leader: CurveN<7>,
|
||||||
|
/// The curve's parameter at each seed and the chord length there, both increasing.
|
||||||
|
seeds: Vec<(f64, f64)>,
|
||||||
/// Convergence tolerance (mm).
|
/// Convergence tolerance (mm).
|
||||||
eps: f64,
|
eps: f64,
|
||||||
}
|
}
|
||||||
@@ -59,8 +66,14 @@ impl Intersection {
|
|||||||
// The leader lies within the curve's tolerance of both surfaces.
|
// The leader lies within the curve's tolerance of both surfaces.
|
||||||
let accept = (ic.tolerance() * 100.0).max(1e-6);
|
let accept = (ic.tolerance() * 100.0).max(1e-6);
|
||||||
let scale = (0..=SEEDS).map(|k| leader(t0 + (t1 - t0) * k as f64 / SEEDS as f64).0.len()).fold(1.0, f64::max);
|
let scale = (0..=SEEDS).map(|k| leader(t0 + (t1 - t0) * k as f64 / SEEDS as f64).0.len()).fold(1.0, f64::max);
|
||||||
let mut it = Intersection { surfaces, domains, leader: CurveN { degree: 1, knots: Vec::new(), ctrl: Vec::new() }, eps: scale * 1e-10 };
|
let mut it = Intersection {
|
||||||
let (mut params, mut points) = (Vec::with_capacity(SEEDS + 1), Vec::with_capacity(SEEDS + 1));
|
surfaces,
|
||||||
|
domains,
|
||||||
|
leader: CurveN { degree: 1, knots: Vec::new(), ctrl: Vec::new() },
|
||||||
|
seeds: Vec::new(),
|
||||||
|
eps: scale * 1e-10,
|
||||||
|
};
|
||||||
|
let (mut params, mut points): (Vec<f64>, Vec<[f64; 7]>) = (Vec::with_capacity(SEEDS + 1), Vec::with_capacity(SEEDS + 1));
|
||||||
let mut prev: Option<[f64; 4]> = None;
|
let mut prev: Option<[f64; 4]> = None;
|
||||||
for k in 0..=SEEDS {
|
for k in 0..=SEEDS {
|
||||||
let t = t0 + (t1 - t0) * k as f64 / SEEDS as f64;
|
let t = t0 + (t1 - t0) * k as f64 / SEEDS as f64;
|
||||||
@@ -77,25 +90,60 @@ impl Intersection {
|
|||||||
q[2 * i] = uv[0];
|
q[2 * i] = uv[0];
|
||||||
q[2 * i + 1] = uv[1];
|
q[2 * i + 1] = uv[1];
|
||||||
}
|
}
|
||||||
// Exactly on the intersection where Newton converges (near-tangent seeds keep the
|
// The fit takes only points exactly on the intersection: a leader point Newton
|
||||||
// leader point and its projections).
|
// cannot place (near-tangent, or the solution leaves a surface's domain where a
|
||||||
let (p, q) = d.normalized().and_then(|dir| it.newton(p, dir, q)).unwrap_or((p, q));
|
// polyline leader overshoots a vertex) is off the curve and would bend the fit back
|
||||||
params.push(t);
|
// along it. The ends stay either way, so the fit spans the whole curve.
|
||||||
|
let solved = d.normalized().and_then(|dir| it.newton(p, dir, q));
|
||||||
|
prev = Some(solved.map_or(q, |(_, q)| q));
|
||||||
|
let (p, q) = match solved {
|
||||||
|
Some(x) => x,
|
||||||
|
None if k == 0 || k == SEEDS => (p, q),
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
// A seed that lands on the previous one adds no chord and stays out of the fit
|
||||||
|
// (whose parameters must increase).
|
||||||
|
let s = match it.seeds.last().zip(points.last()) {
|
||||||
|
Some((&(_, s), &[x, y, z, ..])) => {
|
||||||
|
let chord = p.dist(Vec3::new(x, y, z));
|
||||||
|
if !(chord > it.eps) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
s + chord
|
||||||
|
}
|
||||||
|
None => 0.0,
|
||||||
|
};
|
||||||
|
it.seeds.push((t, s));
|
||||||
|
params.push(s);
|
||||||
points.push([p.x, p.y, p.z, q[0], q[1], q[2], q[3]]);
|
points.push([p.x, p.y, p.z, q[0], q[1], q[2], q[3]]);
|
||||||
prev = Some(q);
|
|
||||||
}
|
}
|
||||||
it.leader = CurveN::interpolate(¶ms, &points, 3).ok()?;
|
let degree = points.len().checked_sub(1)?.min(3);
|
||||||
|
it.leader = CurveN::interpolate(¶ms, &points, degree).ok()?;
|
||||||
Some(it)
|
Some(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The point at curve parameter `t` and both surfaces' parameters there, or `None`
|
/// The point at curve parameter `t` and both surfaces' parameters there, or `None`
|
||||||
/// (near-tangent, or Newton failed).
|
/// (near-tangent, or Newton failed).
|
||||||
pub(crate) fn eval(&self, t: f64) -> Option<(Vec3, [f64; 4])> {
|
pub(crate) fn eval(&self, t: f64) -> Option<(Vec3, [f64; 4])> {
|
||||||
let (x, dx) = self.leader.eval(t)?;
|
let (x, dx) = self.leader.eval(self.chord_at(t)?)?;
|
||||||
let dir = Vec3::new(dx[0], dx[1], dx[2]).normalized()?;
|
let dir = Vec3::new(dx[0], dx[1], dx[2]).normalized()?;
|
||||||
self.newton(Vec3::new(x[0], x[1], x[2]), dir, [x[3], x[4], x[5], x[6]])
|
self.newton(Vec3::new(x[0], x[1], x[2]), dir, [x[3], x[4], x[5], x[6]])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The chord length at curve parameter `t`: linear between the seeds, clamped to the ends.
|
||||||
|
fn chord_at(&self, t: f64) -> Option<f64> {
|
||||||
|
let (&(ta, sa), &(tb, sb)) = (self.seeds.first()?, self.seeds.last()?);
|
||||||
|
if !(t > ta) {
|
||||||
|
return Some(sa);
|
||||||
|
}
|
||||||
|
if !(t < tb) {
|
||||||
|
return Some(sb);
|
||||||
|
}
|
||||||
|
let k = self.seeds.partition_point(|&(tk, _)| tk <= t);
|
||||||
|
let (Some(&(t0, s0)), Some(&(t1, s1))) = (<[_]>::get(&self.seeds, k.checked_sub(1)?), <[_]>::get(&self.seeds, k)) else { return None };
|
||||||
|
Some(s0 + (s1 - s0) * (t - t0) / (t1 - t0))
|
||||||
|
}
|
||||||
|
|
||||||
/// The two surfaces, in the order of the parameters [`Intersection::eval`] gives.
|
/// The two surfaces, in the order of the parameters [`Intersection::eval`] gives.
|
||||||
pub(crate) fn surfaces(&self) -> &[EvalSurface; 2] {
|
pub(crate) fn surfaces(&self) -> &[EvalSurface; 2] {
|
||||||
&self.surfaces
|
&self.surfaces
|
||||||
@@ -186,7 +234,7 @@ mod tests {
|
|||||||
|
|
||||||
/// Points on the intersection edges of a boolean (a cross hole: two cylinders) lie on both
|
/// Points on the intersection edges of a boolean (a cross hole: two cylinders) lie on both
|
||||||
/// surfaces, on truck's curve (the parameterisation follows our smooth leader, so the same
|
/// surfaces, on truck's curve (the parameterisation follows our smooth leader, so the same
|
||||||
/// parameter may sit at a slightly different place along it), and advance along the curve.
|
/// parameter may sit at a slightly different place along it), and advance along it.
|
||||||
#[test]
|
#[test]
|
||||||
fn intersection_points_lie_on_both_surfaces_and_on_truck_s_curve() {
|
fn intersection_points_lie_on_both_surfaces_and_on_truck_s_curve() {
|
||||||
let Ok(pin) = crate::cylinder(Vec3::new(5.0, 5.0, -1.0), Vec3::Z, 2.0, 6.0) else { panic!("pin") };
|
let Ok(pin) = crate::cylinder(Vec3::new(5.0, 5.0, -1.0), Vec3::Z, 2.0, 6.0) else { panic!("pin") };
|
||||||
@@ -199,6 +247,21 @@ mod tests {
|
|||||||
let (t0, t1) = curve.range_tuple();
|
let (t0, t1) = curve.range_tuple();
|
||||||
let dense: Vec<Vec3> = (0..=1000).map(|k| from_p3(curve.subs(t0 + (t1 - t0) * f64::from(k) / 1000.0))).collect();
|
let dense: Vec<Vec3> = (0..=1000).map(|k| from_p3(curve.subs(t0 + (t1 - t0) * f64::from(k) / 1000.0))).collect();
|
||||||
let near = |p: Vec3| dense.windows(2).map(|w| p.dist_to_segment(w[0], w[1])).fold(f64::MAX, f64::min);
|
let near = |p: Vec3| dense.windows(2).map(|w| p.dist_to_segment(w[0], w[1])).fold(f64::MAX, f64::min);
|
||||||
|
// Arc length along truck's curve to the point nearest `p`.
|
||||||
|
let along = |p: Vec3| {
|
||||||
|
let (mut run, mut best) = (0.0, (f64::MAX, 0.0));
|
||||||
|
for w in dense.windows(2) {
|
||||||
|
let (a, b) = (w[0], w[1]);
|
||||||
|
let len = a.dist(b);
|
||||||
|
let f = if len > 0.0 { ((p - a).dot(b - a) / (len * len)).clamp(0.0, 1.0) } else { 0.0 };
|
||||||
|
let d = p.dist(a + (b - a) * f);
|
||||||
|
if d < best.0 {
|
||||||
|
best = (d, run + f * len);
|
||||||
|
}
|
||||||
|
run += len;
|
||||||
|
}
|
||||||
|
best.1
|
||||||
|
};
|
||||||
let mut last: Option<Vec3> = None;
|
let mut last: Option<Vec3> = None;
|
||||||
for k in 0..=50 {
|
for k in 0..=50 {
|
||||||
let t = t0 + (t1 - t0) * f64::from(k) / 50.0;
|
let t = t0 + (t1 - t0) * f64::from(k) / 50.0;
|
||||||
@@ -208,7 +271,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
assert!(near(p) < 1e-4, "t {t}: {p:?} is {} from truck's curve", near(p));
|
assert!(near(p) < 1e-4, "t {t}: {p:?} is {} from truck's curve", near(p));
|
||||||
if let Some(q) = last {
|
if let Some(q) = last {
|
||||||
assert!(p.dist(q) > 0.0, "t {t}: the points advance");
|
assert!(along(p) > along(q), "t {t}: the points advance along the curve");
|
||||||
}
|
}
|
||||||
last = Some(p);
|
last = Some(p);
|
||||||
checked += 1;
|
checked += 1;
|
||||||
|
|||||||
@@ -0,0 +1,836 @@
|
|||||||
|
{
|
||||||
|
"description": "Bike front triangle (lofted tubes joined to a bottom-bracket cylinder): the display mesh drew a flat triangle inside the down tube bend at Fine/Ultra.",
|
||||||
|
"commands": [
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
12,
|
||||||
|
0.0,
|
||||||
|
18
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.947,
|
||||||
|
0.0,
|
||||||
|
-0.322
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.ellipse",
|
||||||
|
"params": {
|
||||||
|
"center": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"major": [
|
||||||
|
19.0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"minor_radius": 18.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
-13.0,
|
||||||
|
0.0,
|
||||||
|
91.5
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.947,
|
||||||
|
0.0,
|
||||||
|
-0.322
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.ellipse",
|
||||||
|
"params": {
|
||||||
|
"center": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"major": [
|
||||||
|
27.0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"minor_radius": 24.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
-38,
|
||||||
|
0.0,
|
||||||
|
165
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.959,
|
||||||
|
0.0,
|
||||||
|
-0.282
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S15"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.ellipse",
|
||||||
|
"params": {
|
||||||
|
"center": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"major": [
|
||||||
|
24.0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"minor_radius": 22.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
-76.646,
|
||||||
|
0.0,
|
||||||
|
320.0
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.97,
|
||||||
|
0.0,
|
||||||
|
-0.242
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S16"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.circle.center",
|
||||||
|
"params": {
|
||||||
|
"center": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"radius": 20.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
-110.577,
|
||||||
|
0.0,
|
||||||
|
456.089
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.97,
|
||||||
|
0.0,
|
||||||
|
-0.242
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S17"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.circle.center",
|
||||||
|
"params": {
|
||||||
|
"center": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"radius": 19.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "solid.loft",
|
||||||
|
"params": {
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"sketch": "S13"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S14"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S15"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S16"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S17"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"operation": "new",
|
||||||
|
"name": "SeatTube",
|
||||||
|
"body_name": "SeatTube"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "solid.cylinder",
|
||||||
|
"params": {
|
||||||
|
"diameter": 46,
|
||||||
|
"height": 73.0,
|
||||||
|
"base": [
|
||||||
|
0,
|
||||||
|
-36.5,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"axis": "Y",
|
||||||
|
"operation": "new",
|
||||||
|
"name": "BBShell",
|
||||||
|
"body_name": "BBShell"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
459.471,
|
||||||
|
0.0,
|
||||||
|
607.143
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
0.349,
|
||||||
|
0.0,
|
||||||
|
-0.937
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.ellipse",
|
||||||
|
"params": {
|
||||||
|
"center": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"major": [
|
||||||
|
22.0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"minor_radius": 20.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
181.44,
|
||||||
|
0.0,
|
||||||
|
503.572
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
0.349,
|
||||||
|
0.0,
|
||||||
|
-0.937
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S11"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.ellipse",
|
||||||
|
"params": {
|
||||||
|
"center": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"major": [
|
||||||
|
27.0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"minor_radius": 23.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
-96.592,
|
||||||
|
0.0,
|
||||||
|
400.0
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
0.349,
|
||||||
|
0.0,
|
||||||
|
-0.937
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.ellipse",
|
||||||
|
"params": {
|
||||||
|
"center": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"major": [
|
||||||
|
17.0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"minor_radius": 16.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "solid.loft",
|
||||||
|
"params": {
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"sketch": "S10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S11"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S12"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"operation": "new",
|
||||||
|
"name": "TopTube",
|
||||||
|
"body_name": "TopTube"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
501.231,
|
||||||
|
0.0,
|
||||||
|
519.592
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.903,
|
||||||
|
0.0,
|
||||||
|
-0.431
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.circle.center",
|
||||||
|
"params": {
|
||||||
|
"center": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"radius": 32.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
473.678,
|
||||||
|
0.0,
|
||||||
|
577.358
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.903,
|
||||||
|
0.0,
|
||||||
|
-0.431
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.circle.center",
|
||||||
|
"params": {
|
||||||
|
"center": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"radius": 28.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
447.417,
|
||||||
|
0.0,
|
||||||
|
632.416
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.903,
|
||||||
|
0.0,
|
||||||
|
-0.431
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.circle.center",
|
||||||
|
"params": {
|
||||||
|
"center": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"radius": 26.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "solid.loft",
|
||||||
|
"params": {
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"sketch": "S1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S3"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"operation": "new",
|
||||||
|
"name": "HeadTube",
|
||||||
|
"body_name": "HeadTube"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
8,
|
||||||
|
0.0,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.178,
|
||||||
|
0.0,
|
||||||
|
0.984
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.rectangle.rounded",
|
||||||
|
"params": {
|
||||||
|
"p0": [
|
||||||
|
-19.0,
|
||||||
|
-18.0
|
||||||
|
],
|
||||||
|
"p1": [
|
||||||
|
19.0,
|
||||||
|
18.0
|
||||||
|
],
|
||||||
|
"radius": 10.799999999999999
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
80,
|
||||||
|
0.0,
|
||||||
|
16
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.211,
|
||||||
|
0.0,
|
||||||
|
0.977
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.rectangle.rounded",
|
||||||
|
"params": {
|
||||||
|
"p0": [
|
||||||
|
-30.0,
|
||||||
|
-26.0
|
||||||
|
],
|
||||||
|
"p1": [
|
||||||
|
30.0,
|
||||||
|
26.0
|
||||||
|
],
|
||||||
|
"radius": 15.6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
175,
|
||||||
|
0.0,
|
||||||
|
40
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.596,
|
||||||
|
0.0,
|
||||||
|
0.803
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.rectangle.rounded",
|
||||||
|
"params": {
|
||||||
|
"p0": [
|
||||||
|
-38.0,
|
||||||
|
-33.0
|
||||||
|
],
|
||||||
|
"p1": [
|
||||||
|
38.0,
|
||||||
|
33.0
|
||||||
|
],
|
||||||
|
"radius": 19.8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
314.248,
|
||||||
|
0.0,
|
||||||
|
271.657
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.857,
|
||||||
|
0.0,
|
||||||
|
0.515
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.rectangle.rounded",
|
||||||
|
"params": {
|
||||||
|
"p0": [
|
||||||
|
-37.0,
|
||||||
|
-33.0
|
||||||
|
],
|
||||||
|
"p1": [
|
||||||
|
37.0,
|
||||||
|
33.0
|
||||||
|
],
|
||||||
|
"radius": 19.8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
422.553,
|
||||||
|
0.0,
|
||||||
|
451.835
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.857,
|
||||||
|
0.0,
|
||||||
|
0.515
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.rectangle.rounded",
|
||||||
|
"params": {
|
||||||
|
"p0": [
|
||||||
|
-33.0,
|
||||||
|
-30.0
|
||||||
|
],
|
||||||
|
"p1": [
|
||||||
|
33.0,
|
||||||
|
30.0
|
||||||
|
],
|
||||||
|
"radius": 18.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
484.441,
|
||||||
|
0.0,
|
||||||
|
554.793
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.857,
|
||||||
|
0.0,
|
||||||
|
0.515
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S9"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.rectangle.rounded",
|
||||||
|
"params": {
|
||||||
|
"p0": [
|
||||||
|
-23.0,
|
||||||
|
-22.0
|
||||||
|
],
|
||||||
|
"p1": [
|
||||||
|
23.0,
|
||||||
|
22.0
|
||||||
|
],
|
||||||
|
"radius": 13.2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "solid.loft",
|
||||||
|
"params": {
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"sketch": "S4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S9"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"operation": "new",
|
||||||
|
"name": "DownTube",
|
||||||
|
"body_name": "DownTube"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "solid.combine",
|
||||||
|
"params": {
|
||||||
|
"target": "SeatTube",
|
||||||
|
"tools": [
|
||||||
|
"BBShell"
|
||||||
|
],
|
||||||
|
"operation": "join"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "solid.combine",
|
||||||
|
"params": {
|
||||||
|
"target": "SeatTube",
|
||||||
|
"tools": [
|
||||||
|
"TopTube"
|
||||||
|
],
|
||||||
|
"operation": "join"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "solid.combine",
|
||||||
|
"params": {
|
||||||
|
"target": "SeatTube",
|
||||||
|
"tools": [
|
||||||
|
"HeadTube"
|
||||||
|
],
|
||||||
|
"operation": "join"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "solid.combine",
|
||||||
|
"params": {
|
||||||
|
"target": "SeatTube",
|
||||||
|
"tools": [
|
||||||
|
"DownTube"
|
||||||
|
],
|
||||||
|
"operation": "join"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "body.rename",
|
||||||
|
"params": {
|
||||||
|
"body": "SeatTube",
|
||||||
|
"name": "FrontTriangle"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,305 @@
|
|||||||
|
{
|
||||||
|
"description": "A lofted down tube (rounded-rectangle sections, widest 82 mm) joined to a 46 mm \u00d7 73 mm bottom-bracket cylinder: the display mesh of the tube's side face gained a flat triangle across the inside of its bend.",
|
||||||
|
"commands": [
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
-4,
|
||||||
|
0.0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.164,
|
||||||
|
0.0,
|
||||||
|
0.986
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S4b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.rectangle.rounded",
|
||||||
|
"params": {
|
||||||
|
"p0": [
|
||||||
|
-19.0,
|
||||||
|
-18.0
|
||||||
|
],
|
||||||
|
"p1": [
|
||||||
|
19.0,
|
||||||
|
18.0
|
||||||
|
],
|
||||||
|
"radius": 10.799999999999999
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
80,
|
||||||
|
0.0,
|
||||||
|
16
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.205,
|
||||||
|
0.0,
|
||||||
|
0.979
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S5b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.rectangle.rounded",
|
||||||
|
"params": {
|
||||||
|
"p0": [
|
||||||
|
-41.0,
|
||||||
|
-33.0
|
||||||
|
],
|
||||||
|
"p1": [
|
||||||
|
41.0,
|
||||||
|
33.0
|
||||||
|
],
|
||||||
|
"radius": 19.8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
175,
|
||||||
|
0.0,
|
||||||
|
40
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.596,
|
||||||
|
0.0,
|
||||||
|
0.803
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S6b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.rectangle.rounded",
|
||||||
|
"params": {
|
||||||
|
"p0": [
|
||||||
|
-41.0,
|
||||||
|
-35.0
|
||||||
|
],
|
||||||
|
"p1": [
|
||||||
|
41.0,
|
||||||
|
35.0
|
||||||
|
],
|
||||||
|
"radius": 21.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
314.248,
|
||||||
|
0.0,
|
||||||
|
271.657
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.857,
|
||||||
|
0.0,
|
||||||
|
0.515
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S7b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.rectangle.rounded",
|
||||||
|
"params": {
|
||||||
|
"p0": [
|
||||||
|
-39.0,
|
||||||
|
-35.0
|
||||||
|
],
|
||||||
|
"p1": [
|
||||||
|
39.0,
|
||||||
|
35.0
|
||||||
|
],
|
||||||
|
"radius": 21.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
422.553,
|
||||||
|
0.0,
|
||||||
|
451.835
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.857,
|
||||||
|
0.0,
|
||||||
|
0.515
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S8b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.rectangle.rounded",
|
||||||
|
"params": {
|
||||||
|
"p0": [
|
||||||
|
-35.0,
|
||||||
|
-32.0
|
||||||
|
],
|
||||||
|
"p1": [
|
||||||
|
35.0,
|
||||||
|
32.0
|
||||||
|
],
|
||||||
|
"radius": 19.2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.create",
|
||||||
|
"params": {
|
||||||
|
"plane": {
|
||||||
|
"origin": [
|
||||||
|
484.441,
|
||||||
|
0.0,
|
||||||
|
554.793
|
||||||
|
],
|
||||||
|
"x_dir": [
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"y_dir": [
|
||||||
|
-0.857,
|
||||||
|
0.0,
|
||||||
|
0.515
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "S9b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.rectangle.rounded",
|
||||||
|
"params": {
|
||||||
|
"p0": [
|
||||||
|
-23.0,
|
||||||
|
-22.0
|
||||||
|
],
|
||||||
|
"p1": [
|
||||||
|
23.0,
|
||||||
|
22.0
|
||||||
|
],
|
||||||
|
"radius": 13.2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sketch.finish",
|
||||||
|
"params": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "solid.loft",
|
||||||
|
"params": {
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"sketch": "S4b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S5b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S6b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S7b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S8b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sketch": "S9b"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"operation": "new",
|
||||||
|
"name": "DT2",
|
||||||
|
"body_name": "DT2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "solid.cylinder",
|
||||||
|
"params": {
|
||||||
|
"diameter": 46,
|
||||||
|
"height": 73.0,
|
||||||
|
"base": [
|
||||||
|
0,
|
||||||
|
-36.5,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"axis": "Y",
|
||||||
|
"operation": "new",
|
||||||
|
"name": "BBShell",
|
||||||
|
"body_name": "BBShell"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "solid.combine",
|
||||||
|
"params": {
|
||||||
|
"target": "DT2",
|
||||||
|
"tools": [
|
||||||
|
"BBShell"
|
||||||
|
],
|
||||||
|
"operation": "join"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in new issue
Block a user