Geometric Computing

Roger Germundsson
Director of R&D
Wolfram Research

actualCow=ExampleData[{"Geometry3D","Cow"},"Graphics3D"];
convexCow=ConvexHullMesh[ExampleData[{"Geometry3D","Cow"},"VertexData"]];
Show[actualCow,RegionPlot3D[convexCow,PlotStyle->Directive[Opacity[0.5],EdgeForm[Directive[Thin,Opacity[0.1],Gray]]]]]

Overview

Overview

Regions

Basic Regions

Formula Regions

Mesh Regions

Derived Regions

Region Properties

Dimension Properties

Membership Properties

Moment/Integration Properties

Distance/Optimization Properties

Region Solvers

Visualizing

Integrating

Optimizing

Solving Equations & Inequalities

Solving Partial Differential Equations

Regions

A region ℛ⊆(ℝ^n) is a subset of (ℝ^n). In (Mathematica^®), anything for which RegionQ[ℛ] is True.

Basic Regions

Simple and common.

Specified with a few parameters or points.

Example: Ball[c,r]

Formula Regions

Flexible, exact, and powerful.

Specified with formulas.

Example: ImplicitRegion[(x^2)≤y,{x,y}]

Mesh Regions

Flexible, approximate, and powerful.

Specified with points and cells.

Example: MeshRegion[{(Subscript[p, 1]),…,(Subscript[p, n])},Tetrahedron[{(Subscript[vol, 1]),…,(Subscript[vol, m])}]]

Derived Regions

Flexible and powerful.

Specified with regions and additional information.

Example: RegionUnion[(Subscript[ℛ, 1]),(Subscript[ℛ, 2])]

Basic Regions

Basic regions have convenient parametrization, occur frequently, and include most of the extended graphics primitives.

1D Embedded

2D Embedded

3D Embedded

nD Embedded

Formula Regions

Formula regions are flexible and exact and allow for general formula specification, whether implicit or explicit.

Grid[{{HoldForm[ImplicitRegion[p[x],x]],"ℛ = {x | p[x]}"},
{HoldForm[ParametricRegion[f[u],u]],"ℛ = {y | y = f[u]}"}},
BaseStyle->"Text",Alignment->Left]//FramedStatement

ℛ=ImplicitRegion[1≤(x^2)+(y^2)≤2,{x,y}];

RegionPlot[ℛ,FrameTicks->None]

Integrate[1,x∈ℛ]

ℛ=ImplicitRegion[x y z≤1,{{x,-5,5},{y,-5,5},{z,-5,5}}];

RegionPlot3D[ℛ,PlotStyle->Opacity[0.5]]

Integrate[1,x∈ℛ]

Mesh Regions

Mesh regions are flexible and approximate. Piecewise linear cells can be used to approximate most regions.

Grid[{{HoldForm[MeshRegion[{(Subscript[p, 1]),(Subscript[p, 2]),…},{(Subscript[c, 1]),(Subscript[c, 2]),…}]],"disjoint union of cells \!\(\*Cell[TextData[Cell[BoxData[
FormBox[
RowBox[{"ℛ", " ", "=", " ", 
RowBox[{
SubscriptBox["⋃", "i"], 
SubscriptBox["c", "i"]}]}], TraditionalForm]],
FormatType->"TraditionalForm"]]]\) (arbitrary dim regions in 1D/2D/3D)"},
{HoldForm[BoundaryMeshRegion[{(Subscript[p, 1]),(Subscript[p, 2]),…},{(Subscript[bc, 1]),(Subscript[bc, 2]),…}]],"region inside boundary (full dim regions in 1D/2D/3D)"}},BaseStyle->"Text",Alignment->Left]//FramedStatement

ℛ=MeshRegion[{{0,0},{1,0},{0,1},{1,1}},Triangle[{{1,2,3},{3,2,4}}],MeshCellLabel->0->"Index"]

Integrate[1,x∈ℛ]

ℛ=MeshRegion[{{0,0,0},{2,0,0},{2,2,0},{0,2,0},{1,1,2}},{Tetrahedron[{{1,2,3,5},{1,3,4,5}}]},MeshCellLabel->0->"Index"]

Integrate[1,x∈ℛ]

ℛ=BoundaryMeshRegion[{{0,0},{3,0},{3,3},{0,3},{1,1},{2,1},{2,2},{1,2}},Line[{1,2,3,4,1}],Line[{5,6,7,8,5}],MeshCellLabel->0->"Index"]

Integrate[1,x∈ℛ]

pts={{0,0,0},{0,1,0},{1,1,0},{1,0,0},{0,0,1},{0,1,1},{1,1,1},{1,0,1}};
pts1=ScalingTransform[{3,3,3}][pts];
pts2=TranslationTransform[{1,1,1}][pts];
hex={{2,3,4,1},{1,4,8,5},{4,3,7,8},{3,2,6,7},{2,1,5,6},{5,8,7,6}};

ℛ=BoundaryMeshRegion[Join[pts1,pts2],Polygon[hex],Polygon[hex+8],MeshCellStyle->Opacity[0.3],MeshCellLabel->0->"Index"]

Integrate[1,x∈ℛ]

Mesh Regions

Typically, mesh-based regions are automatically constructed.

Grid[{{HoldForm[DelaunayMesh[{(Subscript[p, 1]),(Subscript[p, 2]),…}]],"Delaunay mesh from points"},
{HoldForm[VoronoiMesh[{(Subscript[p, 1]),(Subscript[p, 2]),…}]],"Voronoi mesh from points"},
{HoldForm[ConvexHullMesh[{(Subscript[p, 1]),(Subscript[p, 2]),…}]],"convex hull boundary mesh from points"},
{HoldForm[DiscretizeGraphics[g]],"fully discretize 2D/3D graphics"},
{HoldForm[BoundaryDiscretizeGraphics[g]],"boundary discretize 2D/3D graphics"},
{HoldForm[DiscretizeRegion[ℛ]],"fully discretize 1D/2D/3D regions"},
{HoldForm[BoundaryDiscretizeRegion[ℛ]],"boundary discretize 1D/2D/3D regions"},
{HoldForm[TriangulateMesh[ℳℛ]],"fully triangulate mesh from boundary mesh"},
{HoldForm[BoundaryMesh[ℳℛ]],"boundary mesh from full mesh"},
{HoldForm[HighlightMesh[ℳℛ,…]],"style and label mesh cells"}
},
BaseStyle->"Text",Alignment->Left,Dividers->{None,{False,False,False,True,False,True,False,True,False,False}}]//FramedStatement

DelaunayMesh[RandomReal[{0,1},{25,3}]]

VoronoiMesh[RandomReal[{0,1},{25,2}]]

ConvexHullMesh[RandomReal[{0,1},{25,3}]]

BoundaryDiscretizeGraphics[]

TriangulateMesh[%]

MeshCellCount[%]

Note: Mathematica 10.0.2 has high performance and quality.

ℳ=BoundaryDiscretizeRegion[ImplicitRegion[-1+(((-1+18 (x^2)-48 (x^4)+32 (x^6)))^2)+(((-1+18 (y^2)-48 (y^4)+32 (y^6)))^2) ≤0,{x,y}],MaxCellMeasure->0.01]

HighlightMesh[ℳ,Style[{1,All},Red]]

Derived Regions

Derived regions are constructed from other regions.

Grid[{{HoldForm[RegionUnion[(Subscript[ℛ, 1]),(Subscript[ℛ, 2])]],"\!\(\*Cell[TextData[{
Cell[BoxData[
FormBox[
RowBox[{"ℛ", " ", "=", " ", 
RowBox[{"{", 
RowBox[{"x", " ", "|", " ", 
RowBox[{
RowBox[{"x", " ", "∈", " ", 
SubscriptBox["ℛ", "1"]}], " ", "∨", " ", 
RowBox[{"x", " ", "∈", " ", 
SubscriptBox["ℛ", "2"]}]}]}], "}"}]}], TraditionalForm]],
FormatType->"TraditionalForm"],
" = ",
Cell[BoxData[
FormBox[
RowBox[{
SubscriptBox["ℛ", "1"], " ", "⋃", " ", 
SubscriptBox["ℛ", "2"]}], TraditionalForm]],
FormatType->"TraditionalForm"]
}]]\)"},
{HoldForm[RegionIntersection[(Subscript[ℛ, 1]),(Subscript[ℛ, 2])]],"\!\(\*Cell[TextData[{
Cell[BoxData[
FormBox[
RowBox[{"ℛ", " ", "=", " ", 
RowBox[{"{", 
RowBox[{"x", " ", "|", " ", 
RowBox[{
RowBox[{"x", " ", "∈", " ", 
SubscriptBox["ℛ", "1"]}], " ", "∧", " ", 
RowBox[{"x", " ", "∈", " ", 
SubscriptBox["ℛ", "2"]}]}]}], "}"}]}], TraditionalForm]],
FormatType->"TraditionalForm"],
" = ",
Cell[BoxData[
FormBox[
RowBox[{
SubscriptBox["ℛ", "1"], " ", "⋂", " ", 
SubscriptBox["ℛ", "2"]}], TraditionalForm]],
FormatType->"TraditionalForm"]
}]]\)"},
{HoldForm[RegionDifference[(Subscript[ℛ, 1]),(Subscript[ℛ, 2])]],"\!\(\*Cell[TextData[{
Cell[BoxData[
FormBox[
RowBox[{"ℛ", " ", "=", " ", 
RowBox[{"{", 
RowBox[{"x", " ", "|", " ", 
RowBox[{
RowBox[{"x", " ", "∈", " ", 
SubscriptBox["ℛ", "1"]}], " ", "∧", " ", 
RowBox[{"x", " ", "∉", " ", 
SubscriptBox["ℛ", "2"]}]}]}], "}"}]}], TraditionalForm]],
FormatType->"TraditionalForm"],
" = ",
Cell[BoxData[
FormBox[
RowBox[{
SubscriptBox["ℛ", "1"], " ", "\\", " ", 
SubscriptBox["ℛ", "2"]}], TraditionalForm]],
FormatType->"TraditionalForm"]
}]]\)"},
{HoldForm[RegionSymmetricDifference[(Subscript[ℛ, 1]),(Subscript[ℛ, 2])]],"\!\(\*Cell[TextData[Cell[BoxData[
FormBox[
RowBox[{"ℛ", " ", "=", " ", 
RowBox[{
RowBox[{"{", 
RowBox[{"x", " ", "|", " ", 
RowBox[{
RowBox[{"x", " ", "∈", " ", 
SubscriptBox["ℛ", "1"]}], " ", "⊻", " ", 
RowBox[{"x", " ", "∉", " ", 
SubscriptBox["ℛ", "2"]}]}]}], "}"}], " ", "=", " ", 
RowBox[{
SubscriptBox["ℛ", "1"], " ", "Δ", " ", 
SubscriptBox["ℛ", "2"]}]}]}], TraditionalForm]],
FormatType->"TraditionalForm"]]]\)"},
{HoldForm[BooleanRegion[f,{(Subscript[ℛ, 1]),(Subscript[ℛ, 2]),…}]],"\!\(\*Cell[TextData[Cell[BoxData[
FormBox[
RowBox[{"ℛ", " ", "=", " ", 
RowBox[{"{", 
RowBox[{"x", " ", "|", " ", 
RowBox[{"f", "[", 
RowBox[{
RowBox[{"x", " ", "∈", " ", 
SubscriptBox["ℛ", "1"]}], ",", 
RowBox[{"x", " ", "∈", " ", 
SubscriptBox["ℛ", "2"]}], ",", "…"}], "]"}]}], "}"}], " "}], TraditionalForm]],
FormatType->"TraditionalForm"]]]\)"},
{HoldForm[RegionProduct[(Subscript[ℛ, 1]),(Subscript[ℛ, 2]),…]],"\!\(\*Cell[TextData[{
Cell[BoxData[
FormBox[
RowBox[{"ℛ", " ", "=", " ", 
RowBox[{"{", 
RowBox[{
RowBox[{"{", 
RowBox[{
SubscriptBox["x", "1"], ",", 
SubscriptBox["x", "2"], ",", "…"}], "}"}], " ", "|", " ", 
RowBox[{
RowBox[{
SubscriptBox["x", "1"], " ", "∈", " ", 
SubscriptBox["ℛ", "1"]}], " ", "∧", " ", 
RowBox[{
SubscriptBox["x", "2"], " ", "∈", " ", 
SubscriptBox["ℛ", "2"]}], " ", "∧", " ", "⋯"}]}], "}"}]}], TraditionalForm]],
FormatType->"TraditionalForm"],
" = ",
Cell[BoxData[
FormBox[
RowBox[{
SubscriptBox["ℛ", "1"], " ", "×", " ", 
SubscriptBox["ℛ", "2"], " ", "×", " ", "⋯"}], TraditionalForm]],
FormatType->"TraditionalForm"]
}]]\)"},
{HoldForm[TransformedRegion[(Subscript[ℛ, 1]),f]],"\!\(\*Cell[TextData[Cell[BoxData[
FormBox[
RowBox[{"ℛ", " ", "=", " ", 
RowBox[{
RowBox[{"{", 
RowBox[{
RowBox[{"f", "[", "x", "]"}], " ", "|", " ", 
RowBox[{"x", " ", "∈", " ", 
SubscriptBox["ℛ", "1"]}]}], " ", "}"}], " ", "=", " ", 
RowBox[{"f", "[", 
SubscriptBox["ℛ", "1"], "]"}]}]}], TraditionalForm]],
FormatType->"TraditionalForm"]]]\)"},
{HoldForm[InverseTransformedRegion[(Subscript[ℛ, 1]),f]],"\!\(\*Cell[TextData[Cell[BoxData[
FormBox[
RowBox[{"ℛ", " ", "=", " ", 
RowBox[{
RowBox[{"{", 
RowBox[{"x", " ", "|", " ", 
RowBox[{
RowBox[{"f", "[", "x", "]"}], " ", "∈", " ", 
SubscriptBox["ℛ", "1"]}]}], " ", "}"}], " ", "=",
 " ", 
RowBox[{
SuperscriptBox["f", 
RowBox[{"-", "1"}]], "[", 
SubscriptBox["ℛ", "1"], "]"}]}]}], TraditionalForm]],
FormatType->"TraditionalForm"]]]\)"},
{HoldForm[RegionBoundary[(Subscript[ℛ, 1])]],"\!\(\*Cell[TextData[{
Cell[BoxData[
FormBox[
RowBox[{"ℛ", " ", "=", " ", 
RowBox[{"{", 
RowBox[{"x", " ", "|", " ", 
RowBox[{"x", " ", "∈", " ", 
RowBox[{"∂", 
SubscriptBox["ℛ", "1"]}]}]}], " ", "}"}]}], TraditionalForm]],
FormatType->"TraditionalForm"],
" = ",
Cell[BoxData[
FormBox[
RowBox[{"∂", 
SubscriptBox["ℛ", "1"]}], TraditionalForm]],
FormatType->"TraditionalForm"]
}]]\)"}},
BaseStyle->"Text",Alignment->Left,Dividers->{None,{False,False,False,False,False,True,True,False,True}}]//FramedStatement

r1=Disk[{-1/2,0}];
r2=Disk[{1/2,0}];

d1=RegionUnion[r1,r2];
d2=RegionIntersection[r1,r2];
d3=RegionDifference[r1,r2];
d4=RegionSymmetricDifference[r1,r2];

Table[Show[BoundaryDiscretizeRegion[r],PlotRange->{{-1.65,1.65},{-1.1,1.1}},PlotLabel->Head[r]],{r,{d1,d2,d3,d4}}]

ℛ=DiscretizeGraphics[Cuboid[]]

t1=ScalingTransform[{2,1,1}];
t2=RotationTransform[π/3,{1,1,1}];
t3=ShearingTransform[π/6,{1,1,0},{0,0,1}];
t4=Composition[t3,t2,t1];

Table[TransformedRegion[ℛ,t],{t,{t1,t2,t3,t4}}]

Region Properties

Region properties summarize some aspects of regions.

Dimension Properties

RegionEmbeddingDimension

RegionDimension

Membership Properties

x∈ℛ

RegionMember, RegionMemberFunction

Moment/Integration Properties

ArcLength, Area, Volume, RegionMeasure

RegionCentroid

Distance/Optimization Properties

RegionNearest, RegionNearestFunction

RegionDistance, RegionDistanceFunction

RegionSignedDistance, RegionDistanceFunction

Dimension Properties

Grid[{{HoldForm[RegionDimension[ℛ]],"dimension of region"},
{HoldForm[RegionEmbeddingDimension[ℛ]],"dimension of embedding space"}},BaseStyle->"Text",Alignment->Left]//FramedStatement

({{"", 0, 1, 2, 3}, {2, , , , ""}, {3, , , , }})//CellDisplay

RegionEmbeddingDimension

RegionEmbeddingDimension[Disk[]]

RegionEmbeddingDimension[Circle[]]

RegionEmbeddingDimension[Point[{1,2,3,4}]]

RegionDimension

RegionDimension[Disk[]]

RegionDimension[Circle[]]

RegionDimension[Point[{1,2,3,4}]]

Membership Properties

Grid[{{"Element[x,ℛ]","assert that x∈ℛ"},
{HoldForm[RegionMember[ℛ,x]],"find conditions for x∈ℛ"},
{HoldForm[RegionMember[ℛ]],"find region member function"}},BaseStyle->"Text",Alignment->Left]//FramedStatement

Element

Assert membership.

{x,y}∈Disk[{0,0},r]

Integrate[1,%]

RegionMember

Find conditions for membership.

RegionMember[Disk[{0,0},r],{x,y}]

RegionMemberFunction

Get a member function.

mf=RegionMember[Disk[{0,0},1]]

mf[{1/2,0}]

ℛ=ConvexHullMesh[RandomReal[1,{200,3}]];
pts=RandomReal[1,{(10^5),3}];
cls=RegionMember[ℛ,pts];

Graphics3D[{PointSize[Tiny],{Green,Point@Pick[pts,cls,True]},{Red,Point@Pick[pts,cls,False]}}]

Moment/Integration Properties

Grid[{
{HoldForm[ArcLength[ℛ]],"curve length for 1D region"},
{HoldForm[Area[ℛ]],"surface area for 2D region"},
{HoldForm[Volume[ℛ]],"solid volume for 3D region"},
{HoldForm[RegionMeasure[ℛ]],"count, length, area, volume etc (\!\(\*Cell[TextData[Cell[BoxData[
FormBox[
RowBox[{
SubscriptBox["∫", 
RowBox[{"x", "∈", "ℛ"}]], "1"}], TraditionalForm]],
FormatType->"TraditionalForm"]]]\))"},
{HoldForm[RegionCentroid[ℛ]],"centrality measure (\!\(\*Cell[TextData[Cell[BoxData[
FormBox[
RowBox[{
RowBox[{"(", 
RowBox[{
SubscriptBox["∫", 
RowBox[{"x", "∈", "ℛ"}]], "x"}], ")"}], "/", "m"}], TraditionalForm]],
FormatType->"TraditionalForm"]]]\))"}},BaseStyle->"Text",Alignment->Left]//FramedStatement

RegionMeasure

ArcLength[Circle[]]

ArcLength[ImplicitRegion[x^2+(y/2)^2==1,{x,y}]]

ArcLength[]

Area[Disk[]]

Area[]

Volume[Ball[]]

Volume[]

Table[RegionMeasure[Sphere[n]],{n,1,10}]

FindSequenceFunction[%,n]//FullSimplify

Moment/Integration Properties

Grid[{
{HoldForm[ArcLength[ℛ]],"curve length for 1D region"},
{HoldForm[Area[ℛ]],"surface area for 2D region"},
{HoldForm[Volume[ℛ]],"solid volume for 3D region"},
{HoldForm[RegionMeasure[ℛ]],"count, length, area, volume etc (\!\(\*Cell[TextData[Cell[BoxData[
FormBox[
RowBox[{
SubscriptBox["∫", 
RowBox[{"x", "∈", "ℛ"}]], "1"}], TraditionalForm]],
FormatType->"TraditionalForm"]]]\))"},
{HoldForm[RegionCentroid[ℛ]],"centrality measure (\!\(\*Cell[TextData[Cell[BoxData[
FormBox[
RowBox[{
RowBox[{"(", 
RowBox[{
SubscriptBox["∫", 
RowBox[{"x", "∈", "ℛ"}]], "x"}], ")"}], "/", "m"}], TraditionalForm]],
FormatType->"TraditionalForm"]]]\))"}},BaseStyle->"Text",Alignment->Left]//FramedStatement

RegionCentroid

RegionCentroid[Disk[{x,y},r]]

RegionCentroid[Polygon[{{0,0},{3,-1},{1,0},{3,1}}]]

Graphics[{LightBlue,Polygon[{{0,0},{3,-1},{1,0},{3,1}}],Red,Point[%]}]

RegionCentroid[]

Distance/Optimization Properties

Grid[{
{HoldForm[RegionNearest[ℛ,p]],"nearest point in region"},
{HoldForm[RegionDistance[ℛ,p]],"minimum distance to region"},
{HoldForm[SignedRegionDistance[ℛ,p]],"distance to region or negative distance to complement"}},
BaseStyle->"Text",Alignment->Left]//FramedStatement

RegionNearest

Gives the nearest point in a region.

RegionNearest[Disk[],{x,y}]

RegionNearest[Triangle[{{0,0},{1,0},{0,1}}],{x,y}]

rnf=RegionNearest[Triangle[{{0,0},{1,0},{0,1}}]]

rnf/@{{2,2},{1,0},{3,4}}

Distance/Optimization Properties

Grid[{
{HoldForm[RegionNearest[ℛ,p]],"nearest point in region"},
{HoldForm[RegionDistance[ℛ,p]],"minimum distance to region"},
{HoldForm[SignedRegionDistance[ℛ,p]],"distance to region or negative distance to complement"}},BaseStyle->"Text",Alignment->Left]//FramedStatement

RegionDistance

Gives the distance to the nearest point in a region.

dtri=RegionDistance[Triangle[{{0,0},{1,0},{0,1}}]]

ContourPlot[dtri[{x,y}],{x,-2,3},{y,-2,3},Contours->{0.25,0.5,1.0},Exclusions->None]

dtet=RegionDistance[Tetrahedron[{{0,0,0},{1,0,0},{0,1,0},{0,0,1.}}]]

ContourPlot3D[dtet[{x,y,z}],{x,-2,3},{y,-2,3},{z,-2,3},Mesh->None,Contours->{0.25,0.5,1.0},PlotPoints->50,MaxRecursion->0,ContourStyle->ColorData[95,"ColorList"],BaseStyle->Opacity[0.5],ImageSize->Small]

Region Solvers

Region solvers use a flexible problem language that can accept and is optimized for region arguments.

Visualize over a Region

FramedBulletList[{Plot,ParametricPlot,Plot3D,ParametricPlot3D,DensityPlot,ContourPlot,VectorPlot,StreamPlot,VectorDensityPlot,StreamDensityPlot,NumberLinePlot,RegionPlot,RegionPlot3D}]

Example: Plot3D[f[x],x∈ℛ]

Integrate over a Region

FramedBulletList[{Integrate,NIntegrate}]

Example: Integrate[f[x],x∈ℛ]

Solve PDEs over a Region

FramedBulletList[{NDSolve,NDSolveValue,ParametricNDSolve,ParametricNDSolveValue}]

Example: NDSolve[eqns,u,x∈ℛ]

Optimize with Region Constraints

FramedBulletList[{Minimize , MinValue , ArgMin , Maximize , MaxValue ,ArgMax , NMinimize , NMinValue ,NArgMin , NMaximize , NMaxValue , NArgMax , FindMinimum , FindMinValue , FindArgMin , FindMaximum , FindMaxValue , FindArgMax}]

Example: MinValue[f[x],x∈ℛ]

Solve Equations with Region Constraints

FramedBulletList[{Solve , NSolve , Reduce , FindInstance ,Resolve}]

Example: Solve[eqns,x∈ℛ]

Visualize over a Region

Grid[{{HoldForm[Plot["…",x∈ℛ]]},
{HoldForm[ParametricPlot["…",{u,v}∈ℛ]]},
{HoldForm[Plot3D["…",{x,y}∈ℛ]]},
{"⋮"},
{HoldForm[VectorPlot["…",{x,y}∈ℛ]]},
{HoldForm[StreamPlot["…",{x,y}∈ℛ]]},
{"⋮"}},Alignment->Left]//FramedStatement

Note: This will work in Mathematica 10.0.2.

ℛ=Interval@@Table[{k π-π/2,(k+1)π-π/2},{k,2,10,2}]

Plot[Sin[x],x∈ℛ]

Plot3D[Sin[2π x y],{x,y}∈Disk[]]

Note: This will work in Mathematica 10.0.2.

StreamPlot[{-1-x^2+y,1+x-y^2},{x,y}∈Disk[{0,0},3]]

Integrate over a Region

Grid[{{Row[{"Integrate[","f[x], ",HoldForm[x∈ℛ],"]    (", HoldForm[Integrate[f[x],x∈ℛ]],")"}]},
{HoldForm[NIntegrate[f[x],x∈ℛ]]}
},Alignment->Left]//FramedStatement

Integrate[1,{x,y}∈Circle[{1,2},r]]

Integrate[1,{x,y}∈Disk[]]

Integrate[1,{x,y,z}∈Ball[]]

NIntegrate[1,{x,y,z}∈]

NIntegrate[1,{x,y,z}∈]

NIntegrate[1,{x,y,z}∈]

Solve PDEs over a Region

Grid[{{HoldForm[NDSolve[…,…,{(Subscript[x, 1]),…}∈ℛ]]},
{HoldForm[NDSolveValue[…,…,{(Subscript[x, 1]),…}∈ℛ]]}
},Alignment->Left]//FramedStatement

usol=NDSolveValue[{(Subscript[∇, {x,y}]^2)u[x,y]==1,DirichletCondition[u[x,y]==0,True]},u,{x,y}∈Disk[]]

Plot3D[usol[x,y],{x,y}∈Disk[]]

ℛ=;

usol=NDSolveValue[{(Subscript[∇, {x,y}]^2)u[x,y]==10,DirichletCondition[u[x,y]==0,True]},u,{x,y}∈ℛ]

Plot3D[usol[x,y],{x,y}∈ℛ,PlotPoints->150,ImageSize->550,PlotRange->{All,All,{All,-2}},Mesh->None,BoxRatios->{1,0.273,0.4},PlotTheme->"Marketing",PlotStyle->Opacity[0.5]]

Optimize with Region Constraints

Grid[{{HoldForm[Minimize[{f[x],…},x∈ℛ]]},
{"⋮"},
{HoldForm[NMinimize[{f[x],…},x∈ℛ]]},
{"⋮"},
{HoldForm[FindMinimum[{f[x],…},x∈ℛ]]},
{"⋮"}
},Alignment->Left]//FramedStatement

pmin=ArgMin[(x^2)-x y+(y^2),{x,y}∈Disk[]]

pmax=ArgMax[(x^2)-x y+(y^2),{x,y}∈Disk[]]

Legended[Show[ContourPlot[(x^2)-x y+(y^2),{x,y}∈Disk[]],Graphics[{PointSize[Medium],{Red,Point[pmin]},{Blue,Point[pmax]}}]],SwatchLegend[{Red,Blue},{"min","max"}]]

ℛ1=Disk[];
ℛ2=Rectangle[{2,1},{3,3}];

{p1t,p2t}=NArgMin[EuclideanDistance[p1,p2],{p1∈ℛ1,p2∈ℛ2}]

{q1t,q2t}=NArgMax[EuclideanDistance[p1,p2],{p1∈ℛ1,p2∈ℛ2}]

Graphics[{{LightBlue,ℛ1,ℛ2},{Dashed,Line[{p1t,p2t}],Red,Point[{p1t,p2t}]},{Dashed,Line[{q1t,q2t}],Red,Point[{q1t,q2t}]}}]

Solve Equations with Region Constraints

Grid[{{HoldForm[Solve[…,x∈ℛ]]},
{HoldForm[NSolve[…,x∈ℛ]]},
{HoldForm[Reduce[…,x∈ℛ]]},
{HoldForm[FindInstance[…,x∈ℛ]]},
{HoldForm[Resolve[(Subscript[∃, y])y∈𝒮∧⋯,x∈ℛ]]},
{"⋮"}
},Alignment->Left]//FramedStatement

line1=InfiniteLine[{0,0},{1,1}];
line2=InfiniteLine[{{0,1},{1,0}}];

sol=NSolve[{x,y}∈line1∧{x,y}∈line2,{x,y}]

Graphics[{{Lighter[Blue,0.5],line1,line2},{Red,Point[{x,y}/.sol]}},Axes->True]

line=InfiniteLine[{0,0},{1,1}];
circle=Circle[{0,0},1];

sol=Solve[p∈line∧p∈circle,p]

Graphics[{{Lighter[Blue,0.5],line,circle},{Red,Point[p/.sol]}},Axes->True]

{s1,s2,s3}=Table[Sphere[{1/3 Cos[k 2π/3],1/3 Sin[k 2π/3],0}],{k,0,2}];

sol=Solve[p∈s1∧p∈s2∧p∈s3,p]

Graphics3D[{{Opacity[0.5],s1,s2,s3},{Red,PointSize[Large],Point[p/.sol]}}]

Summary

Regions

Basic Regions

Formula Regions

Mesh Regions

Derived Regions

Region Properties

Dimension Properties

Membership Properties

Moment/Integration Properties

Distance/Optimization Properties

Region Solvers

Visualizing

Integrating

Optimizing

Solving Equations & Inequalities

Solving Partial Differential Equations

Exploration: Hausdorff Distance (Subscript[d, H])[𝒜,ℬ]

The Hausdorff distance (Subscript[d, H])[𝒜,ℬ]=Max[h[𝒜,ℬ],h[ℬ,𝒜]], where h[𝒜,ℬ] is the directed Hausdorff distance from region 𝒜 to ℬ given by h(𝒜,ℬ)==(sup_(q∈ℬ))(inf_(p∈𝒜))d(p,q).

Let’s start with two simple regions.

𝒜=Triangle[{{0,0},{2,0},{0,1}}];
ℬ=Triangle[{{0,0},{1,0},{0,3/2}}];

Legended[Graphics[{Opacity[0.5],{Red, 𝒜},{Blue,ℬ}}],SwatchLegend[{Red,Blue},{"𝒜","ℬ"}]]

The directed Hausdorff distance from 𝒜 to ℬ is h(𝒜,ℬ)==(sup_(q∈ℬ))(inf_(p∈𝒜))d(p,q).

d1=RegionDistance[𝒜,{x,y}]

As expected, the distance is zero where ℬ overlaps with 𝒜.

Plot3D[d1,{x,y}∈ℬ,PlotRange->All]

This is h[𝒜,ℬ]:

hAB=MaxValue[d1,{x,y}∈ℬ]

If h[𝒜,ℬ]==ϵ, then (ℬ^cl)⊆(Subscript[𝒜, ϵ]^cl) where (Subscript[𝒜, ϵ])={x|d[𝒜,x]≤ϵ}.

Show[RegionPlot[d1≤hAB,{x,-1,3},{y,-1,5/2}],Graphics[{Opacity[0.5],{Red, 𝒜},{Blue,ℬ}}]]

h[ℬ,𝒜] can be gotten similarly, as well as (Subscript[d, H])[𝒜,ℬ].

hBA=MaxValue[RegionDistance[ℬ,{x,y}],{x,y}∈𝒜]

dH=Max[hAB,hBA]

Exploration: Cantor Sets

The Cantor set 𝒜 is defined recursively with (Subscript[𝒜, 0])=[0,1] and (Subscript[𝒜, n])=(⋃_([a,b]∈(Subscript[𝒜, n-1])))([a,(b-a)/3]⋃[a+(b-a)2/3,b]).

cantorRules={a_,b_}:>{{a,a+(b-a)/3},{a+(b-a)2/3,b}};

CantorRegion[n_Integer?NonNegative]:=
Interval@@Nest[Flatten[Map[Function[s,s/.cantorRules],#],1]&,{{0,1}},n]

CantorRegion[0]

CantorRegion[1]

NumberLinePlot[Table[CantorRegion[i],{i,3}],{x,0,1}]

The measure, i.e. length, evolves in an interesting way.

Table[{i,RegionMeasure[CantorRegion[i]]},{i,5}]

FindSequenceFunction[%,k]

Cantor dust in (ℝ^d) is defined as the product of d Cantor sets: (Subscript[𝒟, n])=(Subscript[𝒜, n])×⋯×(Subscript[𝒜, n]).

CantorDust[n_Integer,d_]:=Module[{An},
An=DiscretizeRegion[CantorRegion[n],MaxCellMeasure->∞];
RegionProduct@@Table[An,{d}]
]

Table[CantorDust[k,2],{k,3}]

Table[CantorDust[k,3],{k,3}]

See how the measure evolves for these regions.

Table[{k,RegionMeasure@CantorDust[k,2]},{k,5}]//Rationalize

FindSequenceFunction[%,k]

Table[{k,RegionMeasure@CantorDust[k,3]},{k,0,3}]//Rationalize

FindSequenceFunction[%,k]

Generalize the Cantor dust definition to (Subscript[𝒟, (Subscript[k, 1]),…,(Subscript[k, d])])=(Subscript[𝒜, (Subscript[k, 1])])×⋯×(Subscript[𝒜, (Subscript[k, d])]).

CantorDust[n_List]:=
RegionProduct@@Table[DiscretizeRegion[CantorRegion[n[[i]]],MaxCellMeasure->∞],{i,Length[n]}]

CantorDust[{2,3,1}]

Exploration: Seidel’s Polyhedron

The Seidel polyhedron is a cuboid with tunnels in every direction that never cross. You can build this directly using MeshRegion.

The idea is to build a grid of cuboid cells and decide which ones to keep. The construction will work for any other region that can be built similarly. You will need a utility that predicts how a position {(Subscript[i, 1]),(Subscript[i, 2]),(Subscript[i, 3])} in a dimension {(Subscript[d, 1]),(Subscript[d, 2]),(Subscript[d, 3])} array transforms into a position j when flattened. The basic formula is given by j=1+((Subscript[i, 3])-1)+(Subscript[d, 3])((Subscript[i, 2])-1)+(Subscript[d, 3])(Subscript[d, 2])((Subscript[i, 1])-1).

IndexFlatten[i_List,d_List]:=1+FoldList[Times,1,Most[Reverse[d]]].Reverse[(i-1)]

IndexFlatten[{(Subscript[i, 1]),(Subscript[i, 2]),(Subscript[i, 3])},{(Subscript[d, 1]),(Subscript[d, 2]),(Subscript[d, 3])}]

Extract[Array[a,{2,3,4}],{1,3,2}]

Extract[Flatten[Array[a,{2,3,4}]],IndexFlatten[{1,3,2},{2,3,4}]]

Now build the MeshRegion corresponding to any array.

ArrayGridMesh[a_List]/;ArrayQ[a]&&ArrayDepth[a]==3:=
Module[{m,n,p,pa,ia,re},
{m,n,p}=Dimensions[a];
pa=Table[{x,y,z},{x,0,m},{y,0,n},{z,0,p}];
re={{1,1,1},{2,1,1},{2,2,1},{1,2,1},{1,1,2},{2,1,2},{2,2,2},{1,2,2}};
ia=Table[IndexFlatten[#,{m,n,p}+1]&/@TranslationTransform[ind-1][re],{ind,Position[a,1]}];
MeshRegion[Flatten[pa,2],Hexahedron[ia]]
]

Use this to convert any array to a MeshRegion.

ArrayGridMesh[{{{1,1,1},{1,0,1},{1,1,1}},
{{1,1,1},{1,0,1},{1,1,1}},{{1,1,1},{1,0,1},{1,1,1}}}]

ArrayGridMesh[CellularAutomaton[{14, {2, 1}, {1, 1}},{{{1}},0},10]]

Defining Seidel’s polyhedron is then about defining the right array. Some experimentation gives something reasonably simple.

SeidelMesh[{r_,s_,t_}]:=
ArrayGridMesh[Table[If[Mod[i,4]==2&&Mod[j,4]==2||Mod[i,4]==0&&Mod[k,4]==0||Mod[j,4]==0&&Mod[k,4]==2,0,1],{i,3+r 4},{j,3+s 4},{k,3+t 4}]]

SeidelMesh[{1,1,1}]

By converting to BoundaryMeshRegion and controlling some styling, you get the desired result.

HighlightMesh[BoundaryMesh@SeidelMesh[{2,2,2}],{Style[1,None],Style[2,Opacity[0.5]]}]

HighlightMesh[BoundaryMesh@SeidelMesh[{4,4,4}],{Style[1,None],Style[2,Opacity[0.5]]}]

Exploration: RegionNearest and Voronoi Diagrams

A Voronoi diagram for points {(Subscript[p, 1]),…,(Subscript[p, n])} is a mesh region with a cell (Subscript[c, i]) for each point (Subscript[p, i]), indicating the region of points that are closer to (Subscript[p, i]) than any other point. Specifically, you have (Subscript[c, i])=(Subscript[∧, j=1,j≠i]^n)d((Subscript[p, i]),p)≤d((Subscript[p, j]),p).

pts={{1,1},{1,2},{3,1},{4,4}};

Show[VoronoiMesh[pts,{{-1,5},{-1,5}}],Graphics[{PointSize[Large],Point[pts]}]]

Or compute the cells directly through  (Subscript[c, i])=(Subscript[∧, j=1,j≠i]^n)d((Subscript[p, i]),p)≤d((Subscript[p, j]),p):

n=Length[pts];
cells=And@@@Table[EuclideanDistance[pts[[i]],{x,y}]≤EuclideanDistance[pts[[j]],{x,y}],{i,n},{j,Complement[Range[n],{i}]}];

Show[RegionPlot[cells,{x,-1,5},{y,-1,5}],Graphics[{PointSize[Large],Point[pts]}]]

This means that you can cheaply compute RegionNearest with this data structure. Since for each cell (Subscript[c, i]) you have a trivial nearest projection function (Subscript[π, i])[p]=(Subscript[p, i]), RegionNearest in effect has to compute these types of cells for points, but also for general regions.

PiecewiseValuesConditions[pw_Piecewise,simp_:Simplify]:=
Module[{vals,conds},
{vals,conds}=Transpose@First@pw;
vals=Append[vals,Last[pw]];
conds=Append[conds,simp[And@@(Not/@conds)]];
{vals,conds}
];

RegionNearest[Point[pts],{x,y}]

{vals,conds}=PiecewiseValuesConditions[%];

RegionPlot[conds,{x,-1,5},{y,-1,5}]

For a more general region it gets more complicated, because you get new cells to accommodate more projection functions.

RegionNearest[Triangle[],{x,y}]

{vals,conds}=PiecewiseValuesConditions[%];

RegionPlot[conds,{x,-1,2},{y,-1,2}]

For a standard tetrahedron:

Graphics3D[Tetrahedron[]]

RegionNearest[Tetrahedron[],{x,y,z}]

If you plot the generalized Voronoi cells for the tetrahedron, you get the following.

Lines, Planes, etc.

• 2D

• 3D

Convex Polygons and Polyhedra

• 3D

Convex Quadratic Regions

• 2D

• 3D

Exploration: Bounding Regions

Often it is useful to use approximations to a region: ℛ⊆(Subscript[ℛ, upper]), where the approximations are “simple” in some sense. There are a few of these already available in Mathematica.

cow=DiscretizeGraphics@ExampleData[{"Geometry3D","Cow"},"Graphics3D"]

RegionBounds gives a bounding box for the region.

boxCow=RegionBounds[cow]

Show[cow,Graphics3D[{Opacity[0.3],Cuboid[boxCow\[Transpose]]}]]

ConvexHullMesh gives a convex polyhedron upper bounding volume.

chCow=ConvexHullMesh[MeshCoordinates[cow]];

Show[cow,HighlightMesh[chCow,Style[{2},Opacity[0.3]]]]

Here is how you can compute the smallest volume bounding ball.

{pmin,pmax}=Transpose[boxCow];
{c1c,c2c,c3c}=RegionCentroid[Cuboid[pmin,pmax]];
rc=Norm[pmax-pmin]/2;

FindArgMin[{Volume[Ball[{c1,c2,c3},r]],RegionMember[Ball[{c1,c2,c3},r],MeshCoordinates[chCow]]},{{c1,c1c},{c2,c2c},{c3,c3c},{r,rc}}]

Show[cow,Graphics3D[{Opacity[0.4],Ball[Take[%,3],Last[%]]}]]

Or the smallest volume axis-aligned ellipsoid.

FindArgMin[{Volume[Ellipsoid[{c1,c2,c3},{r1,r2,r3}]],RegionMember[Ellipsoid[{c1,c2,c3},{r1,r2,r3}],MeshCoordinates[chCow]]},{{c1,c1c},{c2,c2c},{c3,c3c},{r1,rc},{r2,rc},{r3,rc}}]

Show[cow,Graphics3D[{Opacity[0.4],Ellipsoid[Take[%,3],Take[%,-3]]}]]

Summary

Regions

Basic Regions

Formula Regions

Mesh Regions

Derived Regions

Region Properties

Dimension Properties

Membership Properties

Moment/Integration Properties

Distance/Optimization Properties

Region Solvers

Visualizing

Integrating

Optimizing

Solving Equations & Inequalities

Solving Partial Differential Equations

Future

New in 10.0.2

Support for visualization over regions (Plot, Plot3D, ..., VectorPlot, StreamPlot, ...).

Support for optimization over mesh-based regions (NMinimize, ..., FindMinimum, ...).

Improved geometric search for mesh-based regions (RegionMember, RegionNearest, ...).

Improved discretization of 2D embedded regions.

Many more application examples.

Several other performance and robustness improvements.

Later

More and improved regions...

More and improved properties...

More and improved solvers...

More interaction with the world, e.g. 3D printing and scanning.

Whole new categories...

How to Learn More

Marketing Pages

Symbolic Geometry (Overview) [web]

Basic & Formula Regions [web]

Data & Mesh Regions [web]

PDEs & Finite Elements [web]

Guide Pages

Geometric Computation (General Overview) [product] [web]

Plane Geometry (Special Overview) [product] [web]

Solid Geometry (Special Overview) [product] [web]

Region Properties & Measures [product] [web]

Solvers over Regions [product] [web]

Basic Geometric Regions [product] [web]

Mesh-Based Geometric Regions [product] [web]

Derived Geometric Regions [product] [web]

Initialization

Display Boxes

CellDisplay: print cell without Out[nn]

CellDisplay[expr_]:=CellPrint[ExpressionCell[expr,"Output",Background->None,ShowCellLabel->False,CellFrame->False]]

FrameDisplay: frame object with standard settings for this document

FrameDisplay[expr_]:=Framed[expr,RoundingRadius->10,Background->Lighter[Gray,0.9],FrameMargins->10,FrameStyle->GrayLevel[0.5]]

Use this for definitions:

DefinitionGrid[{{duv_,dmv_},{cuv_,cmv_}}]:=
FrameDisplay@Grid[
{{SpanFromLeft,Text[Style["Univariate",FontFamily->"Helvetica"]],Text[Style["Multivariate",FontFamily->"Helvetica"]]},
{Text[Style["Discrete",FontFamily->"Helvetica"]],TraditionalForm@duv,TraditionalForm@dmv},
{Text[Style["Continuous",FontFamily->"Helvetica"]],TraditionalForm@cuv,TraditionalForm@cmv}},
Spacings->{2,4},
Dividers->{{False,True,True,False},{False,True,True,False}}
]

FormattedDefinitionGrid[{{duv_,dmv_},{cuv_,cmv_}}]:=
FrameDisplay@Style[Grid[
{{SpanFromLeft,Text[Style["Univariate",FontFamily->"Helvetica"]],Text[Style["Multivariate",FontFamily->"Helvetica"]]},
{Text[Style["Discrete",FontFamily->"Helvetica"]],duv,dmv},
{Text[Style["Continuous",FontFamily->"Helvetica"]],cuv,cmv}},
Spacings->{2,4},
Dividers->{{False,True,True,False},{False,True,True,False}}
],"Text"]

For moment definitions:

MomentDefinitionGrid[{{uvm_,uvgf_},{mvm_,mvgf_}}]:=
FrameDisplay@
Style[Grid[
{{SpanFromLeft,Text[Style["Moment",FontFamily->"Helvetica"]],Text[Style["Generating Function",FontFamily->"Helvetica"]]},
{Text[Style["Univariate",FontFamily->"Helvetica"]],TraditionalForm@uvm,TraditionalForm@uvgf},
{Text[Style["Multivariate",FontFamily->"Helvetica"]],TraditionalForm@mvm,TraditionalForm@mvgf}},
Spacings->{2,4},
Dividers->{{False,True,True,False},{False,True,True,False}}
],"Text"]

For moments:

MomentGrid[list_,type_]:=
Grid[Transpose@{list},Alignment->{Left,Automatic},Background->{None,{{Lighter[Blend[Switch[type,Moment,{Blue,Green},CentralMoment,{Red,Orange},FactorialMoment,{Magenta,Cyan},Cumulant,{Purple,Red}]],.8],White}}},Dividers->{None,{Darker[Gray,.6],{False},Darker[Gray,.6]}},ItemSize->30]

MomentTabView[dist_,n_Integer?Positive]:=
CellDisplay@TabView[{"Moment"->MomentGrid[Table[Moment[dist,k],{k,n}],Moment],"CentralMoment"->MomentGrid[Table[CentralMoment[dist,k],{k,n}],CentralMoment],"FactorialMoment"->MomentGrid[Table[FactorialMoment[dist,k],{k,n}],FactorialMoment],"Cumulant"->MomentGrid[Table[Cumulant[dist,k],{k,n}],Cumulant]}]

For moment generating functions:

MGFTabView[dist_]:=
CellDisplay@TabView[{"MGF"->MomentGeneratingFunction[dist,t],"CMGF"->CentralMomentGeneratingFunction[dist,t],"FMGF"-> FactorialMomentGeneratingFunction[dist,t],"CGF"->CumulantGeneratingFunction[dist,t],"CF"->CharacteristicFunction[dist,t]}]

FramedStatement:

FramedStatement[expr_]:=
CellDisplay@FrameDisplay@Text[Style[expr,Large,FontFamily->"Helvetica"]]

FramedMediumStatement[expr_]:=
CellDisplay@FrameDisplay@Text[Style[expr,FontSize->16,FontFamily->"Helvetica"]]

Various visualization functions:

FramedBulletList[list_]:=
CellDisplay@FrameDisplay@Text[Style[Row[Riffle[list," • "]],14,FontFamily->"Helvetica"]]

Kernel Initialization

Main Version:

$Version

$Line=0;