Merge pull request #1043 from jdegenstein/surface_fill
Some checks failed
benchmarks / benchmarks (macos-13, 3.12) (push) Has been cancelled
benchmarks / benchmarks (macos-14, 3.12) (push) Has been cancelled
benchmarks / benchmarks (ubuntu-latest, 3.12) (push) Has been cancelled
benchmarks / benchmarks (windows-latest, 3.12) (push) Has been cancelled
Upload coverage reports to Codecov / run (push) Has been cancelled
pylint / lint (3.10) (push) Has been cancelled
Run type checker / typecheck (3.10) (push) Has been cancelled
Run type checker / typecheck (3.13) (push) Has been cancelled
Wheel building and publishing / Build wheel on ubuntu-latest (push) Has been cancelled
tests / tests (macos-13, 3.10) (push) Has been cancelled
tests / tests (macos-13, 3.13) (push) Has been cancelled
tests / tests (macos-14, 3.10) (push) Has been cancelled
tests / tests (macos-14, 3.13) (push) Has been cancelled
tests / tests (ubuntu-latest, 3.10) (push) Has been cancelled
tests / tests (ubuntu-latest, 3.13) (push) Has been cancelled
tests / tests (windows-latest, 3.10) (push) Has been cancelled
tests / tests (windows-latest, 3.13) (push) Has been cancelled
Wheel building and publishing / upload_pypi (push) Has been cancelled

Add `Face.make_surface_patch` constrained surface modeling method
This commit is contained in:
Roger Maitland 2025-07-22 10:58:07 -04:00 committed by GitHub
commit e534dd9d44
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 103 additions and 3 deletions

View file

@ -82,7 +82,7 @@ from OCP.BRepPrimAPI import BRepPrimAPI_MakeRevol
from OCP.BRepTools import BRepTools, BRepTools_ReShape
from OCP.gce import gce_MakeLin
from OCP.Geom import Geom_BezierSurface, Geom_RectangularTrimmedSurface, Geom_Surface
from OCP.GeomAbs import GeomAbs_C0
from OCP.GeomAbs import GeomAbs_C0, GeomAbs_G1, GeomAbs_G2
from OCP.GeomAPI import (
GeomAPI_ExtremaCurveCurve,
GeomAPI_PointsToBSplineSurface,
@ -106,7 +106,14 @@ from OCP.TopoDS import TopoDS, TopoDS_Face, TopoDS_Shape, TopoDS_Shell, TopoDS_S
from OCP.TopTools import TopTools_IndexedDataMapOfShapeListOfShape, TopTools_ListOfShape
from typing_extensions import Self
from build123d.build_enums import CenterOf, GeomType, Keep, SortBy, Transition
from build123d.build_enums import (
CenterOf,
ContinuityLevel,
GeomType,
Keep,
SortBy,
Transition,
)
from build123d.geometry import (
DEG2RAD,
TOLERANCE,
@ -1159,6 +1166,42 @@ class Face(Mixin2D, Shape[TopoDS_Face]):
return_value = cls.cast(BRepFill.Face_s(curve1.wrapped, curve2.wrapped))
return return_value
@classmethod
def make_surface_patch(
cls,
edge_face_constraints: (
Iterable[tuple[Edge, Face, ContinuityLevel]] | None
) = None,
edge_constraints: Iterable[Edge] | None = None,
point_constraints: Iterable[VectorLike] | None = None,
) -> Face:
continuity_dict = {
ContinuityLevel.C0: GeomAbs_C0,
ContinuityLevel.C1: GeomAbs_G1,
ContinuityLevel.C2: GeomAbs_G2,
}
patch = BRepOffsetAPI_MakeFilling()
if edge_face_constraints:
for constraint in edge_face_constraints:
patch.Add(
constraint[0].wrapped,
constraint[1].wrapped,
continuity_dict[constraint[2]],
)
if edge_constraints:
for edge in edge_constraints:
patch.Add(edge.wrapped, continuity_dict[ContinuityLevel.C0])
if point_constraints:
for point in point_constraints:
patch.Add(gp_Pnt(*point))
patch.Build()
result = patch.Shape()
return cls(result)
@classmethod
def revolve(
cls,

View file

@ -35,7 +35,7 @@ import unittest
from unittest.mock import patch, PropertyMock
from OCP.Geom import Geom_RectangularTrimmedSurface
from build123d.build_common import Locations, PolarLocations
from build123d.build_enums import Align, CenterOf, GeomType
from build123d.build_enums import Align, CenterOf, ContinuityLevel, GeomType
from build123d.build_line import BuildLine
from build123d.build_part import BuildPart
from build123d.build_sketch import BuildSketch
@ -430,6 +430,63 @@ class TestFace(unittest.TestCase):
with self.assertRaises(ValueError):
Face.sweep(edge, Polyline((0, 0), (0.1, 0), (0.2, 0.1)))
def test_make_surface_patch(self):
m1 = Spline((0, 0), (1, 0), (10, 0, -10))
m2 = Spline((0, 0), (0, 1), (0, 10, -10))
m3 = Spline(m1 @ 1, (7, 7, -10), m2 @ 1)
patch = Face.make_surface_patch(
edge_constraints=[
m1.edge(),
m2.edge(),
m3.edge(),
]
)
self.assertAlmostEqual(patch.area, 157.186, 3)
f1 = Face.extrude(m1.edge(), (0, -1, 0))
f2 = Face.extrude(m2.edge(), (-1, 0, 0))
f3 = Face.extrude(m3.edge(), (0, 0, -1))
patch2 = Face.make_surface_patch(
edge_face_constraints=[
(m1.edge(), f1, ContinuityLevel.C1),
(m2.edge(), f2, ContinuityLevel.C1),
(m3.edge(), f3, ContinuityLevel.C1),
]
)
self.assertAlmostEqual(patch2.area, 152.670, 3)
mid_edge = Spline(m1 @ 0.5, (5, 5, -3), m2 @ 0.5)
patch3 = -Face.make_surface_patch(
edge_face_constraints=[
(m1.edge(), f1, ContinuityLevel.C1),
(m2.edge(), f2, ContinuityLevel.C1),
(m3.edge(), f3, ContinuityLevel.C1),
],
edge_constraints=[
mid_edge.edge(),
],
)
self.assertAlmostEqual(patch3.area, 152.643, 3)
point = patch.position_at(0.5, 0.5) + (0.5, 0.5)
patch4 = -Face.make_surface_patch(
edge_constraints=[
m1.edge(),
m2.edge(),
m3.edge(),
],
point_constraints=[
point,
],
)
self.assertAlmostEqual(patch4.area, 164.618, 3)
# def test_to_arcs(self):
# with BuildSketch() as bs:
# with BuildLine() as bl: