feat: integrate SimpleCADAPI 2.0.2 CAD workflows
This commit is contained in:
@@ -178,7 +178,62 @@ def _semantic_parameter_candidates(
|
||||
)
|
||||
for item in repeated
|
||||
}
|
||||
if len(unique_centers) >= 3:
|
||||
inferred_gear_kind = semantic_summary.get("inferred_gear_kind")
|
||||
inferred_tooth_count = int(
|
||||
semantic_summary.get("inferred_tooth_count", 0)
|
||||
)
|
||||
if inferred_gear_kind and inferred_tooth_count >= 3:
|
||||
transverse_span = max(bbox_size[index] for index in transverse_axes)
|
||||
if inferred_gear_kind == "internal_spur_gear" and coaxial:
|
||||
internal_tip_diameter = 2.0 * min(
|
||||
float(item["radius"]) for item in coaxial
|
||||
)
|
||||
inferred_module = internal_tip_diameter / (
|
||||
inferred_tooth_count - 2.0
|
||||
)
|
||||
else:
|
||||
inferred_module = transverse_span / (
|
||||
inferred_tooth_count + 2.0
|
||||
)
|
||||
candidates.extend(
|
||||
[
|
||||
_parameter_candidate(
|
||||
"tooth_count",
|
||||
inferred_tooth_count,
|
||||
"count",
|
||||
0.9,
|
||||
["equal_angular_tooth_pattern"],
|
||||
"gear_tooth_count_changes",
|
||||
"paired_equal_radius_cylindrical_tooth_flanks",
|
||||
["gear_teeth"],
|
||||
),
|
||||
_parameter_candidate(
|
||||
"gear_module",
|
||||
inferred_module,
|
||||
"mm",
|
||||
0.72,
|
||||
["spur_gear_body"],
|
||||
"gear_pitch_and_tooth_scale_changes",
|
||||
(
|
||||
"internal_tip_diameter_and_tooth_count"
|
||||
if inferred_gear_kind == "internal_spur_gear"
|
||||
else "external_envelope_and_tooth_count"
|
||||
),
|
||||
["module"],
|
||||
),
|
||||
_parameter_candidate(
|
||||
"gear_width",
|
||||
bbox_size[{"x": 0, "y": 1, "z": 2}[dominant_axis]],
|
||||
"mm",
|
||||
0.96,
|
||||
["spur_gear_body"],
|
||||
"gear_axial_width_changes",
|
||||
"dominant_axis_bounding_span",
|
||||
["face_width"],
|
||||
),
|
||||
]
|
||||
)
|
||||
elif len(unique_centers) >= 3:
|
||||
member_radius = float(repeated[0]["radius"])
|
||||
offsets = [
|
||||
math.hypot(
|
||||
@@ -419,6 +474,41 @@ def _semantic_summary(
|
||||
and pattern_spread / pattern_mean_offset <= 0.08
|
||||
)
|
||||
|
||||
# Spur gears exported by common parametric generators often expose two
|
||||
# equal-radius cylindrical flank faces per tooth. Without this guard the
|
||||
# generic repeated-cylinder detector labels those flanks as a bolt-hole
|
||||
# pattern and invents hole_count / bolt_circle_diameter parameters.
|
||||
#
|
||||
# This is intentionally a conservative final-B-Rep classifier. It does
|
||||
# not claim that the source history contained a gear feature.
|
||||
gear_like_surface_mix = bool(
|
||||
has_rotational_stack
|
||||
and has_circular_pattern
|
||||
and len(largest_repeated_group) >= 12
|
||||
and len(largest_repeated_group) % 2 == 0
|
||||
and len(planes) <= 3
|
||||
and not cones
|
||||
and not toruses
|
||||
and not spheres
|
||||
and not other_surfaces
|
||||
and dominant_span / max(transverse_span, 1e-9) <= 0.6
|
||||
)
|
||||
inferred_tooth_count = (
|
||||
len(largest_repeated_group) // 2 if gear_like_surface_mix else 0
|
||||
)
|
||||
centered_radius_ratio = _ratio(
|
||||
smallest_coaxial_radius, transverse_span
|
||||
)
|
||||
inferred_gear_kind = (
|
||||
"internal_spur_gear"
|
||||
if gear_like_surface_mix and centered_radius_ratio >= 0.35
|
||||
else "external_spur_gear"
|
||||
if gear_like_surface_mix
|
||||
else None
|
||||
)
|
||||
if gear_like_surface_mix:
|
||||
has_repeated_axial_holes = False
|
||||
|
||||
# Multiple radii sharing a transverse center are a robust final-B-Rep
|
||||
# signal for stepped bores/counterbores, without claiming operation order.
|
||||
transverse_groups: dict[tuple[int, int, int], set[float]] = defaultdict(set)
|
||||
@@ -479,7 +569,22 @@ def _semantic_summary(
|
||||
if other_surfaces:
|
||||
features.append({"type": "freeform_surface_region"})
|
||||
if has_circular_pattern:
|
||||
features.append({"type": "circular_equal_radius_pattern"})
|
||||
features.append(
|
||||
{
|
||||
"type": (
|
||||
"equal_angular_tooth_pattern"
|
||||
if gear_like_surface_mix
|
||||
else "circular_equal_radius_pattern"
|
||||
)
|
||||
}
|
||||
)
|
||||
if inferred_gear_kind:
|
||||
features.extend(
|
||||
[
|
||||
{"type": "spur_gear_body"},
|
||||
{"type": inferred_gear_kind},
|
||||
]
|
||||
)
|
||||
if has_stepped_cylindrical_passage:
|
||||
features.append({"type": "stepped_cylindrical_passage"})
|
||||
if has_rotational_stack:
|
||||
@@ -515,7 +620,18 @@ def _semantic_summary(
|
||||
)
|
||||
if has_circular_pattern:
|
||||
constraints.append(
|
||||
{"id": "common_pattern_radius", "type": "radial_pattern"}
|
||||
{
|
||||
"id": (
|
||||
"equal_angular_tooth_pattern"
|
||||
if gear_like_surface_mix
|
||||
else "common_pattern_radius"
|
||||
),
|
||||
"type": (
|
||||
"gear_tooth_pattern"
|
||||
if gear_like_surface_mix
|
||||
else "radial_pattern"
|
||||
),
|
||||
}
|
||||
)
|
||||
if has_multi_axis_passages:
|
||||
constraints.append(
|
||||
@@ -526,7 +642,9 @@ def _semantic_summary(
|
||||
{"id": "shared_passage_axis", "type": "coaxial"}
|
||||
)
|
||||
|
||||
if has_rotational_stack and has_repeated_axial_holes:
|
||||
if inferred_gear_kind:
|
||||
family = inferred_gear_kind
|
||||
elif has_rotational_stack and has_repeated_axial_holes:
|
||||
family = "flanged_rotational_part"
|
||||
elif has_rotational_stack and elongated and len(distinct_coaxial_radii) >= 3:
|
||||
family = "hollow_or_stepped_shaft"
|
||||
@@ -622,6 +740,8 @@ def _semantic_summary(
|
||||
else 0,
|
||||
"parallel_cone_surface_count": len(parallel_cones),
|
||||
"has_multi_axis_passages": has_multi_axis_passages,
|
||||
"inferred_gear_kind": inferred_gear_kind,
|
||||
"inferred_tooth_count": inferred_tooth_count,
|
||||
"shape_class": (
|
||||
"elongated" if elongated else "plate_like" if plate_like else "compact"
|
||||
if compact
|
||||
|
||||
Reference in New Issue
Block a user