Products
  • Wolfram|One

    The definitive Wolfram Language and notebook experience

  • Mathematica

    The original technical computing environment

  • System Modeler

    Multidomain modeling and simulation of complex systems

  • Compute ServicesUse with Mathematica and Wolfram|One
  • AI AccessUse with Mathematica and Wolfram|One
  • Finance Platform
  • Wolfram|Alpha Notebook Edition
  • Application Server
  • Enterprise Private Cloud
  • Wolfram Engine
  • Wolfram Player
  • Wolfram Cloud App
  • Wolfram Player App

More mobile apps

Wolfram|Alpha

  • Wolfram|Alpha Website
  • Wolfram|Alpha APIs

AI Products

  • Wolfram AI Ecosystem
  • Wolfram Foundation Tool
  • Wolfram Cloud MCP
  • Wolfram Local MCP
  • Agent One API
  • CAG Component APIs

Core Technologies of Wolfram Products

  • Wolfram Language
  • Computable Data
  • Wolfram Notebooks
  • Linguistic Understanding

Additional Deployment Options

  • Wolfram Cloud
  • Wolfram Web Engine
  • wolframscript
  • WSTPServer
  • Group & Organizational Licensing
  • All Products
Consulting & Solutions

We deliver solutions for the AI era—combining symbolic computation, data-driven insights and deep technical expertise

  • Data & Computational Intelligence
  • Model-Based Design
  • Algorithm Development
  • Wolfram|Alpha for Business
  • Blockchain Technology
  • Education Technology
  • Quantum Computation

Wolfram Consulting

Wolfram Solutions

  • Data Science
  • Artificial Intelligence
  • Biosciences
  • Healthcare Intelligence
  • Sustainable Energy
  • Control Systems
  • Enterprise Wolfram|Alpha
  • Blockchain Labs

More Wolfram Solutions

Wolfram Solutions For Education

  • Research Universities
  • Colleges & Teaching Universities
  • Junior & Community Colleges
  • High Schools
  • Educational Technology
  • Computer-Based Math

More Solutions for Education

  • Contact Us
Learning & Support

Get Started

  • Wolfram Language Introduction
  • Fast Intro for Programmers
  • Fast Intro for Math Students
  • Wolfram Language Documentation

More Learning

  • Highlighted Core Areas
  • Demonstrations
  • YouTube
  • Daily Study Groups
  • Wolfram Schools and Programs
  • Books

Grow Your Skills

  • Wolfram U

    Courses in computing, science, life and more

  • Community

    Learn, solve problems and share ideas.

  • Blog

    News, views and insights from Wolfram

  • Resources for

    Software Developers

Tech Support

  • Contact Us
  • Support FAQs
  • Support FAQs
  • Contact Us
Company
  • About Wolfram
  • Career Center
  • All Sites & Resources
  • Connect & Follow
  • Contact Us

Work with Us

  • Student Ambassador Initiative
  • Wolfram for Startups
  • Student Opportunities
  • Jobs Using Wolfram Language

Educational Programs for Adults

  • Summer School
  • Winter School

Educational Programs for Youth

  • Middle School Camp
  • High School Research Program
  • Computational Adventures

Read

  • Stephen Wolfram's Writings
  • Wolfram Blog
  • Wolfram Tech | Books
  • Wolfram Media
  • Complex Systems

Educational Resources

  • Wolfram MathWorld
  • Wolfram in STEM/STEAM
  • Wolfram Challenges
  • Wolfram Problem Generator

Wolfram Initiatives

  • Wolfram Science
  • Wolfram Foundation
  • History of Mathematics Project

Events

  • Stephen Wolfram Livestreams
  • Online & In-Person Events
  • Contact Us
  • Connect & Follow
For AIs
  • Your Account
  • User Portal
  • Wolfram Cloud
  • Products
    • Wolfram|One
    • Mathematica
    • System Modeler
    • Compute ServicesUse with Mathematica and Wolfram|One
    • AI AccessUse with Mathematica and Wolfram|One
    • Finance Platform
    • Wolfram|Alpha Notebook Edition
    • Application Server
    • Enterprise Private Cloud
    • Wolfram Engine
    • Wolfram Player
    • Wolfram Cloud App
    • Wolfram Player App

    More mobile apps

    • Wolfram|Alpha
      • Wolfram|Alpha Website
      • Wolfram|Alpha APIs
    • AI Products
      • Wolfram AI Ecosystem
      • Wolfram Foundation Tool
      • Wolfram Cloud MCP
      • Wolfram Local MCP
      • Agent One API
      • CAG Component APIs
    • Core Technologies
      • Wolfram Language
      • Computable Data
      • Wolfram Notebooks
      • Linguistic Understanding
    • Additional Deployment Options
      • Wolfram Cloud
      • Wolfram Web Engine
      • wolframscript
      • WSTPServer
    • Group & Organizational Licensing
    • All Products
  • Consulting & Solutions

    We deliver solutions for the AI era—combining symbolic computation, data-driven insights and deep technical expertise

    WolframConsulting.com

    Wolfram Solutions

    • Data Science
    • Artificial Intelligence
    • Biosciences
    • Healthcare Intelligence
    • Sustainable Energy
    • Control Systems
    • Enterprise Wolfram|Alpha
    • Blockchain Labs

    More Wolfram Solutions

    Wolfram Solutions For Education

    • Research Universities
    • Colleges & Teaching Universities
    • Junior & Community Colleges
    • High Schools
    • Educational Technology
    • Computer-Based Math

    More Solutions for Education

    • Contact Us
  • Learning & Support

    Get Started

    • Wolfram Language Introduction
    • Fast Intro for Programmers
    • Fast Intro for Math Students
    • Wolfram Language Documentation

    Grow Your Skills

    • Wolfram U

      Courses in computing, science, life and more

    • Community

      Learn, solve problems and share ideas.

    • Blog

      News, views and insights from Wolfram

    • Resources for

      Software Developers
    • Tech Support
      • Contact Us
      • Support FAQs
    • More Learning
      • Highlighted Core Areas
      • Demonstrations
      • YouTube
      • Daily Study Groups
      • Wolfram Schools and Programs
      • Books
    • Support FAQs
    • Contact Us
  • Company
    • About Wolfram
    • Career Center
    • All Sites & Resources
    • Connect & Follow
    • Contact Us

    Work with Us

    • Student Ambassador Initiative
    • Wolfram for Startups
    • Student Opportunities
    • Jobs Using Wolfram Language

    Educational Programs for Adults

    • Summer School
    • Winter School

    Educational Programs for Youth

    • Middle School Camp
    • High School Research Program
    • Computational Adventures

    Read

    • Stephen Wolfram's Writings
    • Wolfram Blog
    • Wolfram Tech | Books
    • Wolfram Media
    • Complex Systems
    • Educational Resources
      • Wolfram MathWorld
      • Wolfram in STEM/STEAM
      • Wolfram Challenges
      • Wolfram Problem Generator
    • Wolfram Initiatives
      • Wolfram Science
      • Wolfram Foundation
      • History of Mathematics Project
    • Events
      • Stephen Wolfram Livestreams
      • Online & In-Person Events
    • Contact Us
    • Connect & Follow
  • For AIs
  • Wolfram Cloud
  • Your Account
  • User Portal
Wolfram Language & System Documentation Center
Using OpenCascadeLink
  • Tech Notes
    • Element Mesh Generation
    • Element Mesh Visualization
    • Book Shelf Bracket
    • Disc Brake
    • Helical Bevel Gear
    • Permanent Magnet with Coin
    • Surgical Fixation Plate
    • Tech Notes
      • Element Mesh Generation
      • Element Mesh Visualization
      • Book Shelf Bracket
      • Disc Brake
      • Helical Bevel Gear
      • Permanent Magnet with Coin
      • Surgical Fixation Plate
OPEN CASCADE LINK TUTORIAL
  • Tech Notes
    • Element Mesh Generation
    • Element Mesh Visualization
    • Book Shelf Bracket
    • Disc Brake
    • Helical Bevel Gear
    • Permanent Magnet with Coin
    • Surgical Fixation Plate
    • Tech Notes
      • Element Mesh Generation
      • Element Mesh Visualization
      • Book Shelf Bracket
      • Disc Brake
      • Helical Bevel Gear
      • Permanent Magnet with Coin
      • Surgical Fixation Plate

Using OpenCascadeLink

OpenCascade PrimitivesPossible issues
Operations on OpenCascade objectsUtility functions
Import/ExportApplication examples
Units

This section shows some of the ways that OpenCascadeLink can be applied. To use OpenCascadeLink, it must first be loaded.

Wolfram Language code: Needs["OpenCascadeLink`"]

Since many of the OpenCascade examples interact with the finite element mesh functionality the finite element package is also loaded.

Wolfram Language code: Needs["NDSolve`FEM`"]

OpenCascade Primitives

The first step is to create OpenCascade objects. There are several ways of doing this. For 3D objects the options are to:

  • Convert solid graphics 3D primitives
  • Additional OpenCascade 3D primitives
  • Convert surface graphics primitives
  • Convert surface meshes
  • Convert edge graphics primitives
  • Additional OpenCascade edge primitives
    • Create Surfaces from Edges

    Working with 2D graphics primitives the possibility are to:

  • Convert solid graphics 2D primitives
  • Convert boundary graphics primitives

Solid 3D Primitives

Various Wolfram Language Graphics3D primitives can be represented in OpenCascade. These primitives are represented as solids.

Ball

Create two distinct Ball primitives in OpenCascade.
Wolfram Language code: shape1 = OpenCascadeShape[Ball[{1, 0, 0}]] shape2 = OpenCascadeShape[Ball[{0, 1 / 2, 0}, 1 / 2]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape1]
Generate a boundary ElementMesh from the first OpenCascade shape.
Wolfram Language code: bmesh1 = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape1]
Generate a boundary ElementMesh from the second OpenCascade shape.
Wolfram Language code: bmesh2 = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape2]
Visualize the boundary ElementMesh.
Wolfram Language code: Show[bmesh1["Wireframe"], bmesh2["Wireframe"]]
Generate the full ElementMesh.
Wolfram Language code: ToElementMesh[bmesh1] ToElementMesh[bmesh2]
Generate several Ball primitives in OpenCascade.
Wolfram Language code: OpenCascadeShape[Ball[RandomReal[{-1, 1}, {4, 3}]]]

CapsuleShape

Create a CapsuleShape primitive in OpenCascade.
Wolfram Language code: shape = OpenCascadeShape[CapsuleShape[{{0, -2, 0}, {0, 0, 1}}, 1]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]
Visualize the fully meshed ElementMesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]

Cone

Create a Cone primitive in OpenCascade.
Wolfram Language code: shape = OpenCascadeShape[Cone[{{0, 0, 0}, {0, 0, 1}}, 1]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]
Visualize the fully meshed ElementMesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]

Cuboid

Create a Cuboid primitive in OpenCascade.
Wolfram Language code: shape = OpenCascadeShape[Cuboid[{0, 0, 0}, {1, 2, 3}]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]
Visualize the fully meshed ElementMesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]

Cylinder

Create a Cylinder primitive in OpenCascade.
Wolfram Language code: shape = OpenCascadeShape[c1 = Cylinder[{{0, 0, 0}, {1, 2, 3}}, 1 / 2]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Visualize the boundary ElementMesh and the graphics primitive.
Wolfram Language code: Show[bmesh["Wireframe"], Graphics3D[c1]]
Visualize the fully meshed ElementMesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]

Ellipsoid

Create a Ellipsoid primitive in OpenCascade.
Wolfram Language code: shape = OpenCascadeShape[el1 = Ellipsoid[{0, 0, 0}, {{5, 2, 3}, {2, 3, 2}, {3, 2, 5}}]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Visualize the boundary ElementMesh and the graphics primitive.
Wolfram Language code: Show[bmesh["Wireframe"], Graphics3D[el1]]
Visualize the fully meshed ElementMesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]

FilledTorus

Create a FilledTorus primitive in OpenCascade.
Wolfram Language code: shape = OpenCascadeShape[ft = FilledTorus[]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Visualize the boundary ElementMesh and the graphics primitive.
Wolfram Language code: Show[bmesh["Wireframe"], Graphics3D[ft]]
Visualize the fully meshed ElementMesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]

Hexahedron

Create a Hexahedron primitive in OpenCascade.
Wolfram Language code: shape = OpenCascadeShape[Hexahedron[{{0, 0, 0}, {1, 0, 0}, {2, 1, 0}, {1, 1, 0}, {0, 0, 1}, {1, 0, 1}, {2, 1, 1}, {1, 1, 1}}]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]
Visualize the fully meshed ElementMesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]

Parallelepiped

Create a Parallelepiped primitive in OpenCascade.
Wolfram Language code: p = Parallelepiped[{1, 0, 0}, {{1, 0, 0}, {1, 2, 1}, {0, 1, 1}}]; shape = OpenCascadeShape[p]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Extract and visualize the boundary mesh and the Parallelepiped.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]; Show[ Graphics3D[{Opacity[0.25], p}], bmesh["Wireframe"], Boxed -> False]

Prism

Create a Prism primitive in OpenCascade.
Wolfram Language code: shape = OpenCascadeShape[prism = Prism[{{1, 0, 1}, {0, 0, 0}, {2, 0, 0}, {1, 2, 1}, {0, 2, 0}, {2, 2, 0}}]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Visualize the boundary ElementMesh and the graphics primitive.
Wolfram Language code: Show[bmesh["Wireframe"], Graphics3D[prism]]
Visualize the fully meshed ElementMesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]

Polyhedron

Create a Polyhedron primitive in OpenCascade.
Wolfram Language code: polyhedron = Polyhedron[{{-Sqrt[1 + 2/Sqrt[5]], 0, Root[1 - 20*#1^2 + 80*#1^4 & , 3, 0]}, {Sqrt[1 + 2/Sqrt[5]], 0, Root[1 - 20*#1^2 + 80*#1^4 & , 2, 0]}, {Root[1 - 20*#1^2 + 80*#1^4 & , 1, 0], (-3 - Sqrt[5])/4, Root[1 - 20*#1^2 + 80*#1^4 & , 3, 0]}, {R ... }, {11, 12, 8, 16, 7}, {12, 6, 20, 4, 8}, {6, 2, 13, 18, 20}, {2, 5, 19, 17, 13}, {4, 20, 18, 10, 15}, {18, 13, 17, 9, 10}, {17, 19, 3, 14, 9}, {3, 7, 16, 1, 14}, {16, 8, 4, 15, 1}, {22, 23, 24}, {23, 22, 21}, {24, 21, 22}, {21, 24, 23}}]; shape = OpenCascadeShape[polyhedron]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]
Visualize the fully meshed ElementMesh.
Wolfram Language code: ToElementMesh[bmesh, "RegionHoles" -> {{0, 0, 0}}]["Wireframe"["MeshElement" -> "MeshElements", "MeshElementStyle" -> Directive[{FaceForm[Orange], EdgeForm[]}], PlotRange -> {{-1.5, 1.5}, {0, 1.5}, {-1.2, 1.2}}]]
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors, PlotRange -> {{-1.5, 1.5}, {0, 1.5}, {-1.2, 1.2}}]]
Create a Polyhedron primitive in OpenCascade.
Wolfram Language code: r1 = TransformedRegion[Cuboid[], RotationTransform[Pi / 8, {1, 0, 0}]]; r2 = TransformedRegion[Cuboid[], RotationTransform[Pi / 8, {0, 1, 0}]]; polyhedron = RegionUnion[r1, r2]; shape = OpenCascadeShape[polyhedron]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]
Visualize the fully meshed ElementMesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"["MeshElement" -> "MeshElements", "MeshElementStyle" -> Directive[{FaceForm[Orange], EdgeForm[LightGray]}]]]

Pyramid

Create a Pyramid primitive in OpenCascade.
Wolfram Language code: shape = OpenCascadeShape[Pyramid[{{0, 0, 0}, {2, 0, 0}, {2, 2, 0}, {0, 2, 0}, {1, 1, 2}}]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]
Visualize the fully meshed ElementMesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]

SphericalShell

Create a SphericalShell primitive in OpenCascade.
Wolfram Language code: shape = OpenCascadeShape[SphericalShell[]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]
Mesh the region while keeping a region hole. Visualize the fully meshed ElementMesh.
Wolfram Language code: ToElementMesh[bmesh, "RegionHoles" -> {{0, 0, 0}}]["Wireframe"]

Tetrahedron

Create a Tetrahedron primitive in OpenCascade.
Wolfram Language code: shape = OpenCascadeShape[Tetrahedron[{{0, 0, 0}, {1, 0, 0}, {0, 1, 0}, {0, 0, 2}}]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]
Visualize the fully meshed ElementMesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]

Extended Solid 3D Primitives

OpenCascade provides some primitives that do not have a direct correspondence in the Wolfram language.

Torus

Here the arguments are an axis around which the torus is located, a radius from the axis to the interior of the torus and a second radius specifying the the radius of the interior of the torus.

Create a Torus primitive in OpenCascade.
Wolfram Language code: shape = OpenCascadeShape[OpenCascadeTorus[{{0, 0, 0}, {0, 0, 1}}, 3, 1]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Generate a boundary ElementMesh from the first OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]
Generate the full ElementMesh.
Wolfram Language code: ToElementMesh[bmesh]

Partial tori are also possible.

Create and visualize a refined partial Torus primitive in OpenCascade.
Wolfram Language code: shape = OpenCascadeShape[OpenCascadeTorus[{{0, 0, 0}, {0, 0, 1}}, 1, 0.1, π / 3]]; OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape, "ShapeSurfaceMeshOptions" -> {"AngularDeflection" -> 0.25}]["Wireframe"]

Surfaces Primitives

It is also possible to create instances of surface graphics primitives embedded in 3D. These represent face type OpenCascade objects.

BSplineSurface

Set up a pipe section using a B-spline surface with weights:
Wolfram Language code: pts = {{{0.5, 0, -0.5}, {0, 0, -0.5}, {0, 1, -0.5}, {0.5, 1, -0.5}, {1, 1, -0.5}, {1, 0, -0.5}, {0.5, 0, -0.5}}, {{0.5, 0, 0.7}, {0, 0, 0.7}, {0, 1, 0.7}, {0.5, 1, 0.7}, {1, 1, 0.7}, {1, 0, 0.7}, {0.5, 0, 0.7}}, {{0.5, 0, 0.9}, {0, 0, 0.9}, {0, 1, 1.5}, {0.5, 1, 1.5}, {1, 1, 1.5}, {1, 0, 0.9}, {0.5, 0, 0.9}}, {{0.5, -0.1, 1}, {0, -0.1, 1}, {0, 0.5, 2}, {0.5, 0.5, 2}, {1, 0.5, 2}, {1, -0.1, 1}, {0.5, -0.1, 1}}, {{0.5, -0.3, 1}, {0, -0.3, 1}, {0, -0.3, 2}, {0.5, -0.3, 2}, {1, -0.3, 2}, {1, -0.3, 1}, {0.5, -0.3, 1}}, {{0.5, -1.5, 1}, {0, -1.5, 1}, {0, -1.5, 2}, {0.5, -1.5, 2}, {1, -1.5, 2}, {1, -1.5, 1}, {0.5, -1.5, 1}}};w = {{1, .5, .5, 1, .5, .5, 1}, {1, .5, .5, 1, .5, .5, 1}, {1, .5, .5, 1, .5, .5, 1}, {1, .5, .5, 1, .5, .5, 1}, {1, .5, .5, 1, .5, .5, 1}, {1, .5, .5, 1, .5, .5, 1}}; uk = {0, 0, 0, 1 / 4, 1 / 2, 3 / 4, 1, 1, 1}; vk = {0, 0, 0, 1 / 4, 1 / 2, 1 / 2, 3 / 4, 1, 1, 1}; ud = 2; vd = 2; closed = {False, False}; bss = BSplineSurface[pts, SplineKnots -> {uk, vk}, SplineDegree -> {ud, vd}, SplineWeights -> w, SplineClosed -> closed];
Create a BSplineSurface primitive in OpenCascade.
Wolfram Language code: surface = OpenCascadeShape[bss]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[surface]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[surface]
Visualize the boundary ElementMesh with the B-spline surface.
Wolfram Language code: Show[bmesh["Wireframe"], Graphics3D[{Opacity[0.5], bss}]]

A fully meshed ElementMesh can not be created from a non closed surface.

Closed B-splines are supported as long as the knots and weights are set to Automatic.

Set up a pipe section using a closed B-spline surface with weights:
Wolfram Language code: pts = { {{1, -1, 0}, {1, -1, 1}, {0, -1, 1}}, {{1, 0, 0}, {1, 0, 1}, {0, 0, 1}}, {{1, 1, 0}, {1, 1, 1}, {0, 0, 1}}, {{0, 1, 0}, {0, 1, 1}, {0, 0, 1}}, {{-1, 1, 0}, {-1, 1, 1}, {-1, 0, 1}} }; uk = {0, 0, 0, 0, 1, 2, 2, 2, 2}; vk = {0, 0, 0, 1, 1, 1}; w = ConstantArray[1, Most[Dimensions[pts]]]; ud = 3; vd = 2; closed = {False, True}; bss = BSplineSurface[pts, SplineDegree -> {ud, vd}, SplineClosed -> closed];
Create a BSplineSurface primitive in OpenCascade.
Wolfram Language code: surface = OpenCascadeShape[bss]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[surface]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[surface]
Visualize the boundary ElementMesh with the B-spline surface.
Wolfram Language code: Show[bmesh["Wireframe"], Graphics3D[{Opacity[0.5], bss}]]

Disk in 3D

OpenCascade provides some primitives that do not have a direct correspondence in the Wolfram language.

Visualize a disk that has it's center at {0,0,1} and a plane with a normal in direction {0,-1,0}, a radius of 1/2 and an arc length from π to 2 π.
Wolfram Language code: gr = Show[Graphics3D[Disk3D[{{0, 0, 1}, {0, -1, 0}}, 1 / 2, {π, 2π}]], Axes -> True, AxesLabel -> {"X", "Y", "Z"}]
Create a OpenCascadeDisk primitive in OpenCascade.
Wolfram Language code: face = OpenCascadeShape[OpenCascadeDisk[{{0, 0, 1}, {0, -1, 0}}, 1 / 2, {π, 2π}]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[face]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[face]
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]
Show the boundary ElementMesh with the graphics.
Wolfram Language code: Show[gr, bmesh["Wireframe"]]

A fully meshed ElementMesh can not be created from a surface.

Polygon

Create a Polygon primitive in OpenCascade.
Wolfram Language code: face = OpenCascadeShape[Polygon[{{0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 1, 0}}]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[face]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[face]
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]

A fully meshed ElementMesh can not be created from a surface.

Create a Polygon with a hole in OpenCascade.
Wolfram Language code: face = OpenCascadeShape[Polygon[{{0, 0, 0}, {3, 0, 0}, {3, 3, 0}, {0, 3, 0}, {1, 1, 0}, {1, 2, 0}, {2, 2, 0}, {2, 1, 0}}, {1, 2, 3, 4} -> {{5, 6, 7, 8}}]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[face]

A shell is a collection of faces.

Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[face]
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]
Specify a self intersecting Polygon in OpenCascade.
Wolfram Language code: shape = OpenCascadeShape[Polygon[{{0.35, 0.2, 0}, {0.9, 0.75, 0}, {0.1, 0.55, 0}, {0.9, 0.35, 0}, {0.42, 0.9, 0}}]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Surface meshes can not be generated from a self intersecting Polygon.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]

Triangle

Create a Triangle primitive in OpenCascade.
Wolfram Language code: face = OpenCascadeShape[Triangle[{{0, 0, 0}, {1, 0, 0}, {1, 1, 0}}]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[face]
Generate a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[face]
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]

A fully meshed ElementMesh can not be created from a non closed surface.

Surfaces Meshes

ElementMesh

An ElementMesh is the mesh structure used in the wolfram language for finite element analysis. The creation of ElementMesh is documented in the reference pages of ToBoundaryMesh and ToElementMesh or the ElementMesh generation tutorial.

Create and visualize a boundary ElementMesh.
Wolfram Language code: r = ImplicitRegion[-4 y^2 - 4 x y^2 + y^4 + 4 x z^2 + 4 x^2 z^2 + 2 y^2 z^2 + z^4 == 0, {x, y, z}]; bmesh = ToBoundaryMesh[r, {{-1, 1}, {-1, 1}, {-1, 1}}]; bmesh["Wireframe"]
Convert a boundary ElementMesh to an OpenCascade object.
Wolfram Language code: shape = OpenCascadeShape[bmesh]

The conversion is computationally expensive since every surface element is mapped into an OpenCascade object and then sewed together. This type of shape creation should only be used if no other approach can be found.

Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]

Both, open and closed surfaces can be converted.

Create and visualize a boundary ElementMesh.
Wolfram Language code: r = ImplicitRegion[x^6 - 5 x^4 y + 3 x^4 y^2 + 10 x^2 y^3 + 3 x^2 y^4 - y^5 + y^6 + z^2 ≤ 1, {x, y, z}]; bmesh = ToBoundaryMesh[r]; bmesh["Wireframe"]
Convert a boundary ElementMesh to an OpenCascade object.
Wolfram Language code: shape = OpenCascadeShape[bmesh]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]

Edge Primitives

It is also possible to create instances of edge graphics primitives embedded in 3D.

Line

Create a Line primitive in OpenCascade.
Wolfram Language code: wire = OpenCascadeShape[Line[{{0, 1, 0}, {1, 1, 0}, {1.5, 2, 0}, {2, 2, 0}}]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[wire]

A boundary ElementMesh can not be created from an OpenCascade shape of type wire. Wire objects can, however, be used for rotational or linear sweeps or combined with other wire or edge objects.

Combining wires

A collection of wires can be combined into a single wire.

Create several lines.
Wolfram Language code: lines = {Line[{{0, 0, 0}, {1, 0, 0}}], Line[{{1, 0, 0}, {1, 1, 0}}], Line[{{1, 1, 0}, {0, 1, 0}}], Line[{{0, 1, 0}, {0, 0, 0}}]};
Visualize the lines.
Wolfram Language code: Show[Graphics3D[lines], Axes -> True, AxesLabel -> {"X", "Y", "Z"}]
Create several wires.
Wolfram Language code: wires = OpenCascadeShape /@ lines
Combine several wires into a single wire.
Wolfram Language code: wire = OpenCascadeShapeWire[wires]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[wire]

The main usage of this is for convenience.

BezierCurve

Create a BezierCurve.
Wolfram Language code: bcurve = BezierCurve[{{1 / 50, 3 / 500, 0}, {2 / 500, 0, 0}, {1 / 50, -3 / 500, 0}}]
Visualize the BezierCurve.
Wolfram Language code: Graphics3D[bcurve, PlotRange -> {-0.001, 0.001}]
Create a BezierCurve primitive in OpenCascade.
Wolfram Language code: edge = OpenCascadeShape[bcurve]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[edge]

A boundary ElementMesh can not be created from an OpenCascade shape of type wire. Wire objects can, however, be used for rotational or linear sweeps or combined with other wire or edge objects.

Create a Line.
Wolfram Language code: w2 = OpenCascadeShape[Line[{{1 / 50, 3 / 500, 0}, {1 / 50, -3 / 500, 0}}]]
Create an OpenCascade face from the BezierCurve and Line wires.
Wolfram Language code: face = OpenCascadeShapeFace[{wire, w2}]
Visualize the mesh face.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[face] bmesh["Wireframe"]

BSplineCurve

Create a BSplineCurve.
Wolfram Language code: pts = {{0, 0, 0}, {1, 1, 1}, {2, -1, 1}, {3, 0, 2}, {4, 1, 1}}; bsc = BSplineCurve[pts];
Visualize the BSplineCurve.
Wolfram Language code: Graphics3D[{bsc, Green, Line[pts], Red, Point[pts]}]
Create a BSplineCurve primitive in OpenCascade.
Wolfram Language code: edge = OpenCascadeShape[bsc]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[edge]

A boundary ElementMesh can not be created from an OpenCascade shape of type wire. Wire objects can, however, be used for rotational or linear sweeps or combined with other wire or edge objects.

Create and visualize an axis around which we will rotate the BSpline curve.
Wolfram Language code: axis = {{0, 0, 0}, {1, 0, 0}}; gr = Graphics3D[{{Red, Thick, bsc}, {Blue, Arrow[axis]}}]
Create a rotational sweep of the BSplineCurve.
Wolfram Language code: sweep = OpenCascadeShapeRotationalSweep[edge, axis, π / 2]
Visualize the discretized surface and the original BSpline curve.
Wolfram Language code: Show[gr, OpenCascadeShapeSurfaceMeshToBoundaryMesh[sweep]["Wireframe"]]

Extended Edge Primitives

OpenCascade provides some primitives that do not have a direct correspondence in the Wolfram language.

Circle in 3D

Visualize a circle that has it's center at {0,0,1} and a plane with a normal in direction {0,-1,0}, a radius of 1/2 and an arc length from π to 2 π.
Wolfram Language code: Show[Graphics3D[Circle3D[{{0, 0, 1}, {0, -1, 0}}, 1 / 2, {π, 2π}]], Axes -> True, AxesLabel -> {"X", "Y", "Z"}]
Create a OpenCascadeCircle primitive in OpenCascade.
Wolfram Language code: wire = OpenCascadeShape[OpenCascadeCircle[{{0, 0, 1}, {0, -1, 0}}, 1 / 2, {π, 2π}]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[wire]

A boundary ElementMesh can not be created from an OpenCascade shape of type wire. Wire objects can, however, be used for rotational or linear sweeps or combined with other wire or edge objects.

Surfaces from Edges

It's also possible to use wires to construct the boundary of surfaces. There are a few restrictions, however: Wires must not self intersect, the wires must form a closed loop and the surface that is to be formed must be planar.

Create several edge primitives.
Wolfram Language code: edges = {Line[{{0, 0, 0}, {1, 0, 0}}], OpenCascadeCircle[{{1, 1 / 2, 0}, {0, 0, 1}}, 1 / 2, {-π / 2, π / 2}], Line[{{1, 1, 0}, {0, 1, 0}}], Line[{{0, 1, 0}, {0, 0, 0}}]};
Visualize the edges.
Wolfram Language code: Show[Graphics3D[edges /. OpenCascadeCircle -> Circle3D], Axes -> True, AxesLabel -> {"X", "Y", "Z"}]
Create several wires.
Wolfram Language code: wires = OpenCascadeShape /@ edges
Combine several wires into a single wire.
Wolfram Language code: wire = OpenCascadeShapeWire[wires]
Convert the closed wire to a surface.
Wolfram Language code: surface = OpenCascadeShapeFace[wire]
Discretize and visualize the surface.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[surface]; bmesh["Wireframe"]

Solid 2D Primitives

OpenCascade is a 3D CAD engine. With that being said, it is still possible to convert 2D graphics primitives such as Disk, Rectangle etc to OpenCascade shapes. There are two main reasons for doing this:

  • The creation of a region might be simpler in 2D than in 3D
    • Using the OpenCascade engine for 2D boundary element mesh generation

    The fundamental way this works is that 2D embedded objects are created in 3D in the - plane and the -value is assumed 0. Since the shapes created are embedded in 3D OpenCascade operations like extrusion, Boolean operations etc can be applied in the same way as in the rest of the system.

    We start by looking at a workflow.

Workflow

As a first step we illustrate a workflow for both scenarios. Let's start with creating a half disk.

Create a half disk.
Wolfram Language code: i = OpenCascadeShape[Disk[{0, 0}, 1, {0, π}]]
Inspect the shape type.
Wolfram Language code: OpenCascadeShapeType[i]
Convert the OpenCascade shape into a boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[i]

Note that the boundary mesh generated is embedded in 3D and the -extend is 0. The projection of this mesh to 3D will be shown in a minute.

Visualize the boundary mesh.
Wolfram Language code: Show[ OpenCascadeAxis3D[], bmesh["Wireframe"]]

Back to the half disk object. This Object can be projected to any other position by using a transformation function. This works the same way as with other OpenCascade shapes.

Create a transformation function.
Wolfram Language code: tf = RotationTransform[π / 2, {1, 0, 0}]
Apply the transformation function to the OpenCascade shape.
Wolfram Language code: i2 = OpenCascadeShapeTransformation[i, tf]
Visualize the boundary mesh.
Wolfram Language code: Show[ OpenCascadeAxis3D[], OpenCascadeShapeSurfaceMeshToBoundaryMesh[i2]["Wireframe"]]

To create a 2D boundary mesh the function ElementMeshProjection can be used.

Create a half disk, generate a boundary mesh and project the mesh to 2D.
Wolfram Language code: i = OpenCascadeShape[Disk[{0, 0}, 1, {0, π}]]; bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[i]; ElementMeshProjection[bmesh, {#1, #2}&]["Wireframe"]

The boundary mesh refinement works in the standard way. This is described in more detail in the section Surface mesh generation.

Create a half disk, generate a refined boundary mesh and project the mesh to 2D.
Wolfram Language code: i = OpenCascadeShape[Disk[{0, 0}, 1, {0, π}]]; bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[i, "ShapeSurfaceMeshOptions" -> {"AngularDeflection" -> 0.1}]; ElementMeshProjection[bmesh, {#1, #2}&]["Wireframe"]

Note that now the boundary representation is less jagged.

Annulus

Create a 2D Annulus in OpenCascade.
Wolfram Language code: i = OpenCascadeShape[Annulus[{0, 0}, {1, 2}, {0, π}]]
Inspect the shape type.
Wolfram Language code: OpenCascadeShapeType[i]
Visualize the surface mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[i]["Wireframe"]

Disk

Create a 2D Disk in OpenCascade.
Wolfram Language code: i = OpenCascadeShape[Disk[{0, 0}, 1, {0, π}]]
Inspect the shape type.
Wolfram Language code: OpenCascadeShapeType[i]
Visualize the surface mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[i]["Wireframe"]

FilledCurve

FilledCurve is not a region primitive. The main reason this graphics operation is partially supported in OpenCascadeLink is that in current versions of Mathematica there is no way to create a 2D region by connecting 1D segments that are embedded in 2D.

Create a boundary curve of 1D segments embedded in 2D.
Wolfram Language code: curves = {BezierCurve[{{-1, 0}, {0, 1}, {1, 0}}], Line[{{1, 0}, {0, -2 / 3}, {-1, 0}}]}; Graphics[curves]

For graphics FilledCurve can be used to mean the region that is enclosed by the curve.

Create 2D FilledCurve.
Wolfram Language code: fc = FilledCurve[curves]; Graphics[fc]
Create the 2D FilledCurve in OpenCascade.
Wolfram Language code: i = OpenCascadeShape[fc]
Inspect the shape type.
Wolfram Language code: OpenCascadeShapeType[i]
Create and visualize the boundary surface mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[i]["Wireframe"]

The way OpenCascadeLink supports FilledCurve, and JoinedCurve for that matter, is a bit different from what they support in Graphics. For example, a Circle, can not be used as a segment in Graphics but it can be used in OpenCascadeLink.

Create a filled curve with a a Circle segment.
Wolfram Language code: fc = FilledCurve[{Line[{{-1, 0}, {1, 0}}], Circle[{0, 0}, 1, {0, π}]}]
Visualize the graphics filled curve with a helper function.
Wolfram Language code: Graphics[fc /. Circle[data__] :> Sequence@@MeshPrimitives[DiscretizeRegion[Circle[data]], 1]]
Create the OpenCascade shape.
Wolfram Language code: i = OpenCascadeShape[fc]
Inspect the shape type.
Wolfram Language code: OpenCascadeShapeType[i]
Create and visualize the boundary surface mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[i]["Wireframe"]

In the OpenCascadeLink implementation FilledCurve and JoinedCurve must not have missing segments.

Create a filled curve where the segments are not connected.
Wolfram Language code: fc = FilledCurve[{BezierCurve[{{-1, 0}, {0, 1}, {1, 0}}], Line[{{0, -2 / 3}, {-1, 0}}]}]
The conversion to OpenCascade will fail.
Wolfram Language code: i = OpenCascadeShape[fc]

JoinedCurve and FilledCurve options are currently not supported.

Parallelogram/Parallelepiped

Create a 2D Parallelogram in OpenCascade.
Wolfram Language code: i = OpenCascadeShape[Parallelogram[]]
Inspect the shape type.
Wolfram Language code: OpenCascadeShapeType[i]
Visualize the surface mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[i]["Wireframe"]

Polygon

Create a 2D Polygon in OpenCascade.
Wolfram Language code: i = OpenCascadeShape[Polygon[{{1, 0}, {0, Sqrt[3]}, {-1, 0}}]]
Inspect the shape type.
Wolfram Language code: OpenCascadeShapeType[i]
Visualize the surface mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[i]["Wireframe"]

Rectangle

Create a 2D Rectangle in OpenCascade.
Wolfram Language code: i = OpenCascadeShape[Rectangle[]]
Inspect the shape type.
Wolfram Language code: OpenCascadeShapeType[i]
Visualize the surface mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[i]["Wireframe"]

RegularPolygon

Create a 2D RegularPolygon in OpenCascade.
Wolfram Language code: i = OpenCascadeShape[RegularPolygon[{1, 2}, {1 / 2, 0}, 6]]
Inspect the shape type.
Wolfram Language code: OpenCascadeShapeType[i]
Visualize the surface mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[i]["Wireframe"]

Triangle

Create a 2D Triangle in OpenCascade.
Wolfram Language code: i = OpenCascadeShape[Triangle[{{1, 0}, {0, Sqrt[3]}, {-1, 0}}]]
Inspect the shape type.
Wolfram Language code: OpenCascadeShapeType[i]
Visualize the surface mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[i]["Wireframe"]

Example

In this example we show how 2D graphics primitives can be used for creating a boundary element mesh. We would like to create a multi material region with a cutout described by a Bezier curve.

Create graphics primitives.
Wolfram Language code: angle = 2π / 16; r1 = 0.01; r2 = 0.02; offset = 1 / 1000; faces = Disk[{0, 0}, #, {0, angle}]& /@ {r1, r1 + offset, r2}; cut = FilledCurve[{BezierCurve[{{1 / 50, 3 / 500}, {2 / 500, 0}, {1 / 50, -3 / 500}}], Line[{{1 / 50, -3 / 500}, {1 / 50, 3 / 500}}]}];
Visualize the graphics primitives with an empty FaceForm and a black EdgeForm.
Wolfram Language code: Graphics[{Directive[FaceForm[], EdgeForm[Black]], faces, cut}, PlotRange -> {{0, r2}, All}]
Create a union of the Disk faces.
Wolfram Language code: ofs = OpenCascadeShape /@ faces; f1 = OpenCascadeShapeUnion[ofs]
Create the cut shape.
Wolfram Language code: f2 = OpenCascadeShape[cut]
Compute the difference of the region with the cut.
Wolfram Language code: f = OpenCascadeShapeDifference[f1, f2]
Create a refined boundary surface mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[f, "ShapeSurfaceMeshOptions" -> {"AngularDeflection" -> 0.1}]; bmesh["Wireframe"]
Project the 3D surface mesh to a 2D mesh.
Wolfram Language code: mesh2D = ElementMeshProjection[bmesh, {#[[1]], #[[2]]}&]
Visualize the 2D mesh.
Wolfram Language code: mesh2D["Wireframe"]
Create and visualize a 2D boundary mesh.
Wolfram Language code: bmesh2D = ToBoundaryMesh[mesh2D]; bmesh2D["Wireframe"]
Create and visualize a full 2D element mesh, with markers and a refined subregion.
Wolfram Language code: (mesh = ToElementMesh[bmesh2D, "RegionMarker" -> {{{0.005, 0.001}, 1}, {{r1 + offset / 2, 0.00005}, 2, 0.0000001}, {{0.013, 0.004}, 3}}])["Wireframe"]

Boundary 2D Primitives

Just like solid 2D graphics primitives can be converted, as explained in the section Solid 2D Primitives, we can also convert 2D edge or boundary graphics primitives such as Line and Circle.

The fundamental way this works is that 2D embedded objects are created in 3D in the - plane and the -value is assumed 0. Since the shapes created are embedded in 3D OpenCascade operations like extrusion, Boolean operations etc can be applied in the same way as in the rest of the system.

Workflow

As a first step we illustrate a work flow for both scenarios. Let's start with creating a half circle and a line that closes the half circle.

Create a half disk.
Wolfram Language code: i1 = OpenCascadeShape[Circle[{0, 0}, 1, {0, π}]] i2 = OpenCascadeShape[Line[{{-1, 0}, {1, 0}}]]
Inspect the shape types.
Wolfram Language code: OpenCascadeShapeType /@ {i1, i2}

The next step is to connect the wires and create a face from them.

Connect wires and create a face.
Wolfram Language code: wire = OpenCascadeShapeWire[{i1, i2}]; face = OpenCascadeShapeFace[wire]
Inspect the shape type.
Wolfram Language code: OpenCascadeShapeType[face]

The creation of a face from a set of wires can be done in one go.

Connect wires and create a face in one go.
Wolfram Language code: face = OpenCascadeShapeFace[{i1, i2}]
Inspect the shape type.
Wolfram Language code: OpenCascadeShapeType[face]
Convert the OpenCascade shape into a boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[face]

Note that the boundary mesh generated is embedded in 3D and the -extend is 0. The projection of this mesh to 3D will be shown in a minute.

Visualize the boundary mesh.
Wolfram Language code: Show[ OpenCascadeAxis3D[], bmesh["Wireframe"]]

Back to the half circle and line object. This Object can be projected to any other position by using a transformation function. This works the same way as with other OpenCascade shapes.

Create a 2D transformation function.
Wolfram Language code: tf = ReflectionTransform[{0, -1}, {0, 0}]
Apply the transformation function to the OpenCascade shape.
Wolfram Language code: i2 = OpenCascadeShapeTransformation[face, tf]
Visualize the boundary mesh.
Wolfram Language code: Show[ OpenCascadeAxis3D[], OpenCascadeShapeSurfaceMeshToBoundaryMesh[i2]["Wireframe"]]

It is also possible to apply 3D transformations, as the underlying shape expression is embedded in 3D with the axis set to 0.

Create a 3D transformation function.
Wolfram Language code: tf = RotationTransform[π / 2, {1, 0, 0}]
Apply the transformation function to the OpenCascade shape.
Wolfram Language code: i2 = OpenCascadeShapeTransformation[face, tf]
Visualize the boundary mesh.
Wolfram Language code: Show[ OpenCascadeAxis3D[], OpenCascadeShapeSurfaceMeshToBoundaryMesh[i2]["Wireframe"]]

To create a 2D boundary mesh the function ElementMeshProjection can be used.

Generate a boundary mesh and project the mesh to 2D.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[face]; ElementMeshProjection[bmesh, {#[[1]], #[[2]]}&]["Wireframe"]

The boundary mesh refinement works in the standard way. This is described in more detail in the section Surface mesh generation.

Generate a refined boundary mesh and project the mesh to 2D.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[face, "ShapeSurfaceMeshOptions" -> {"AngularDeflection" -> 0.1}]; ElementMeshProjection[bmesh, {#[[1]], #[[2]]}&]["Wireframe"]

Note that now the boundary representation is less jagged. To extract a boundary only ToBoundaryMesh can be applied.

Extract a boundary.
Wolfram Language code: ToBoundaryMesh[ElementMeshProjection[bmesh, {#[[1]], #[[2]]}&]]["Wireframe"]

BezierCurve

Create a BezierCurve.
Wolfram Language code: bc = BezierCurve[{{1, 0}, {2, 1}, {3, 0}, {4, 1}}]; Graphics[bc]
Convert the curve to an OpenCacade shape.
Wolfram Language code: i = OpenCascadeShape[bc]
Inspect the type of the shape.
Wolfram Language code: OpenCascadeShapeType[i]

BSplineCurve

Create a BSplineCurve.
Wolfram Language code: bsc = BSplineCurve[{{1, 0}, {2, 1}, {3, 0}, {4, 1}}]; Graphics[bsc]
Convert the curve to an OpenCacade shape.
Wolfram Language code: i = OpenCascadeShape[bsc]
Inspect the type of the shape.
Wolfram Language code: OpenCascadeShapeType[i]

Circle

Create a Circle.
Wolfram Language code: c = Circle[{0, 0}, 1, {0, π}]; Graphics[c]
Convert the circle to an OpenCacade shape.
Wolfram Language code: i = OpenCascadeShape[c]
Inspect the type of the shape.
Wolfram Language code: OpenCascadeShapeType[i]

JoinedCurve

JoinedCurve is not a region primitive. The main reason this graphics operation is partially supported in OpenCascadeLink is that in current versions of Mathematica there is no way to create a connected region of 1D segments that are embedded in 2D.

Create a boundary curve of 1D segments embedded in 2D.
Wolfram Language code: curves = {BezierCurve[{{-1, 0}, {0, 1}, {1, 0}}], Line[{{1, 0}, {0, -2 / 3}, {-1, 0}}]}; Graphics[curves]

For graphics JoinedCurve can be used to mean the region that is enclosed by the curve.

Create JoinedCurve.
Wolfram Language code: jc = JoinedCurve[curves]; Graphics[jc]
Create the JoinedCurve in OpenCascade.
Wolfram Language code: i = OpenCascadeShape[jc]
Inspect the shape type.
Wolfram Language code: OpenCascadeShapeType[i]

The way OpenCascadeLink supports JoinedCurve, and FilledCurve for that matter, is a bit different from what they support in Graphics. For example, a Circle, can not be used as a segment in Graphics but it can be used in OpenCascadeLink.

Create a joined curve with a a Circle segment.
Wolfram Language code: jc = JoinedCurve[{Line[{{-1, 0}, {1, 0}}], Circle[{0, 0}, 1, {0, π}]}]
Visualize the graphics filled curve with a helper function.
Wolfram Language code: Graphics[jc /. Circle[data__] :> Sequence@@MeshPrimitives[DiscretizeRegion[Circle[data]], 1]]
Create the OpenCascade shape.
Wolfram Language code: i = OpenCascadeShape[jc]
Inspect the shape type.
Wolfram Language code: OpenCascadeShapeType[i]

In the OpenCascadeLink implementation FilledCurve and JoinedCurve must not have missing segments.

Create a joined curve where the segments are not connected.
Wolfram Language code: jc = JoinedCurve[{BezierCurve[{{-1, 0}, {0, 1}, {1, 0}}], Line[{{0, -2 / 3}, {-1, 0}}]}]
The conversion to OpenCascade will fail.
Wolfram Language code: OpenCascadeShape[jc]

JoinedCurve and FilledCurve options are currently not supported.

Line

Create a Line.
Wolfram Language code: l = Line[{{1, 0}, {2, 1}, {3, 0}, {4, 1}}]; Graphics[l]
Convert the circle to an OpenCacade shape.
Wolfram Language code: i = OpenCascadeShape[l]
Inspect the type of the shape.
Wolfram Language code: OpenCascadeShapeType[i]

Operations on OpenCascade objects

The following operations on OpenCascade objects are available:

  • Surface mesh generation
  • Part extraction
  • Geometric transformations
  • Sweeps
  • Boolean operations
  • Shape splitting
  • Shape sewing
  • Internal boundary generation
  • Fillets
  • Chamfers
  • Lofting
  • Shelling
  • De-featuring
  • Shape simplification
  • Shape healing

Surface mesh generation

Surfaces of OpenCascade objects can be meshed.

Generate an OpenCascade object.
Wolfram Language code: shape = OpenCascadeShape[Cone[{{0, 0, 0}, {0, 0, 1}}, 1]]
Generate a surface mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMesh[shape]
Extract and visualize the coordinates from the meshed shape.
Wolfram Language code: c = OpenCascadeShapeSurfaceMeshCoordinates[shape]; Graphics3D[Point[c]]
Extract and visualize the surface elements from the meshed shape.
Wolfram Language code: ele = OpenCascadeShapeSurfaceMeshElements[shape]; Graphics3D[GraphicsComplex[c, Triangle[ele]]]
OpenCascadeShapeSurfaceMesh has the following options:
Wolfram Language code: Options[OpenCascadeShapeSurfaceMesh]

"AngularDeflection" and "LinearDeflection" specify the maximum amount a segment may deviate from the true surface. The concepts are best explained with the following illustration.

"AngularDeflection" specifies the maximum deflection angle α at the end nodes of a segment while "LinearDeflection" specifies the maximum deflection to the true curve within a segment. The Automatic default for the "AngularDeflection" is set to 0.5 degrees and the Automatic default for the "LinearDeflection" is set to 0.01 units of the relative size of the shape. For more information please consult the OpenCascade Documentation.

"ComputeInParallel" specifies if the surface discretization should be performed on multiple CPU cores. The Automatic default is set to False.

"RelativeDeflection" specifies if the deflection is relative or absolute to the size of the geometry. The Automatic default is set to True.

"Rediscretization" specifies if one of the input shapes already as a discretization attached to it if that discretization is to be reused. The Automatic default is set to False. This functionality is useful to have different levels of discretization on different parts in a multi material object. An example is given below in the section Internal boundaries refinement by sewing.

To make working with OpenCascade and the finite element method easier a function to mesh the surface and return a boundary ElementMesh is provided.

Extract a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Visualize the boundary ElementMesh extracted from the OpenCascade shape.
Wolfram Language code: bmesh["Wireframe"]
Note that sub-surfaces have appropriate boundary markers.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> {FaceForm[Green], FaceForm[Red]}]]
Create and visualize a full mesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]
OpenCascadeShapeSurfaceMeshToBoundaryMesh has the following options:
Wolfram Language code: Options[OpenCascadeShapeSurfaceMeshToBoundaryMesh]

All options that are relevant for the ElementMesh generation can be specified via "ElementMeshOptions" and options relevant for OpenCascadeShapeSurfaceMesh can be specified via "ShapeSurfaceMeshOptions".

The "MarkerMethod" option allows to specify if markers should be added and how they should be computed. The default is to use "OpenCascade". Other options are "ElementMesh" and None to switch off markers entirely. Using "ElementMesh" as a "MarkerMethod" option can be useful if the generated surface consists of many single surface elements. In that case the "OpenCascade" method would attribute each element a unique marker which may be undesirable. With the method "ElementMesh", however, the markers are added based on their face normals and if those deviate by a certain amount. The ToBoundaryMesh reference page has more information on this topic.

Extract a boundary ElementMesh from the OpenCascade shape with a refined surface mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape, "ShapeSurfaceMeshOptions" -> {"LinearDeflection" -> 0.001}]
Visualize the boundary ElementMesh extracted from the OpenCascade shape.
Wolfram Language code: bmesh["Wireframe"]

Part extraction

Create a shape.
Wolfram Language code: shape = OpenCascadeShape[Cone[]]
Extract the number of faces.
Wolfram Language code: OpenCascadeShapeNumberOfFaces[shape]
Extract the faces.
Wolfram Language code: faces = OpenCascadeShapeFaces[shape]
Extract the type.
Wolfram Language code: OpenCascadeShapeType /@ faces
Generate a boundary mesh from one of the faces.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[faces[[1]]]["Wireframe"]
Extract the number of vertices.
Wolfram Language code: OpenCascadeShapeNumberOfVertices[shape]
Extract the vertices.
Wolfram Language code: vertices = OpenCascadeShapeVertices[shape]
Extract the type.
Wolfram Language code: OpenCascadeShapeType /@ vertices

Geometric transformations

Create a shape.
Wolfram Language code: shape = OpenCascadeShape[Cone[]]
Rotate the shape.
Wolfram Language code: rshape = OpenCascadeShapeTransformation[shape, RotationTransform[10°, {0, 1, 0}]]
Extract a boundary ElementMesh from the OpenCascade shape.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[rshape]
Visualize the boundary ElementMesh and the shape rotated in the Wolfram language.
Wolfram Language code: Show[bmesh["Wireframe"], Graphics3D[TransformedRegion[Cone[], RotationTransform[10°, {0, 1, 0}]]]]

As an alternative, the TransformationFunction can directly be applied during the creation of the OpenCascade shape by making use of a TransformedRegion.

Create a rotated shape.
Wolfram Language code: rshape = OpenCascadeShape[TransformedRegion[Cone[], RotationTransform[20°, {0, 1, 1}]]]
Extract and visualize the boundary ElementMesh and the shape rotated in the Wolfram language.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[rshape];Show[bmesh["Wireframe"], Graphics3D[TransformedRegion[Cone[], RotationTransform[20°, {0, 1, 1}]]]]

To mirror a shape ReflectionTransform can be used.

Create a mirrored shape.
Wolfram Language code: rt = ReflectionTransform[{0, 0, 1}, {0, 0, 1.1}]; rshape = OpenCascadeShape[TransformedRegion[Cone[], rt]]
Extract and visualize the boundary ElementMesh and the shape rotated in the Wolfram language.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[rshape];Show[bmesh["Wireframe"], Graphics3D[Cone[]] , Graphics3D[GeometricTransformation[{Opacity[.85], Red, Cone[]}, rt]] ]

Sweeps

RotationalSweeps

OpenCascade can perform rotational sweeps. For this a surface is rotated around an axis. The rotation can be less than a full rotation.

Create a polygon face in OpenCascade.
Wolfram Language code: pp = Polygon[{{0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 1, 0}}]; shape = OpenCascadeShape[pp]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Specify a rotation axis and the amount of the rotation.
Wolfram Language code: axis = {{2, 0, 0}, {2, 1, 0}}; sweep = OpenCascadeShapeRotationalSweep[shape, axis, -3π / 2]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[sweep]
Extract and visualize the boundary mesh, the rotation axis of rotation and the polygon face.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[sweep]; Show[Graphics3D[{{Red, pp}, {Blue, Thick, Arrow[axis]}}], bmesh["Wireframe"], Boxed -> False]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]

OpenCascade can also perform rotational sweeps on wire objects.

Create a Line primitive in OpenCascade.
Wolfram Language code: ll = Line[{{0, 1, 0}, {1, 1, 0}, {1.5, 2, 0}, {2, 2, 0}}]; wire = OpenCascadeShape[ll]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[wire]
Specify a rotation axis and the amount of the rotation.
Wolfram Language code: axis = {{0, 0, 0}, {1, 0, 0}}; sweep = OpenCascadeShapeRotationalSweep[wire, axis]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[sweep]
Extract and visualize the boundary mesh, the rotation axis of rotation and the Line edge.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[sweep]; Show[Graphics3D[{{Red, Thickness[0.02], ll}, {Blue, Thick, Arrow[axis]}}], bmesh["Wireframe"], Boxed -> False]

Rotational sweeps can not be performed on Solid or CompoundSolid OpenCascade shape types.

OpenCascade can also perform rotational sweeps on edge objects.

Visualize a Circle in 3D.
Wolfram Language code: gr = {Red, Thickness[0.02], Circle3D[{{0, 0, 1}, {0, -1, 0}}, 1 / 2, {π, 2π}]}; Show[Graphics3D[gr], Axes -> True, AxesLabel -> {"X", "Y", "Z"}]
Create a OpenCascadeCricle primitive in OpenCascade.
Wolfram Language code: wire = OpenCascadeShape[OpenCascadeCircle[{{0, 0, 1}, {0, -1, 0}}, 1 / 2, {π, 2π}]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[wire]
Specify a rotation axis and the amount of the rotation.
Wolfram Language code: axis = {{0, 0, 0}, {1, 0, 0}}; sweep = OpenCascadeShapeRotationalSweep[wire, axis, 3π / 2]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[sweep]
Extract and visualize the boundary mesh, the rotation axis of rotation and the Line edge.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[sweep]; Show[Graphics3D[{gr, {Blue, Thick, Arrow[axis]}}], bmesh["Wireframe"], Axes -> True, AxesLabel -> {"X", "Y", "Z"}]

Rotational sweeps can not be performed on Solid or CompoundSolid OpenCascade shape types.

Possible Issues

Rotational sweeps can not be performed when the axis intersects the shape to be swept and that shape does not have a vertex or edge at the intersection. Consider an example.

Create a Line primitive in OpenCascade.
Wolfram Language code: line = Line[{{-1, 0, 0}, {1, 0, 0}}]; wire = OpenCascadeShape[line]
Create an axis and visualize the line in 3D.
Wolfram Language code: axis = {{0, 0, -1}, {0, 0, 1}}; Graphics3D[{{Red, Thickness[0.02], line}, {Blue, Thick, Arrow[axis]}}, Axes -> True, AxesLabel -> {"X", "Y", "Z"}]
Failure of a sweep.
Wolfram Language code: sweep = OpenCascadeShapeRotationalSweep[wire, axis, π]

One way to fix this failure is to create a shape that has a vertex or edge along which the rotation is supposed to happen.

Insert a vertex at the intersection of the axis and the wire.
Wolfram Language code: line = Line[{{-1, 0, 0}, {0, 0, 0}, {1, 0, 0}}]; wire = OpenCascadeShape[line]; sweep = OpenCascadeShapeRotationalSweep[wire, axis, π]
Visualize the sweep.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[sweep]; bmesh["Wireframe"]

A more general approach, for example for spline curves, is to only model half the shape and perform the sweep for 2π in stead.

Sweep of half the shape around 2 π.
Wolfram Language code: line = Line[{{0, 0, 0}, {1, 0, 0}}]; wire = OpenCascadeShape[line]; sweep = OpenCascadeShapeRotationalSweep[wire, axis, 2π]; bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[sweep]; bmesh["Wireframe"]

Rotational sweeps can not be performed on Solid or CompoundSolid OpenCascade shape types.

LinearSweeps

For a linear sweep of a surface and a direction needs to be give. The surface is then swept to the along this direction.

Create a polygon face in OpenCascade.
Wolfram Language code: pp = Polygon[{{0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 1, 0}}]; shape = OpenCascadeShape[pp]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Sweep the surface along the direction from {1/2,1/2,0} to {1,1,1}.
Wolfram Language code: direction = {{1 / 2, 1 / 2, 0}, {1, 1, 1}}; sweep = OpenCascadeShapeLinearSweep[shape, direction]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[sweep]
Extract and visualize the boundary mesh, the rotation axis of rotation and the polygon face.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[sweep]; Show[Graphics3D[{{Red, pp}, {Blue, Thick, Arrow[direction]}}], bmesh["Wireframe"], Boxed -> False]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]

OpenCascade can also perform linear sweeps on wire objects.

Create a Line primitive in OpenCascade.
Wolfram Language code: ll = Line[{{0, 1, 0}, {1, 1, 0}, {1.5, 2, 0}, {2, 2, 0}}]; wire = OpenCascadeShape[ll]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[wire]
Sweep the surface along the axis {1/2,1/2,0} to {1,1,1}.
Wolfram Language code: axis = {{1 / 2, 1 / 2, 0}, {1, 1, 1}}; sweep = OpenCascadeShapeLinearSweep[wire, axis]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[sweep]
Extract and visualize the boundary mesh, the rotation axis of rotation and the Line edge.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[sweep]; Show[Graphics3D[{{Red, Thickness[0.02], ll}, {Blue, Thick, Arrow[axis]}}], bmesh["Wireframe"], Boxed -> False]

Linear sweeps can not be performed on Solid or ComSolid OpenCascade shape types.

Sweeps along a path

Given a face and a path, OpenCascade can sweep the face along the path.

Create Bezier curve and a polygon:
Wolfram Language code: bcurve = BezierCurve[{{0,0,0},{1,1/2,0},{0,1,0}}]; surface = Polygon[{{0,-l,-l},{0,l,-l},{0,l,l},{0,-l,l}}]/.l->1/8;
Visualize the geometric primitives:
Wolfram Language code: Show[OpenCascadeAxis3D[], Graphics3D[{bcurve, surface}]]
Create the OpenCascade shapes:
Wolfram Language code: path = OpenCascadeShape[bcurve]; face = OpenCascadeShape[surface];

The path has to be either of type "Edge" or of type "Wire" and the surface must not contain a solid or compound.

Inspect the shape types:
Wolfram Language code: OpenCascadeShapeType /@ {face, path}
Create the path sweep:
Wolfram Language code: pathSweep = OpenCascadeShapePathSweep[face, path]
Inspect the shape type of the sweep:
Wolfram Language code: OpenCascadeShapeType[pathSweep]
Create the boundary element mesh:
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[pathSweep]
Visualize the element mesh, the starting face and in red the path:
Wolfram Language code: Show[ bmesh["Wireframe"], Graphics3D[{surface, {Thick, Red, bcurve}}]]

Boolean Operations

Some restrictions in computing Boolean operations are detailed in the Boolean possible issues section and the Boolean operations on solids section.

Boolean operations will always return compound objects.

Difference

Compute geometric differences of shapes.

Generate two Ball shapes.
Wolfram Language code: b1 = Ball[]; b2 = Ball[{1, -1 / 2, 0}, 1 / 2]; shape1 = OpenCascadeShape[b1]; shape2 = OpenCascadeShape[b2];
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType /@ {shape1, shape2}
Compute the geometric difference between the two shapes
Wolfram Language code: difference = OpenCascadeShapeDifference[shape1, shape2]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[difference]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[difference];
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]
Generate a Prism and a Ball Graphics3D primitive.
Wolfram Language code: p1 = Prism[{{1, 0, 1}, {0, 0, 0}, {2, 0, 0}, {1, 2, 1}, {0, 2, 0}, {2, 2, 0}}]; b1 = Ball[{1, 0, -1 / 10}];
Visualize the scene.
Wolfram Language code: Graphics3D[{p1, b1}]
Generate the OpenCascade shape instances.
Wolfram Language code: shape1 = OpenCascadeShape[p1]; shape2 = OpenCascadeShape[b1];
Compute the geometric difference.
Wolfram Language code: difference = OpenCascadeShapeDifference[shape1, shape2]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[difference]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[difference];
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]
Create a SphericalShell and a Cylinder shape.
Wolfram Language code: shape1 = OpenCascadeShape[SphericalShell[]]; shape2 = OpenCascadeShape[Cylinder[{{0, 0, 0}, {1, -2, 3}}, 1 / 2]];
Compute the geometric difference of the shapes
Wolfram Language code: difference = OpenCascadeShapeDifference[shape1, shape2]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[difference];
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]
Create a Polyhedron and a Ball primitive in OpenCascade.
Wolfram Language code: polyhedron = Polyhedron[{{-Sqrt[1 + 2/Sqrt[5]], 0, Root[1 - 20*#1^2 + 80*#1^4 & , 3, 0]}, {Sqrt[1 + 2/Sqrt[5]], 0, Root[1 - 20*#1^2 + 80*#1^4 & , 2, 0]}, {Root[1 - 20*#1^2 + 80*#1^4 & , 1, 0], (-3 - Sqrt[5])/4, Root[1 - 20*#1^2 + 80*#1^4 & , 3, 0]}, {R ... }, {11, 12, 8, 16, 7}, {12, 6, 20, 4, 8}, {6, 2, 13, 18, 20}, {2, 5, 19, 17, 13}, {4, 20, 18, 10, 15}, {18, 13, 17, 9, 10}, {17, 19, 3, 14, 9}, {3, 7, 16, 1, 14}, {16, 8, 4, 15, 1}, {22, 23, 24}, {23, 22, 21}, {24, 21, 22}, {21, 24, 23}}]; shape1 = OpenCascadeShape[polyhedron] shape2 = OpenCascadeShape[Ball[{1, 0, 0}, 1 / 2]]
Compute the geometric difference of the shapes
Wolfram Language code: difference = OpenCascadeShapeDifference[shape1, shape2]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[difference]
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize a cross section through the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors, PlotRange -> {{-1.5, 1.5}, {0, 1.5}, {-1.2, 1.2}}]]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]

Union

Compute geometric unions of shapes.

Generate two Ball shapes.
Wolfram Language code: b1 = Ball[]; b2 = Ball[{1, -1 / 2, 0}, 1 / 2]; shape1 = OpenCascadeShape[b1]; shape2 = OpenCascadeShape[b2];
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType /@ {shape1, shape2}
Compute the geometric union.
Wolfram Language code: union = OpenCascadeShapeUnion[shape1, shape2]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[union]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[union];
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]
Create a Ball and a Hexahedron shape.
Wolfram Language code: shape1 = OpenCascadeShape[Ball[{0, 0, 1}, 1 / 2]]; shape2 = OpenCascadeShape[Hexahedron[{{0, 0, 0}, {1, 0, 0}, {2, 1, 0}, {1, 1, 0}, {0, 0, 1}, {1, 0, 1}, {2, 1, 1}, {1, 1, 1}}]];
Compute the geometric union of the shapes
Wolfram Language code: union = OpenCascadeShapeUnion[shape1, shape2]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[union];
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]
Create a Ball and a Pyramid shape.
Wolfram Language code: shape1 = OpenCascadeShape[Ball[{0, 0, 1}, 1 / 2]]; shape2 = OpenCascadeShape[Pyramid[{{0, 0, 0}, {2, 0, 0}, {2, 2, 0}, {0, 2, 0}, {1, 1, 2}} - 1]];
Compute the geometric union of the shapes
Wolfram Language code: union = OpenCascadeShapeUnion[shape1, shape2]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[union];
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]
Create a SphericalShell and a Cylinder shape.
Wolfram Language code: shape1 = OpenCascadeShape[SphericalShell[]]; shape2 = OpenCascadeShape[Cylinder[{{0, 0, 0}, {1, 2, 3}}, 1 / 2]];
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType /@ {shape1, shape2}
Compute the geometric union of the shapes
Wolfram Language code: union = OpenCascadeShapeUnion[shape1, shape2]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[union]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[union];
Visualize the boundary ElementMesh..
Wolfram Language code: bmesh["Wireframe"]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]

Intersection

Compute geometric intersection of shapes.

Generate two Ball shapes.
Wolfram Language code: b1 = Ball[]; b2 = Ball[{1, -1 / 2, 0}, 1 / 2]; shape1 = OpenCascadeShape[b1]; shape2 = OpenCascadeShape[b2];
Compute the geometric union.
Wolfram Language code: intersection = OpenCascadeShapeIntersection[shape1, shape2]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[intersection];
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]
Create a Ball and a Hexahedron shape.
Wolfram Language code: shape1 = OpenCascadeShape[Ball[{0, 0, 1}, 1 / 2]]; shape2 = OpenCascadeShape[Hexahedron[{{0, 0, 0}, {1, 0, 0}, {2, 1, 0}, {1, 1, 0}, {0, 0, 1}, {1, 0, 1}, {2, 1, 1}, {1, 1, 1}}]];
Compute the geometric intersection of the shapes
Wolfram Language code: intersection = OpenCascadeShapeIntersection[shape1, shape2]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[intersection];
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]
Create a Ball and a Pyramid shape.
Wolfram Language code: shape1 = OpenCascadeShape[Ball[{0, 0, 1}, 1 / 2]]; shape2 = OpenCascadeShape[Pyramid[{{0, 0, 0}, {2, 0, 0}, {2, 2, 0}, {0, 2, 0}, {1, 1, 2}} - 1]];
Compute the geometric intersection of the shapes
Wolfram Language code: intersection = OpenCascadeShapeIntersection[shape1, shape2]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[intersection];
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]
Create a SphericalShell and a Cylinder shape.
Wolfram Language code: shape1 = OpenCascadeShape[SphericalShell[]]; shape2 = OpenCascadeShape[Cylinder[{{0, 0, 0}, {1, 2, 3}}, 1 / 2]];
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType /@ {shape1, shape2}
Compute the geometric intersection of the shapes.
Wolfram Language code: intersection = OpenCascadeShapeIntersection[shape1, shape2]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[intersection]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[intersection];
Visualize the boundary ElementMesh..
Wolfram Language code: bmesh["Wireframe"]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]

Intersections can also be generated from lower dimensional region objects.

Create a Cone and a Polygon shape.
Wolfram Language code: c1 = Cone[{{0, 0, 0}, {0, 0, 1}}, 1]; shape1 = OpenCascadeShape[c1]; shape2 = OpenCascadeShape[Polygon[{{-2, 0, -2}, {2, 0, -2}, {2, 0, 2}, {-2, 0, 2}}]];
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType /@ {shape1, shape2}
Compute the geometric intersection of the shapes.
Wolfram Language code: intersection = OpenCascadeShapeIntersection[shape1, shape2]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[intersection]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[intersection];
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]
Visualize the boundary ElementMesh in the Cone.
Wolfram Language code: Show[bmesh["Wireframe"["MeshElementStyle" -> Directive[FaceForm[Green], EdgeForm[Red]]]], Graphics3D[{Opacity[0.15], c1}], Boxed -> False]

Simplifications of Boolean operations

In some cases the surfaces resulting from Boolean operations can be simplified.

A default union of two cuboids:
Wolfram Language code: c1 = Cuboid[{0, 0, 0}, {1, 1, 1}]; c2 = Cuboid[{1 / 2, 0, 0}, {2, 2, 2}]; u1 = OpenCascadeShapeUnion[OpenCascadeShape /@ {c1, c2}]; OpenCascadeShapeSurfaceMeshToBoundaryMesh[u1]["Wireframe"]
A union of two cuboids with surface simplification:
Wolfram Language code: c1 = Cuboid[{0, 0, 0}, {1, 1, 1}]; c2 = Cuboid[{1 / 2, 0, 0}, {2, 2, 2}]; u1 = OpenCascadeShapeUnion[OpenCascadeShape /@ {c1, c2}, "SimplifyResult" -> True]; OpenCascadeShapeSurfaceMeshToBoundaryMesh[u1]["Wireframe"]

BooleanRegion

The OpenCascadeLink provides functionality to directly work with BooleanRegion objects.

Generate a BooleanRegion shape.
Wolfram Language code: shape = OpenCascadeShapeBooleanRegion[BooleanRegion[Or, {Cuboid[], Ball[{1, 1, 1}]}]]

As a convenience it is also possible to use OpenCascadeShape for BooleanRegion objects directly.

Alternative to generate a BooleanRegion shape.
Wolfram Language code: shape = OpenCascadeShape[BooleanRegion[Or, {Cuboid[], Ball[{1, 1, 1}]}]]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape];
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]
Generate a BooleanRegion shape.
Wolfram Language code: shape = OpenCascadeShape[BooleanRegion[And, {Cuboid[], Ball[{1, 1, 1}]}]]
Extract and visualize the boundary mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Wireframe"]
Generate a BooleanRegion shape.
Wolfram Language code: shape = OpenCascadeShape[BooleanRegion[¬#2∧#1&, {Cuboid[], Ball[{1, 1, 1}]}]]
Extract and visualize the boundary mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Wireframe"]

Boolean operations on solids

OpenCascade handles Boolean operations in a slightly different manner than the Wolfram Language Boolean operators RegionUnion, RegionIntersection and RegionDifference. It's illustrative to walk through several examples.

Solids overlapping
Create two overlapping cubes.
Wolfram Language code: gr1 = Graphics3D[{{Opacity[0.5], c1 = Cuboid[], c2 = Cuboid[{1 / 4, 1 / 4, 1 / 4}]}}, Boxed -> False]
Setup the shapes.
Wolfram Language code: s1=OpenCascadeShape[c1]; s2=OpenCascadeShape[c2];
Intersection
Compute the intersection.
Wolfram Language code: shape = OpenCascadeShapeIntersection[s1, s2];
Visualize the Boolean operation.
Wolfram Language code: Show[gr1, OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Wireframe"["MeshElementStyle" -> {FaceForm[Blue]}]]]
Union
Compute the union.
Wolfram Language code: shape = OpenCascadeShapeUnion[s1, s2];
Visualize the Boolean operation.
Wolfram Language code: Show[gr1, OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Wireframe"["MeshElementStyle" -> {FaceForm[Blue]}]]]
Difference
Compute the first difference.
Wolfram Language code: shape = OpenCascadeShapeDifference[s1, s2];
Visualize the Boolean operation.
Wolfram Language code: Show[gr1, OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Wireframe"["MeshElementStyle" -> {FaceForm[Blue]}]]]
Compute the second difference.
Wolfram Language code: shape = OpenCascadeShapeDifference[s2, s1];
Visualize the Boolean operation.
Wolfram Language code: Show[gr1, OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Wireframe"["MeshElementStyle" -> {FaceForm[Blue]}]]]
Solids touching at a face
Create two touching cubes.
Wolfram Language code: gr1 = Graphics3D[{{Opacity[0.5], c1 = Cuboid[], c2 = Cuboid[{1, 1 / 2, 1 / 2}]}}, Boxed -> False]
Setup the shapes.
Wolfram Language code: s1=OpenCascadeShape[c1]; s2=OpenCascadeShape[c2];
Intersection
Compute the intersection.
Wolfram Language code: shape = OpenCascadeShapeIntersection[s1, s2];

The lowest dimensional object that can be returned from an OpenCascase Boolean operation is that of the minimal dimension of any argument given to the Boolean operation. For example, a Boolean operation of two OpenCascade solids can not return an OpenCascade face object.

Extract the number of faces.
Wolfram Language code: OpenCascadeShapeNumberOfFaces[shape]

Since there are no solids and no faces the conversion to a boundary element mesh will fail.

Converting a shape with no faces or solids will fail.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Union
Compute the union.
Wolfram Language code: shape = OpenCascadeShapeUnion[s1, s2];
Visualize the Boolean operation.
Wolfram Language code: Show[gr1, OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Wireframe"["MeshElementStyle" -> {FaceForm[Blue]}]]]

Note that the resulting full mesh will be open at the touching faces.

Visualize the full mesh and note that the union of the solids is open at the touching faces.
Wolfram Language code: ToElementMesh[OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape], MaxCellMeasure -> 0.005]["Wireframe"]
Difference
Compute the first difference.
Wolfram Language code: shape = OpenCascadeShapeDifference[s1, s2];
Visualize the Boolean operation.
Wolfram Language code: Show[gr1, OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Wireframe"["MeshElementStyle" -> {FaceForm[Blue]}]]]

Note that the resulting solid has it's surface split according to the shape of the touching object.

Visualize the boundary mesh and it's split surface.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Wireframe"["MeshElementStyle" -> {FaceForm[Blue]}]]
Compute the second difference.
Wolfram Language code: shape = OpenCascadeShapeDifference[s2, s1];
Visualize the Boolean operation.
Wolfram Language code: Show[gr1, OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Wireframe"["MeshElementStyle" -> {FaceForm[Blue]}]]]

Note that the resulting solid has it's surface split according to the shape of the touching object.

Solids touching at an edge
Create two touching cubes that touch at an edge.
Wolfram Language code: gr1 = Graphics3D[{{Opacity[0.5], c1 = Cuboid[], c2 = Cuboid[{1, 1, 1 / 2}]}}, Boxed -> False]
Setup the shapes.
Wolfram Language code: s1=OpenCascadeShape[c1]; s2=OpenCascadeShape[c2];
Intersection
Compute the intersection.
Wolfram Language code: shape = OpenCascadeShapeIntersection[s1, s2];

The lowest dimensional object that can be returned from an OpenCascase Boolean operation is that of the minimal dimension of any argument given to the Boolean operation. For example, a Boolean operation of two OpenCascade solids can not return an OpenCascade face object.

Extract the number of edges.
Wolfram Language code: OpenCascadeShapeNumberOfEdges[shape]
Union
Compute the union.
Wolfram Language code: shape = OpenCascadeShapeUnion[s1, s2];
Visualize the Boolean operation.
Wolfram Language code: Show[gr1, OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Wireframe"["MeshElementStyle" -> {FaceForm[Blue]}]]]

Note that the edge of resulting full mesh will be split at the touching edges.

Visualize the full mesh and note that the union of the solids is split at the touching edges.
Wolfram Language code: ToElementMesh[OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape], MaxCellMeasure -> Infinity]["Wireframe"]
Difference
Compute the first difference.
Wolfram Language code: shape = OpenCascadeShapeDifference[s1, s2];
Visualize the Boolean operation.
Wolfram Language code: Show[gr1, OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Wireframe"["MeshElementStyle" -> {FaceForm[Blue]}]]]

Note that the edge of resulting boundary mesh will be split at the touching edges.

Visualize the boundary mesh and it's split surface.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Wireframe"["MeshElementStyle" -> {FaceForm[Blue]}]]
Compute the second difference.
Wolfram Language code: shape = OpenCascadeShapeDifference[s2, s1];
Visualize the Boolean operation.
Wolfram Language code: Show[gr1, OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Wireframe"["MeshElementStyle" -> {FaceForm[Blue]}]]]

Note that the edge of resulting boundary mesh will be split at the touching edges.

Shape splitting

When we have a shape, like a solid, sometimes we want to split that object into several parts. A solid can be split by another solid or by a face. The shape that is to be split is called the object and the shape that does the splitting is called the tool.

Define a shape that is to be split.
Wolfram Language code: r = RegionDifference[Cuboid[{0, 0, 0}, {1, 1, 1}], Cuboid[{0.1, 0.1, 0.1}, {0.9, 0.9, 0.9}]]; shape = OpenCascadeShape[r];
Define a shape that is the splitting tool.
Wolfram Language code: t = Cuboid[{0.5, 0.5, 0.5}, {1.5, 1.5, 1.5}]; tool = OpenCascadeShape[t]
Inspect the object's shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Inspect the tool's shape type.
Wolfram Language code: OpenCascadeShapeType[tool]
Visualize the object and the tool.
Wolfram Language code: Show[ Region[Style[r, Opacity[0.2]]], Graphics3D[{Opacity[0.2], LightRed, t}], OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Edgeframe"], OpenCascadeShapeSurfaceMeshToBoundaryMesh[tool]["Edgeframe"]]
Split the object with the tool.
Wolfram Language code: split = OpenCascadeShapeSplit[shape, tool]

Note that we obtain a list of OpenCascade shape expressions.

Generate boundary meshes from the split object.
Wolfram Language code: bmeshes = OpenCascadeShapeSurfaceMeshToBoundaryMesh /@ split
Visualize the boundary meshes.
Wolfram Language code: #["Wireframe"]& /@ bmeshes
Show the edge frame of the split objects on top of the original object and the tool.
Wolfram Language code: Show[ Region[Style[r, Opacity[0.2]]], Graphics3D[{Opacity[0.2], LightRed, t}], #["Edgeframe"]]& /@ bmeshes
Generate full meshes from the split objects.
Wolfram Language code: ToElementMesh[OpenCascadeShapeSurfaceMeshToBoundaryMesh[#]]["Wireframe"]& /@ split

The tool must no necessarily be an other solid, a face can also be used.

Set up a surface as a splitting tool.
Wolfram Language code: t = Polygon[{{-1, -1, 1 / 2}, {2, -1, 1 / 2}, {2, 2, 1 / 2}, {-1, 2, 1 / 2}}]; tool = OpenCascadeShape[t]
Inspect the shape type of the tool.
Wolfram Language code: OpenCascadeShapeType[tool]
Visualize the shape and the tool.
Wolfram Language code: Show[ Region[Style[r, Opacity[0.2]]], Graphics3D[t], OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Edgeframe"]]
Split the shape with the tool.
Wolfram Language code: split = OpenCascadeShapeSplit[shape, tool]
Visualize the boundary meshes of the split object.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[#]["Wireframe"]& /@ split

A solid can not be split by a wire. Faces can be split by other faces or wires.

Create an object.
Wolfram Language code: r = Polygon[{{0, 0, 1 / 2}, {1, 0, 1 / 2}, {1, 1, 1 / 2}, {0, 1, 1 / 2}}]; shape = OpenCascadeShape[r]
Create a tool.
Wolfram Language code: t = Line[{{-1, 0, 1 / 2}, {1 / 2, 1 / 2, 1 / 2}, {2, 0, 1 / 2}}]; tool = OpenCascadeShape[t]
Inspect the tool's shape type.
Wolfram Language code: OpenCascadeShapeType[tool]
Visualize the object and the tool.
Wolfram Language code: Graphics3D[{r, t}]
Split the shape with the tool.
Wolfram Language code: split = OpenCascadeShapeSplit[shape, tool]
Visualize the boundary meshes of the split object.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[#]["Wireframe"]& /@ split

It's important that the tool has the proper shape type. If an "Edge" type shape tools is given it is automatically converted to a "Wire" tool.

Sewing

Surfaces that share edges can be sewn together. More technically, sewing is the process of stitching topologically disconnected faces into a shell.

Generate a list of polygons.
Wolfram Language code: data = {Polygon[{{0, 1, 0}, {1, 0, 0}, {0, 0, 0}}], Polygon[{{0, 0, 2}, {1, 0, 0}, {0, 0, 0}}], Polygon[{{0, 0, 2}, {0, 1, 0}, {1, 0, 0}}], Polygon[{{0, 0, 2}, {0, 0, 0}, {0, 1, 0}}]};
Create the polygons in OpenCacade.
Wolfram Language code: ocFaces = OpenCascadeShape[#]& /@ data
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType /@ ocFaces
Sew the faces together.
Wolfram Language code: sewenFaces = OpenCascadeShapeSewing[ocFaces]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[sewenFaces]

A shell is a collection of faces. To create a solid either an option can be used during the sewing process or the function OpenCascadeShapeSolid can be used.

Sew the faces together.
Wolfram Language code: sewenFaces = OpenCascadeShapeSewing[ocFaces, "BuildSolid" -> True]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[sewenFaces]
Extract and visualize the boundary ElementMesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[sewenFaces] bmesh["Wireframe"]
Create and visualize a full mesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]

Sewing of B-Spline surfaces with other objects is possible. However, nodes need to match.

Create a PolarPlot.
Wolfram Language code: pp = PolarPlot[1 + 0.5 Sin[2 θ], {θ, 0, 2 π}, MaxRecursion -> 1, PlotPoints -> 45]
Extract the coordinates from the PolarPlot.
Wolfram Language code: coordinates = First[Cases[Normal[pp], Line[l_] :> l, ∞]];
Make use of a function to parameterize the coordinates of the shape.
Wolfram Language code: parametrizeCurve[pts_List, a : (_ ? NumericQ) : 1 / 2] := FoldList[Plus, 0, Normalize[(Norm /@ Differences[pts]) ^ a, Total]] /; MatrixQ[pts, NumericQ] tvals = parametrizeCurve[coordinates, 1];
Construct the BSplineSurface.
Wolfram Language code: bottom = ArrayPad[coordinates,{{0,0},{0,1}},-1.]; top = ArrayPad[coordinates,{{0,0},{0,1}},2.]; knots = Join[{0.,0.},tvals[[2;;-2]],{1.,1.}]; bss = BSplineSurface[Transpose[{bottom,top}],SplineDegree->1,SplineKnots->{knots,{0,0,1,1}}];
Visualize the BSplineSurface and the top and bottom cap.
Wolfram Language code: gr = Graphics3D[{EdgeForm[], Polygon[top], Polygon[bottom], bss}, Boxed -> False]
Construct the surfaces in OpenCascade.
Wolfram Language code: surface = OpenCascadeShape[bss]; p1 = OpenCascadeShape[Polygon[top]]; p2 = OpenCascadeShape[Polygon[bottom]];
Sew the surfaces together.
Wolfram Language code: shape = OpenCascadeShapeSewing[{surface, p1, p2}]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Convert to a solid.
Wolfram Language code: shape = OpenCascadeShapeSolid[shape]; OpenCascadeShapeType[shape]
Extract and visualize the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]; Show[gr, bmesh["Wireframe"], Boxed -> False]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]

As a further example an Ellipsoid is created from 8 BSplineSurface patches.

Create and visualize an Ellipsoid.
Wolfram Language code: center = {0, 1, -1 / 2}; sigma = {{5, 2, 3}, {2, 3, 2}, {3, 2, 5}}; el = Ellipsoid[center, sigma]; gr = Graphics3D[el, Boxed -> False]
Compute the eigenvalues and eigenvectors of the Ellipsoid.
Wolfram Language code: matrix = If[VectorQ[sigma], DiagonalMatrix[sigma ^ 2], sigma]; {vals, vecs} = Eigensystem[N[matrix]];
Compute the TransformationFunction to map a unit Ball onto the Ellipsoid.
Wolfram Language code: composition = Composition[TranslationTransform[center], AffineTransform[Transpose[vecs]], ScalingTransform[Sqrt[vals]]]
Set up the control points for 8 B-Spline surfaces and generate the surfaces.
Wolfram Language code: pts1 = {{{1, 0, 0}, {1, 1, 0}, {0, 1, 0}}, {{1, 0, 1}, {1, 1, 1}, {0, 1, 1}}, {{0, 0, 1}, {0, 0, 1}, {0, 0, 1}}}; pts2 = {{{0, 1, 0}, {-1, 1, 0}, {-1, 0, 0}}, {{0, 1, 1}, {-1, 1, 1}, {-1, 0, 1}}, {{0, 0, 1}, {0, 0, 1}, {0, 0, 1}}}; pts3 = {{{-1, 0, 0}, {-1, -1, 0}, {0, -1, 0}}, {{-1, 0, 1}, {-1, -1, 1}, {0, -1, 1}}, {{0, 0, 1}, {0, 0, 1}, {0, 0, 1}}}; pts4 = {{{0, -1, 0}, {1, -1, 0}, {1, 0, 0}}, {{0, -1, 1}, {1, -1, 1}, {1, 0, 1}}, {{0, 0, 1}, {0, 0, 1}, {0, 0, 1}}}; pts = {pts1, pts2, pts3, pts4, -pts1, -pts2, -pts3, -pts4}; bsss = Table[BSplineSurface[composition /@ d, SplineDegree -> 2, SplineKnots -> {{0, 0, 0, 1, 1, 1}, {0, 0, 0, 1, 1, 1}}, SplineWeights -> {{1, 1 / Sqrt[2], 1}, {1 / Sqrt[2], 1 / 2, 1 / Sqrt[2]}, {1, 1 / Sqrt[2], 1}}], {d, pts}];

Note, here the ordering of the control points is important. The orientation of the resulting surfaces can be fixed with OpenCascadeShapeFix as shown further down.

Convert the B-Spline surfaces into OpenCascade expressions.
Wolfram Language code: bsurfs = OpenCascadeShape /@ bsss
Sew the surfaces together and make the shape a solid.
Wolfram Language code: shape = OpenCascadeShapeSewing[bsurfs, "BuildSolid" -> True]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Extract and visualize the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]; Show[gr, bmesh["Wireframe"], Boxed -> False]

A possible issue is that OpenCascade is sensitive to the ordering of the surfaces given for sewing. This may be tricky to note as a displayed surface might look good but when, for example, Boolean operations are performed on the object unexpected results may happen.

Compute the Boolean union of a the ellipsoid and a cuboid.
Wolfram Language code: cu = OpenCascadeShape[Cuboid[{0, 0, 0}, {2, 2, 2}]]; union = OpenCascadeShapeUnion[cu, shape]; OpenCascadeShapeSurfaceMeshToBoundaryMesh[union]["Wireframe"]

Internal boundaries

OpenCascade offers several ways to include internal boundaries for creating geometric models with multiple materials.

Internal boundaries by union of faces

Forming the union of solids will leave the position of the over lap open.

Create two touching cubes that touch at an edge.
Wolfram Language code: Graphics3D[{{Opacity[0.5], c1 = Cuboid[{0, 0, 0}, {0.5, 1, 1}], c2 = Cuboid[{0.5, 0, 0}, {1, 1, 2}]}}, Boxed -> False]
Create the OpenCascade shapes.
Wolfram Language code: shape1 = OpenCascadeShape[c1]; shape2 = OpenCascadeShape[c2];
Form the union and visualize the full mesh.
Wolfram Language code: union = OpenCascadeShapeUnion [shape1, shape2]; bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[union]; ToElementMesh[bmesh, MaxCellMeasure -> 0.01]["Wireframe"]

Note that at the overlap where the two cuboids touched the union is not closed. This may be undesirable if one is working with a multiple material region. One option to close the face at the overlap is to compute the union of all faces of the solids.

Extract all faces from the solids and compute the union of the faces.
Wolfram Language code: faces1 = OpenCascadeShapeFaces[shape1]; faces2 = OpenCascadeShapeFaces[shape2]; union = OpenCascadeShapeUnion[Flatten[{faces1, faces2}]]
Visualize the full mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[union]; ToElementMesh[bmesh, MaxCellMeasure -> 0.01]["Wireframe"]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[union]; ToElementMesh[bmesh]["Wireframe"]

Note that now an interface exists between the two solids.

Internal boundaries by sewing

Shape sewing can also be used to generate shapes that have internal boundaries.

Generate two shapes.
Wolfram Language code: shape1 = OpenCascadeShape[Cuboid[{-2, -2, -2}, {2, 2, 1 / 2}]]; shape2 = OpenCascadeShape[Cylinder[]];
Compute the geometric union between the two shapes.
Wolfram Language code: union = OpenCascadeShapeUnion [shape1, shape2]
Visualize the resulting union.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[union]["Wireframe"]
Compute the geometric intersection between the two shapes.
Wolfram Language code: intersection = OpenCascadeShapeIntersection [shape1, shape2]
Visualize the resulting intersection.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[intersection]["Wireframe"]

Note that computing the intersection returns a closed shape.

Sew the faces together.
Wolfram Language code: shape = OpenCascadeShapeSewing[{union, intersection}]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape];
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors, PlotRange -> {All, {-1, 2}, All}]]

Since the intersection of the two shapes is closed by sewing that closed shape into the union of the shapes we have three internal regions. One in the cylinder on top of the cuboid, one in the cylinder that is inside the cuboid and one in the remaining cuboid.

Generate a full mesh.
Wolfram Language code: mesh = ToElementMesh[bmesh, "RegionMarker" -> {{{-1, -1, -1}, 1}, {{0, 0, 3 / 4}, 2}, {{0, 0, 1 / 4}, 3}}]
Check that all markers are present.
Wolfram Language code: mesh["MeshElementMarkerUnion"]
Visualize the parts specified by the markers.
Wolfram Language code: parts = Map[mesh["Wireframe"[ElementMarker == #[[1]], "MeshElement" -> "MeshElements", "ElementMeshDirective" -> Directive[EdgeForm[], FaceForm[#[[2]]]]]]&, {{1, Gray}, {2, Pink}, {3, Orange}}]
Visualize a cross section through the mesh with markers highlighted.
Wolfram Language code: Rasterize[Show[parts, PlotRange -> {All, {-0.02, 2}, All}]]

Internal boundaries refinement by sewing

Sometimes it is desirable to have different internal boundaries discretized at different resolutions. This can be achieved by discretizing the respective boundaries to a desired level and then sew them together.

Create symbolic regions:
Wolfram Language code: cylinder = Cylinder[{{0, 0, 3.097}, {0, 0, 3.097 + 6}}, 3]; cuboid1 = Cuboid[{-10, -10, -10}, {10, 10, 10}]; cuboid2 = Cuboid[{-5, -5, -2}, {5, 5, 2}];
Convert the symbolic regions to OpenCascade and sew them together:
Wolfram Language code: cylinderShape = OpenCascadeShape[cylinder]; cuboid1Shape = OpenCascadeShape[cuboid1]; cuboid2Shape = OpenCascadeShape[cuboid2]; shape = OpenCascadeShapeSewing[{cylinderShape, cuboid1Shape, cuboid1Shape}]
Discretize the boundary and visualize the discretization:
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]; bmesh["Wireframe"]

Now, what if you want to refine the inner cylinder and not the boundary of the cuboids? Changing the linear or angular deflection during on the sewn object is going to affect all boundaries. To still change the discretization of a single shape in the object it is possible to surface mesh that object and retain that discretization during the sewing.

Discretize the cylinder:
Wolfram Language code: OpenCascadeShapeSurfaceMesh[cylinderShape, "LinearDeflection" -> 0.00125]

Note, that the discretization is attached to the OpenCascadeShapeExpression.

Sew the shapes together:
Wolfram Language code: shape = OpenCascadeShapeSewing[{cylinderShape, cuboid1Shape, cuboid2Shape}]

To make use of previous boundary discretizations attached to an OpenCascadeShapeExpression the OpenCascadeShapeSurfaceMeshToBoundaryMesh needs the option "Rediscretization"False to make use of those previous discretizations if available.

Create the boundary ElementMesh by not re-discretizeing if shapes already have a boundary discretization attached:
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape, "ShapeSurfaceMeshOptions" -> {"Rediscretization" -> False}]; bmesh["Wireframe"]

Now, the inner cylinder is discretized at a different level then the remaining boundaries.

Fillets

OpenCascade provides functionality to fillet shapes.

Generate a shape.
Wolfram Language code: shape = OpenCascadeShape[Cuboid[{0, 0, 0}, {1, 2, 3}]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Fillet all edges with a radius of 0.25.
Wolfram Language code: fillet = OpenCascadeShapeFillet[shape, 0.25]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[fillet]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[fillet]
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]
Generate a full mesh.
Wolfram Language code: ToElementMesh[bmesh]["Wireframe"]

It is also possible to fillet only selected edges.

Generate a shape.
Wolfram Language code: shape = OpenCascadeShape[Cuboid[{0, 0, 0}, {1, 2, 3}]]
Look at the number of edges in the shape.
Wolfram Language code: OpenCascadeShapeNumberOfEdges[shape]

In OpenCascade every face has access to all the edges the face is comprised of. In the case of the cube each face is connected to 4 edges. Since there are 6 faces this makes a total of 24 edges that can be addressed of which 12 are duplicated.

Fillet edges number 1 and 7 with a radius of 0.25.
Wolfram Language code: fillet = OpenCascadeShapeFillet[shape, 0.25, {1, 7}]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[fillet]
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]

Sometimes it is convenient to walk through all edges and see the effect a filleting has on the overall shape, or one needs to find the edge one wants to fillet. For this purpose there is a helper function called VisualizeEdgeFunction defined in the appendix that does that.

Interactively apply the filleting function to edges of the shape.
Wolfram Language code: VisualizeEdgeFunction[Cuboid[{0, 0, 0}, {1, 2, 3}], OpenCascadeShapeFillet[#1, 0.25, #2]&]
Generate a shape.
Wolfram Language code: face = OpenCascadeShape[Polygon[{{0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 1, 0}}]]; sweep = OpenCascadeShapeRotationalSweep[face, {{2, 0, 0}, {2, 1, 0}}, -3π / 2]; shape1 = OpenCascadeShape[Cylinder[{{1, -1, 0}, {1, 1, 0}}, 1 / 2]]; shape = OpenCascadeShapeUnion[sweep, shape1]
Fillet the shape with a radius of 0.125.
Wolfram Language code: fillet = OpenCascadeShapeFillet[shape, 0.125]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[fillet]
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> Directive[FaceForm[LightBlue], EdgeForm[]]]]

If the requested fillet radius is too large then the filleting will fail.

Wolfram Language code: shape = OpenCascadeShape[Cylinder[{{1, -1, 0}, {1, 1, 0}}, 1 / 2]]
Filleting a shape with too large a radius will fail.
Wolfram Language code: fillet = OpenCascadeShapeFillet[shape, 1]
Use a radius that can be filleted.
Wolfram Language code: fillet = OpenCascadeShapeFillet[shape, 0.025]
Extract the boundary mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[fillet]["Wireframe"]

Chamfers

Chamfers are similar to fillets. The difference is that chamfers are not rounded but planes. The chamfers created are symmetric and the function's parameter specifies the distance tangential to which the chamfer surface will be created.

Generate a shape.
Wolfram Language code: shape = OpenCascadeShape[Cuboid[{0, 0, 0}, {1, 2, 3}]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Apply chamfer to edges 5 and 6.
Wolfram Language code: chamfer = OpenCascadeShapeChamfer[shape, 0.25, {5, 6}]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[chamfer]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[chamfer]
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]
Generate the full mesh.
Wolfram Language code: ToElementMesh[bmesh]

Sometimes it is convenient to walk through all edges and see the effect a chamfer has on the overall shape, or one needs to find the edge one wants to chamfer. For this purpose there is a helper function called VisualizeEdgeFunction defined in the appendix that does that.

Interactively apply the chamfer function to edges of the shape.
Wolfram Language code: VisualizeEdgeFunction[Cuboid[{0, 0, 0}, {1, 2, 3}], OpenCascadeShapeChamfer[#1, 0.25, #2]&]

Lofting

A loft surface or solid is generated by creating surfaces that pass through wires. The concept is easily understood once a visualization has explained it.

Create and visualize a set of Line objects.
Wolfram Language code: w1 = Line[{{0, 0, 0}, {1, 0, 0}, {0, 1, 0}, {0, 0, 0}}]; w2 = OpenCascadeCircle[{{1 / 2, 1 / 2, 1}, {0, 0, 1}}, 1 / 4]; w3 = Line[{{0, 0, 2}, {0.7, 0, 2}, {0, 0.7, 2}, {0, 0, 2}}]; gr = Graphics3D[{Red, Thickness[0.02], {w1, w2, w3}} /. OpenCascadeCircle -> Circle3D, Boxed -> False]

The loft command will greate a surface or a solid by creating surfaces that pass through the given objects.

Convert the graphics primitives to OpenCascade shapes.
Wolfram Language code: s = OpenCascadeShape /@ {w1, w2, w3}

Lofts can be generated from "Wire" or "Face" shape objects. All objects need to be of the same type though.

Inspect the types of the shapes.
Wolfram Language code: OpenCascadeShapeType /@ s
Create a loft.
Wolfram Language code: loft = OpenCascadeShapeLoft[s]
Visualize the loft and the original wires
Wolfram Language code: Show[ gr, OpenCascadeShapeSurfaceMeshToBoundaryMesh[loft]["Wireframe"] ]

By default, a loft created from wire objects will return an open shell.

Inspect the shape type of the loft.
Wolfram Language code: OpenCascadeShapeType[loft]

To generate a solid suitable for a full mesh generation set the option "BuildSolid"True.

Generate solid loft.
Wolfram Language code: loft = OpenCascadeShapeLoft[s, "BuildSolid" -> True]; OpenCascadeShapeType[loft]
Generate and visualize a full mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[loft]; mesh = ToElementMesh[bmesh, MaxCellMeasure -> Infinity]
Visualize the mesh and the wires
Wolfram Language code: Show[gr, mesh["Wireframe"["MeshElementStyle" -> FaceForm[Orange]]]]

When a loft is generated from faces, a solid is returned automatically.

Here is an example that creates a helix.

Loft a helix from a set of circles:
Wolfram Language code: f[t_] := {1 / 2 * Cos[10 * t], 1 / 2 * Sin[10 * t], t / 4}; circles = Table[OpenCascadeCircle[{f[t], f'[t]}, 1 / 20], {t, 0, 2 π, 2 π / 61}]; s = OpenCascadeShape /@ circles; loft = OpenCascadeShapeLoft[s, "BuildSolid" -> True]; bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[loft, "ShapeSurfaceMeshOptions" -> {"AngularDeflection" -> 0.15}]; bmesh["Wireframe"["MeshElementStyle" -> Directive[FaceForm[MaterialShading["Aluminum"]], EdgeForm[]]]]

Shelling

OpenCascade provides functionality to shell shapes.

Generate a shape.
Wolfram Language code: shape = OpenCascadeShape[Cuboid[]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Find the number of faces in the shape.
Wolfram Language code: OpenCascadeShapeNumberOfFaces[shape]
Shell the shape by removing faces 2 and 3.
Wolfram Language code: shell = OpenCascadeShapeShelling[shape, 0.1, {2, 3}]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shell]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shell]
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]
Generate the full mesh.
Wolfram Language code: ToElementMesh[bmesh]

Sometimes it is convenient to walk through all faces and see the effect a shelling has on the overall shape, or one needs to find the face one wants to use for shelling. For this purpose there is a helper function called VisualizeFaceFunction defined in the appendix that does that.

Interactively apply the shelling function to faces of the shape.
Wolfram Language code: VisualizeFaceFunction[Cuboid[], OpenCascadeShapeShelling[#1, 0.1, #2]&]

De-featuring

OpenCascade provides functionality to de-feature shapes.

Generate a shape.
Wolfram Language code: b1 = Cuboid[{0, 0, 0}, {9, 4, 2}]; b2 = Cuboid[{0, 0, 1}, {4, 1, 2}]; b3 = Cuboid[{4, 0, 0}, {6, 2, 2}];shapes = OpenCascadeShape /@ {b1, b2, b3}; shape = OpenCascadeShapeDifference@@shapes
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Find the number of faces.
Wolfram Language code: OpenCascadeShapeNumberOfFaces[shape]
Extract the boundary element markers.
Wolfram Language code: bmesh["BoundaryElementMarkerUnion"]
Visualize the boundary ElementMesh with faces 11 and 12 highlighted.
Wolfram Language code: Show[bmesh["Wireframe"], bmesh["Wireframe"[ElementMarker == 11 || ElementMarker == 12, "MeshElementStyle" -> FaceForm[Orange]]]]
De-feature the shape by removing faces 11 and 12.
Wolfram Language code: defeatured = OpenCascadeShapeDefeaturing[shape, {11, 12}]
Extract and visualize the boundary ElementMesh of the de-featured shape.
Wolfram Language code: bmeshDefeatured = OpenCascadeShapeSurfaceMeshToBoundaryMesh[defeatured]; bmeshDefeatured["Wireframe"["MeshElementStyle" -> FaceForm[Orange]]]
Visualize the boundary ElementMesh with faces 8 and 12 highlighted.
Wolfram Language code: Show[bmesh["Wireframe"], bmesh["Wireframe"[ElementMarker == 8 || ElementMarker == 12, "MeshElementStyle" -> FaceForm[Orange]]]]
De-feature the shape by removing faces 8 and 12.
Wolfram Language code: defeatured = OpenCascadeShapeDefeaturing[shape, {8, 12}]
Extract and visualize the boundary ElementMesh of the de-featured shape.
Wolfram Language code: bmeshDefeatured = OpenCascadeShapeSurfaceMeshToBoundaryMesh[defeatured]; bmeshDefeatured["Wireframe"["MeshElementStyle" -> FaceForm[Orange]]]
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[defeatured]

Shape Simplification

OpenCascade provides functionality to simplify shapes.

Generate a shape.
Wolfram Language code: b1 = Cuboid[{2, 0, 0}, {8, 4, 2}]; b2 = Cuboid[{1, 0, 1}, {4, 1, 2}]; b3 = Cuboid[{4, -1, 0}, {6, 2, 2}];shapes = OpenCascadeShape /@ {b1, b2, b3}; shape = OpenCascadeShapeUnion@@shapes
Look at the OpenCascade shape type.
Wolfram Language code: OpenCascadeShapeType[shape]
Extract the boundary mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Wireframe"]
Find the number of faces.
Wolfram Language code: OpenCascadeShapeNumberOfFaces[shape]
Extract the boundary element markers.
Wolfram Language code: shape = OpenCascadeShapeSimplify[shape]
Extract the boundary mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]["Wireframe"]
Find the number of faces.
Wolfram Language code: OpenCascadeShapeNumberOfFaces[shape]

Shape Healing

OpenCascade provides functionality to heal shapes. Healing means that, for example, broken ordering of surfaces can be fixed.

Fix a broken shape:
Wolfram Language code: OpenCascadeShapeFix[shape]

Import/Export

OpenCascade can read and write various computer aided design relevant file formats. Import and Export of the these file formats is partially implemented.

STL Export

OpenCascade can export STL files.

Create a shape.
Wolfram Language code: shape = OpenCascadeShape[Ball[{1, 0, 0}]]
Export the shape as a STL file.
Wolfram Language code: fileName = FileNameJoin[{$TemporaryDirectory, "test.stl"}]; OpenCascadeShapeExport[fileName, shape]
Import the generated STL with Import.
Wolfram Language code: mr = Import[fileName]; bmesh = ToBoundaryMesh[mr];
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]

Boundary normals in OpenCascade are in the opposite direction then what they are in the wolfram language. If an exported STL shows signs of the normals being in the 'wrong' direction one can convert the shape to an ElementMesh and that to a MeshRegion. The MeshRegion can then be exported as a STL file with Export.

Convert a shape to a MeshRegion for STL export.
Wolfram Language code: fileName = FileNameJoin[{$TemporaryDirectory, "testMR.stl"}]; mr = MeshRegion[OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]]; Export[fileName, mr]

STL Import

OpenCascade can import STL files.

Import a STL file.
Wolfram Language code: shape = OpenCascadeShapeImport[FindFile["ExampleData/vase.stl"]]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Visualize the boundary ElementMesh.
Wolfram Language code: bmesh["Wireframe"]

Note that an import of a STL file with OpenCascadeShapeImport will result in a boundary mesh that has unique markers assigned to each surface element.

Inspect the boundary element markers.
Wolfram Language code: bmesh["BoundaryElementMarkerUnion"]//Short

This may not be wanted. To avoid that the options "MarkerMethod""ElementMesh" or "MarkerMethod"None may be specified.

Extract the boundary mesh and have the markers computed in the Wolfram language.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape, "MarkerMethod" -> "ElementMesh"]
Inspect the boundary element markers.
Wolfram Language code: (groups = bmesh["BoundaryElementMarkerUnion"])//Short
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]

Step Export

OpenCascade can export STEP files.

Create a shape.
Wolfram Language code: shape = OpenCascadeShape[Cone[{{0, 0, 0}, {0, 0, 1}}, 1]]
Export the shape as a STEP file.
Wolfram Language code: fileName = FileNameJoin[{$TemporaryDirectory, "test.stp"}]; OpenCascadeShapeExport[fileName, shape]

Step Import

OpenCascade can import STEP files.

Set up the example directory path.
Wolfram Language code: path = FileNameJoin[{$OpenCascadeInstallationDirectory, "ExampleData"}];
Import a step file.
Wolfram Language code: shape = OpenCascadeShapeImport[FileNameJoin[{path, "screw.step"}]]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]
Generate the full mesh.
Wolfram Language code: ToElementMesh[bmesh]
Import a step file.
Wolfram Language code: shape = OpenCascadeShapeImport[FileNameJoin[{path, "linkrods.step"}]]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: Rasterize[bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]]
Generate the full mesh.
Wolfram Language code: ToElementMesh[bmesh]

Step assemblies are imported as OpenCascade Compounds. The function OpenCascadeShapeNumberOfSolids can be used to find the number of solids parts in the assembly and the function OpenCascadeShapeSolids can extract the parts.

BRep Export

OpenCascade can export BRep files.

Create a shape.
Wolfram Language code: shape = OpenCascadeShape[Cone[{{0, 0, 0}, {0, 0, 1}}, 1]]
Export the shape as a BRep file.
Wolfram Language code: fileName = FileNameJoin[{$TemporaryDirectory, "test.brep"}]; OpenCascadeShapeExport[fileName, shape]

BRep Import

OpenCascade can import BRep files.

Set up the example directory path.
Wolfram Language code: path = FileNameJoin[{$OpenCascadeInstallationDirectory, "ExampleData"}];
Import a brep file.
Wolfram Language code: shape = OpenCascadeShapeImport[FileNameJoin[{path, "Bottom.brep"}]]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Look at the boundary element marker union and create colors for the markers.
Wolfram Language code: groups = bmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp
Visualize the boundary ElementMesh with markers highlighted.
Wolfram Language code: Rasterize[bmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]]]
Generate the full mesh with mesh order 1.
Wolfram Language code: ToElementMesh[bmesh, "MeshOrder" -> 1]

Units

The default of OpenCascadeLink uses no units.

Set up the example directory path.
Wolfram Language code: path = FileNameJoin[{$OpenCascadeInstallationDirectory, "ExampleData"}];
Import a step file.
Wolfram Language code: shape = OpenCascadeShapeImport[FileNameJoin[{path, "linkrods.step"}]]
Extract the boundary mesh.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape]
Inspect the length unit.
Wolfram Language code: bmesh["LengthUnit"]

By default OpenCascade operates with the length unit of millimeter, these can be requested.

Extract the boundary mesh with units of millimeters.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape, "ElementMeshOptions" -> {"LengthUnit" -> "Millimeters"}]
Inspect the length unit.
Wolfram Language code: bmesh["LengthUnit"]
Extract and rescale the boundary mesh with custom units.
Wolfram Language code: bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape, "ElementMeshOptions" -> {"LengthUnit" -> "Meter"}]
Inspect the length unit.
Wolfram Language code: bmesh["LengthUnit"]
Convert the boundary mesh to a full mesh and inspect the units.
Wolfram Language code: ToElementMesh[bmesh]["LengthUnit"]

Possible issues

Boolean operation issues

The lowest dimensional object that can be returned from an OpenCascase Boolean operation is that of the minimal dimension of any argument given to the Boolean operation. For example, a Boolean operation of two OpenCascade solids can not return an OpenCascade face object.

Create two touching cubes.
Wolfram Language code: Graphics3D[{{Opacity[0.5], c1 = Cuboid[], c2 = Cuboid[{1, 1 / 2, 1 / 2}]}, {Red, Polygon[{{1, 1 / 2, 1 / 2}, {1, 1, 1 / 2}, {1, 1, 1}, {1, 1 / 2, 1}}]}}, Boxed -> False]
Create two OpenCascade shapes.
Wolfram Language code: s1 = OpenCascadeShape[c1] s2 = OpenCascadeShape[c2]
Look at the OpenCascade shape types.
Wolfram Language code: OpenCascadeShapeType[s1] OpenCascadeShapeType[s2]
Construct the intersection.
Wolfram Language code: intersection = OpenCascadeShapeIntersection[s1, s2]
Look at the intersection shape type.
Wolfram Language code: OpenCascadeShapeType[intersection]

A boundary mesh can not be generated because the resulting OpenCascade shape intersection does not contain information on the lower dimensional face object.

Extract the boundary mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[intersection]
Look at the number of faces.
Wolfram Language code: OpenCascadeShapeNumberOfFaces[intersection]

Consider the case of a face and a cuboid touching.

Wolfram Language code: Graphics3D[{{Opacity[0.5], face = Polygon[{{1, 0, 0}, {1, 1, 0}, {1, 1, 1}, {1, 0, 1}}], c2}, {Red, Polygon[{{1, 1 / 2, 1 / 2}, {1, 1, 1 / 2}, {1, 1, 1}, {1, 1 / 2, 1}}]}}, Boxed -> False]
Create two OpenCascade shapes.
Wolfram Language code: s1 = OpenCascadeShape[face] s2 = OpenCascadeShape[c2]
Look at the OpenCascade shape types.
Wolfram Language code: OpenCascadeShapeType[s1] OpenCascadeShapeType[s2]
Construct the intersection.
Wolfram Language code: intersection = OpenCascadeShapeIntersection[s1, s2]
Look at the intersection shape type.
Wolfram Language code: OpenCascadeShapeType[intersection]

The lowest dimensional argument to the OpenCascade Boolean intersection operation was the face object. Since the resulting operation is also a face object the object information is present in the resulting shape object and can be meshed.

Visualize the boundary mesh.
Wolfram Language code: OpenCascadeShapeSurfaceMeshToBoundaryMesh[intersection]["Wireframe"]

Tolerance issues

The standard tolerance for OpenCascade is . If you are dealing with geometries that have components in that scale it is recommenced to rescale the geometry. Once the geometry is generated then the boundary mesh can be rescaled again to the original scale.

Create and visualize a geometry below the standard OpenCascade tolerance.
Wolfram Language code: s1 = OpenCascadeShape[Ball[{0, 0, 0}, 10 ^ -8]]; s2 = OpenCascadeShape[Ball[{10 ^ -8, 0, 0}, 10 ^ -8]]; s = OpenCascadeShapeUnion[s1, s2]; bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[s]; bmesh["Wireframe"["MeshElementStyle" -> Directive[{Opacity[0.5], FaceForm[LightGreen]}]]]

Depending on the operating system this may show a defect. For convenience the defect is reproduced below.

15.gif

A Boolean operation below the default OpenCascade tolerance of can lead to defects.

A solution for this is to scale the geometry.

Scale the geometry.
Wolfram Language code: scale = 10 ^ 6; s1 = OpenCascadeShape[Ball[{0, 0, 0}, scale * 10 ^ -8]]; s2 = OpenCascadeShape[Ball[scale * {10 ^ -8, 0, 0}, scale * 10 ^ -8]]; s = OpenCascadeShapeUnion[s1, s2]; bmesh = OpenCascadeShapeSurfaceMeshToBoundaryMesh[s]; bmesh["Wireframe"["MeshElementStyle" -> Directive[{Opacity[0.5], FaceForm[LightGreen]}]]]

As a second step the boundary mesh can be rescaled to it's intended scale.

Inspect the length unit of the boundary mesh.
Wolfram Language code: bmesh["LengthUnit"]
Set a length unit.
Wolfram Language code: SetLengthUnit[bmesh, "Micrometers"]
Rescale the mesh.
Wolfram Language code: bmesh2 = ElementMeshCoordinateRescale[bmesh, "Meters"]
Inspect the region bounds.
Wolfram Language code: bmesh2["Bounds"]

One thing to keep in mind though, is that a subsequent finite element analysis might benefit if the geometry is left in the rescale size and the PDE coefficients are adjusted to the new length scale. This can improve the stability of numerical solutions. This is outlined, for example, in the solid mechanics monograph.

Utility functions

VisualizeEdgeFunction

The function VisualizeEdgeFunction can be used to scroll through the edges of a region and apply an edge operation.

A utility function to interactively visualize edge operations.
Wolfram Language code: VisualizeEdgeFunction[region_, funIn_] := With[ {fun = funIn, ishape = OpenCascadeLink`OpenCascadeShape[region]}, With[ {numEdges = OpenCascadeLink`OpenCascadeShapeNumberOfEdges[ishape], bmesh = OpenCascadeLink`OpenCascadeShapeSurfaceMeshToBoundaryMesh[ishape]}, Manipulate[Module[{shape, newShape}, shape = OpenCascadeLink`OpenCascadeShape[region]; newShape = fun[shape, edge]; Show[ bmesh["Edgeframe"["EdgeframeDirective" -> LightGray]], If[newShape === $Failed, {} , OpenCascadeLink`OpenCascadeShapeSurfaceMeshToBoundaryMesh[newShape]["Edgeframe"] ] , PlotLabel -> Style["Edge = " <> ToString[edge]] ] ], {edge, 1, numEdges, 1, Appearance -> "Open"}, Initialization :> (Needs["OpenCascadeLink`"])] ] ]
VisualizeFaceFunction

The function VisualizeFaceFunction can be used to scroll through the faces of a region and apply a face operation.

A utility function to interactively visualize face operations.
Wolfram Language code: VisualizeFaceFunction[region_, funIn_] := With[ {fun = funIn, ishape = OpenCascadeLink`OpenCascadeShape[region]}, With[ {numFaces = OpenCascadeLink`OpenCascadeShapeNumberOfFaces[ishape], bmesh = OpenCascadeLink`OpenCascadeShapeSurfaceMeshToBoundaryMesh[ishape]}, Manipulate[Module[{shape, newShape, newBmesh, groups, temp, colors}, shape = OpenCascadeLink`OpenCascadeShape[region]; newShape = fun[shape, face]; Show[ bmesh["Edgeframe"["EdgeframeDirective" -> LightGray]], If[newShape === $Failed, {} , newBmesh = OpenCascadeLink`OpenCascadeShapeSurfaceMeshToBoundaryMesh[newShape]; groups = newBmesh["BoundaryElementMarkerUnion"]; temp = Most[Range[0, 1, 1 / (Length[groups])]]; colors = ColorData["BrightBands"][#]& /@ temp; newBmesh["Wireframe"["MeshElementStyle" -> FaceForm /@ colors]] ] , PlotLabel -> Style["Face = " <> ToString[face]] ] ], {face, 1, numFaces, 1, Appearance -> "Open"}, Initialization :> (Needs["OpenCascadeLink`"])] ] ]

Application examples

  • 3D Printed Mechanical Design
  • Book shelf bracket
  • Disc Brake
  • Helical bevel gear
  • Surgical fixation plate

Related Tech Notes

    ▪
  • Element Mesh Generation
  • ▪
  • Element Mesh Visualization
  • ▪
  • Book Shelf Bracket
  • ▪
  • Disc Brake
  • ▪
  • Helical Bevel Gear
  • ▪
  • Permanent Magnet with Coin
  • ▪
  • Surgical Fixation Plate
Top
Introduction for Programmers
Introductory Book
Wolfram Function Repository | Wolfram Data Repository | Wolfram Data Drop | Wolfram Language Products
Top
  • Products
  • Wolfram|One
  • Mathematica
  • AI Access
  • Compute Services
  • System Modeler

  • Wolfram|Alpha Notebook Edition
  • Wolfram|Alpha Pro
  • Mobile Apps

  • Wolfram Engine
  • Wolfram Player

  • Volume & Site Licensing
  • Server Deployment Options
  • Consulting
  • Wolfram Consulting
  • Repositories
  • Data Repository
  • Function Repository
  • Community Paclet Repository
  • Neural Net Repository
  • Prompt Repository

  • Wolfram Language Example Repository
  • Notebook Archive
  • Wolfram GitHub
  • Learning
  • Wolfram U
  • Wolfram Language Documentation
  • Webinars & Training
  • Educational Programs

  • Wolfram Language Introduction
  • Fast Introduction for Programmers
  • Fast Introduction for Math Students
  • Books

  • Wolfram Community
  • Wolfram Blog
  • Public Resources
  • Wolfram|Alpha
  • Wolfram Problem Generator
  • Wolfram Challenges

  • Computer-Based Math
  • Computational Thinking
  • Computational Adventures

  • Demonstrations Project
  • Wolfram Data Drop
  • MathWorld
  • Wolfram Science
  • Wolfram Media Publishing
  • Customer Resources
  • Store
  • Product Downloads
  • User Portal
  • Your Account
  • Organization Access

  • Support FAQ
  • Contact Support
  • Company
  • About Wolfram
  • Careers
  • Contact
  • Events
Wolfram Community Wolfram Blog
Legal & Privacy Policy
WolframAlpha.com | WolframCloud.com
© 2026 Wolfram
© 2026 Wolfram | Legal & Privacy Policy |
English