Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ffDesign_CounterboreBridges.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,12 @@ def make_upside_down_counterbores(body, hole):
if not Utils.hole_has_counterbore_sure(hole):
Utils.warning_confirm_proceed("Selected Hole does not seem to have a known counterbore type.")

profile_sketch = Utils.get_hole_profile_sketch(hole)
profile_sketch, profile_partial = Utils.get_hole_profile_sketch(hole)

sketch_bridges_y = Utils.make_derived_sketch(body, profile_sketch, "_BridgesY")
sketch_bridges_x = Utils.make_derived_sketch(body, profile_sketch, "_BridgesX")

for hole_loc in Utils.get_sketch_locations(profile_sketch, Utils.get_hole_profile_type(hole)):
for hole_loc in Utils.get_sketch_locations(profile_sketch, Utils.get_hole_profile_type(hole), profile_partial):
# Create parametric y bridges cutout for this circle
make_parametric_y_cutout(
sketch_bridges_y,
Expand Down
4 changes: 2 additions & 2 deletions ffDesign_RibThreads.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ def make_rib_threads(body, hole, global_template: bool, rib_param: RibParameters
Utils.assert_body(body)
Utils.assert_hole(hole)

profile_sketch = Utils.get_hole_profile_sketch(hole)
profile_sketch, profile_partial = Utils.get_hole_profile_sketch(hole)

template = get_or_create_rib_template(body, hole, global_template, rib_param)

Expand All @@ -327,7 +327,7 @@ def make_rib_threads(body, hole, global_template: bool, rib_param: RibParameters

sketch_entrance = Utils.make_derived_sketch(body, profile_sketch, "_ThreadEntrance")

circles = Utils.get_sketch_locations(profile_sketch, Utils.get_hole_profile_type(hole))
circles = Utils.get_sketch_locations(profile_sketch, Utils.get_hole_profile_type(hole), profile_partial)
if len(circles) == 1 and not global_template:
# In the special case of the Hole only having one circle and we have
# generated a local template, we can just move this local template in
Expand Down
4 changes: 2 additions & 2 deletions ffDesign_RoofBridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,13 @@ def make_roof_bridges(
hole.addProperty("App::PropertyLength", "RoofBridgeClearance", group="FusedFilamentDesign")
hole.RoofBridgeClearance = bridge_clearance

profile_sketch = Utils.get_hole_profile_sketch(hole)
profile_sketch, profile_partial = Utils.get_hole_profile_sketch(hole)
roofbridge_sketch = Utils.make_derived_sketch(body, profile_sketch, "_RoofBridge")
roofbridge_sketch_other_side = None
if do_doublesided:
roofbridge_sketch_other_side = Utils.make_derived_sketch(body, profile_sketch, "_RoofBridge2")

hole_locations = Utils.get_sketch_locations(profile_sketch, Utils.get_hole_profile_type(hole))
hole_locations = Utils.get_sketch_locations(profile_sketch, Utils.get_hole_profile_type(hole), profile_partial)
for hole_loc in hole_locations:
make_parametric_roof_bridge(
roofbridge_sketch,
Expand Down
4 changes: 2 additions & 2 deletions ffDesign_Teardrop.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ def make_teardrops(
hole.addProperty("App::PropertyAngle", "TeardropRotation", group="FusedFilamentDesign")
hole.TeardropRotation = rotation

profile_sketch = Utils.get_hole_profile_sketch(hole)
profile_sketch, profile_partial = Utils.get_hole_profile_sketch(hole)
teardrop_sketch = Utils.make_derived_sketch(body, profile_sketch, "_Teardrops")

hole_locations = Utils.get_sketch_locations(profile_sketch, Utils.get_hole_profile_type(hole))
hole_locations = Utils.get_sketch_locations(profile_sketch, Utils.get_hole_profile_type(hole), profile_partial)
for hole_loc in hole_locations:
make_parametric_teardrop(
teardrop_sketch,
Expand Down
18 changes: 18 additions & 0 deletions ffDesign_Tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,24 @@ def test_construction_and_non_defining(self):
self.assert_expected_body()


class PartialHoleProfiles(ffDesignTestCase_Fc11):
test_document = "PartialHoleProfile.FCStd"

@unittest.expectedFailure
def test_plausibility(self):
self.prepare_regression_test()
self.assert_expected_body()

def test_partial_profile(self):
"""
Test that a PartDesign_Hole using a partial sketch as its profile is
correctly handled by the counterbore bridges tool.
"""
self.prepare_regression_test()
ffDesign_CounterboreBridges.CounterboreBridgesCommand().Activated()
self.assert_expected_body()


class RibThreads(ffDesignTestCase):
test_document = "TapHoles.FCStd"

Expand Down
53 changes: 46 additions & 7 deletions ffDesign_Utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,14 @@ def get_hole_profile_sketch(hole):
if profile_sketch.TypeId != "Sketcher::SketchObject":
raise ffDesignError("Hole profile must be a Sketch!")

if hole.Profile[1] != [""]:
raise ffDesignError(
"Only some parts of the sketch are selected as profile for the PartDesign_Hole. This is not supported yet!"
)

return profile_sketch
if hole.Profile[1] in ([""], []):
return (profile_sketch, None)
else:
# Only some edges of the Sketch are selected. We prepare identifying
# information for them so we can later filter for only these
# geometries:
profile_partial = [profile_sketch.Shape.getElementMappedName(edge_name) for edge_name in hole.Profile[1]]
return (profile_sketch, profile_partial)


def make_derived_sketch(body, original, suffix: str):
Expand Down Expand Up @@ -277,14 +279,43 @@ def sketch_external_geo_is_defining(sketch, index):
return None


def profile_partial_contains_geo(sketch, profile_partial, geo_id) -> bool:
if profile_partial is None:
return True

geometry_id = sketch.getGeometryId(geo_id)
ident = f"g{geometry_id}"

for pp in profile_partial:
if ident in pp:
return True

return False


def profile_partial_contains_external_geo(sketch, profile_partial, ext_geo_id) -> bool:
if profile_partial is None:
return True

ext_geo = sketch.ExternalGeo[ext_geo_id]
geometry_id = Sketcher.ExternalGeometryFacade(ext_geo).Id
ident = f"e{geometry_id}"

for pp in profile_partial:
if ident in pp:
return True

return False


@dataclasses.dataclass
class LocationExprSet:
vector_expr: str
x_expr: str
y_expr: str


def get_sketch_locations(sketch, profile_type):
def get_sketch_locations(sketch, profile_type, profile_partial=None):
assert_sketch(sketch)

def try_make_loc_expr_set(index, obj, kind):
Expand Down Expand Up @@ -325,6 +356,10 @@ def try_make_loc_expr_set(index, obj, kind):
if sketch.getConstruction(i):
continue

# If we are filtering for partial selection, check if this geo is included
if not profile_partial_contains_geo(sketch, profile_partial, i):
continue

loc = try_make_loc_expr_set(i, obj, "Geometry")
if loc is not None:
locations.append(loc)
Expand All @@ -334,6 +369,10 @@ def try_make_loc_expr_set(index, obj, kind):
if not sketch_external_geo_is_defining(sketch, i):
continue

# If we are filtering for partial selection, check if this external geo is included
if not profile_partial_contains_external_geo(sketch, profile_partial, i):
continue

loc = try_make_loc_expr_set(i, obj, "ExternalGeo")
if loc is not None:
locations.append(loc)
Expand Down