Automated Planar Geometry
in
Wolfram Language

Daniel McDonald, WRI
Xiaofan Zhang, WREL

(RowDefault[, (Spacer1), , (Spacer1), ])  #WolframTechConf

ABSTRACT

We present updates to the automated geometric functionality of the Wolfram Language, including adding the PlotTheme option and support for Graphics options to GeometricScene, updating the formatting and dynamic capabilities of GeometricScene, and adding the function GeometricSolveValues for solving for quantities in abstract scenes.

GEOMETRICSOLVEVALUES INTRODUCED INTO WOLFRAM LANGUAGE

Solve for the area of a quadrilateral

Define an abstract scene featuring a quadrilateral:

scene=GeometricScene[{a,b,c,d,e,f},{
PlanarAngle[{b,a,c}]==90Degree,
PlanarAngle[{a,c,b}]==45Degree,
Line[{a,d,c}],
Line[{b,f,c}],
Line[{a,e,b}],
Line[{e,f}],
GeometricAssertion[{Line[{d,f}],Line[{b,c}]},"Perpendicular"],
EuclideanDistance[a,d]==4,
EuclideanDistance[d,c]==8,
EuclideanDistance[a,e]==10,
p==Polygon[{a,e,f,d}]
}];

Visualize the scene:

RandomInstance[scene]

Solve for the area of the quadrilateral:

GeometricSolveValues[scene,Area[p]]

Solve for the area of a triangle

Consider a triangle where one point has an unknown but positive x value:

scene=GeometricScene[{{a,b,c},{x}},{
a=={0,0},b=={0,4},
c=={x,5},x>0,
Polygon[{a,b,c}]
}];
instance=RandomInstance[scene]

Compute the area of the particular triangle pictured above:

GeometricSolveValues[instance,Area[Polygon[{a,b,c}]]]

Compute the area of the triangle for any value of x:

GeometricSolveValues[scene,Area[Polygon[{a,b,c}]]]

Solve for a hypotenuse

Consider a scene featuring a right triangle with its leg lengths specified but its hypotenuse h unknown:

scene=GeometricScene[{{a,b,c},{h}},{
PolygonAngle[{a,b,c},a]==90Degree,EuclideanDistance[a,b]==1,
EuclideanDistance[a,c]==2,
h==EuclideanDistance[b,c]
}];
RandomInstance[scene]

The subvalue “AlgebraicFormulation” of a GeometricScene object gives a conjunction of constraints for that scene to be valid:

formulation=scene["AlgebraicFormulation"]

The hypotenuse h can be solved for using SolveValues on the algebraic formulation, or using GeometricSolveValues directly on the scene:

{SolveValues[Exists[{(IndexedDefault[a, 1]),(IndexedDefault[a, 2]),(IndexedDefault[b, 1]),(IndexedDefault[b, 2]),(IndexedDefault[c, 1]),(IndexedDefault[c, 2])},formulation],h,Reals],GeometricSolveValues[scene,h]}

DYNAMICALLY ADJUST QUANTITIES

One can dynamically adjust the value of a declared quantity by clicking on the scene, then adjusting the slider for that quantity. Points can still be dynamically moved.

Adjust the ratio of a polygon’s perimeter to its area:

RandomInstance[GeometricScene[{{a,b,c,d},{r}},
{poly==Polygon[{a,b,c,d}],Perimeter[poly]/Area[poly]==r,r>=1,GeometricAssertion[poly,{"Inside",Circle[{0,0},10]}]}
]]

WAYS TO STYLE GEOMETRICSCENE INSTANCES

Style[]

Brahmagupta’s theorem:

RandomInstance[GeometricScene[{a,b,c,d,e,f,m},
{GeometricAssertion[Style[Polygon[{a,b,c,d}],Purple],"Cyclic"],
GeometricAssertion[{Line[{a,Style[m,Red,FontFamily->"Courier",FontSize->20, FontWeight->Bold],c}],Line[{b,m,d}]},"Perpendicular"],
GeometricAssertion[{Style[Line[{f,m,e}],Yellow],Line[{b,e,c}]},"Perpendicular"],
Line[{a,f,d}]}],RandomSeeding->4]

GeometricStylingRules option

Thales’ theorem:

RandomInstance[GeometricScene[{a,b,c,o},
{Triangle[{a,b,c}],CircleThrough[{a,b,c},o],o==Midpoint[{a,c}]},
{PlanarAngle[{a,b,c}]==90 Degree},
GeometricStylingRules->{"PointStyle"->{Black},"StylingPatterns"->{_CircleThrough->{Red}},"ConclusionStyle"->{Purple}}
]]

Graphics options (new)

Pappus’ hexagon theorem:

RandomInstance[GeometricScene[{a,b,c,d,e,f,x,y,z},
{Line[{{a,b,c}}],Line[{d,e,f}],Line[{a,x,e}],Line[{b,x,d}],Line[{a,y,f}],Line[{c,y,d}],Line[{b,z,f}],Line[{c,z,e}],InfiniteLine[{x,z}]},
Background->Yellow,GridLines->Automatic,PlotLabel->"Pappus' hexagon theorem",LabelStyle->Directive[Red,FontFamily->"Copperplate",FontSize->20]
],RandomSeeding->4]

PlotTheme option (new)

Automatically add curated sets of the above styling elements.

USE PLOTTHEME OPTION IN GEOMETRICSCENE

Euclidean construction of an angle bisector:

scene1=RandomInstance[GeometricScene[{a,b,c,d,e,f},
{
GeometricStep[{HalfLine[{b,a}],HalfLine[{b,c}]}],
GeometricStep[{CircleThrough[{d,e},b],Line[{b,d,a}],Line[{b,e,c}]}],
GeometricStep[{CircleThrough[{e,f},d],CircleThrough[{d,f},e]}],
GeometricStep[{InfiniteLine[{b,f}]}]}
],RandomSeeding->4];
GeometricScene[scene1,PlotTheme->#,PlotLabel->#]["Graphics"]&/@{"Default","Monochrome","Detailed","Business","Marketing","Minimal","Scientific","Web","Classic","Textbook","BlackWhite","NoPointLabels"}

Finsler-Hadwiger theorem:

scene2=RandomInstance[GeometricScene[{a,b,c,d,bb,cc,dd,q,r,s,t},{GeometricAssertion[{Polygon[{a,b,c,d}],Polygon[{a,bb,cc,dd}]},"Regular","Counterclockwise"],q==Midpoint[{bb,d}],r==Midpoint[{a,c}],s==Midpoint[{b,dd}],t==Midpoint[{a,cc}],Polygon[{q,r,s,t}]}],RandomSeeding->1];
GeometricScene[scene2,PlotTheme->{#,"NoPointLabels"},PlotLabel->{#,"NoPointLabels"}]["Graphics"]&/@{"Default","Detailed","Business","Marketing","Minimal","Scientific","Web","Classic","Textbook"}

Combining different ways of styling

RandomInstance[GeometricScene[GeometricScene[{a,b,c,d,e,f},
{
GeometricStep[{HalfLine[{b,a}],HalfLine[{b,c}]}],
GeometricStep[{CircleThrough[{d,e},b],Line[{Style[b,Red],d,a}],Line[{b,e,c}]}],
GeometricStep[{CircleThrough[{e,f},d],CircleThrough[{d,f},e]}],
GeometricStep[{InfiniteLine[{b,f}]}]}
],Background->LightBlue,GeometricStylingRules->{"PointStyle"->{Blue}},PlotTheme->{"BlackWhite"}], RandomSeeding->4]

Thank you for listening