How to use Wolfram(Alpha) to calculate location of three overlapping Circles
How to use Wolfram(Alpha) to calculate location of three overlapping Circles
Werner Geiger, 07.05.2023
Note: I think WolframAlpha is not able to do this.
Note: I think WolframAlpha is not able to do this.
In response to Don Baechtel: https://community.wolfram.com/groups/-/m/t/2915829
I have three sensors, and each sensor provides the distance to a person. The distance sensed provides a Radius for the person in a circle around the sensor. But the distances sensed are not exact, only approximate. It may be off by several feet. So the Radii of the three circles may not overlap, or they may intersect at one point, or the circles may overlap without intersecting exactly at one point. This may be corrected, if necessary, by increasing the radii proportionally until the three circles overlap each other. Once the circles overlap each other, the person’s approximate location can be found by calculating the center of the overlapped area.
How can Wolfram Alpha give the person’s location from the distance reported by three sensors? What are the methods to do this?
I have three sensors, and each sensor provides the distance to a person. The distance sensed provides a Radius for the person in a circle around the sensor. But the distances sensed are not exact, only approximate. It may be off by several feet. So the Radii of the three circles may not overlap, or they may intersect at one point, or the circles may overlap without intersecting exactly at one point. This may be corrected, if necessary, by increasing the radii proportionally until the three circles overlap each other. Once the circles overlap each other, the person’s approximate location can be found by calculating the center of the overlapped area.
How can Wolfram Alpha give the person’s location from the distance reported by three sensors? What are the methods to do this?
My Solution
My Solution
I have some sensors and their readings for i=1, …, sCnt.
This defines sCnt circles around with radius .
A point on a circle is defined by its angle which denotes the radius angle in its circle.
The person is at location p where the sum of the squared distances from p to all circle points is at a minimum.
S
i
dist
i
This defines sCnt circles around
S
i
dist
i
A point
C
i
α
i
The person is at location p where the sum of the squared distances from p to all circle points is at a minimum.
We define some functions draw…[…] which draw the problem.
We define a function calcDistFunc[{p,,… }}, dists, sensors] which calculates this sum to be minimized for a given point p and given circle points (i.e. given angles ).
From that we can use the WL-function Minimize[fun, vars] to solve the problem.
This is done by calcMinCPs[dists, sensors]. It returns {p,,… }}, i.e. the persons location p and the circle points where the minimum is achieved.
Note: Just for fun we define similar functions
calcMinCPsA[p, dists, sensors] and calcMinCPsP[,… }, dists, sensors] which do the same for fixed p and fixed respectively.
We define a function calcDistFunc[{p,
{
α
i
C
i
α
i
From that we can use the WL-function Minimize[fun, vars] to solve the problem.
This is done by calcMinCPs[dists, sensors]. It returns {p,
{
α
i
C
i
Note: Just for fun we define similar functions
calcMinCPsA[p, dists, sensors] and calcMinCPsP[
{
α
i
α
i
Initialize
Initialize
In[]:=
ClearAll["Global`*"];SetOptions[$FrontEnd,Language"English"]
In[]:=
testLvl=0;sensorsDef={{3,-2},{0,3},{-2,-1}};distsDef={2,2.5,4};sCntDef=Length[sensorsDef];sensorsDef4={{3,-2},{0,3},{-2,-1},{-3,3}};distsDef4={2,2.5,4,1.5};sCntDef4=Length[sensorsDef4];
Presentation
Presentation
drawSRs[dists:distsDef, {withRad:True, withLeg:True}, sensors:sensorDefs, size:300] draws the sensors at locations sensors and their reading circles of radius dists.
withRad draws the circle radius.
withLeg draws a legend.
size is the size of the drawing.
The whole parameter {withRad, withLeg} can be omitted.
Returns a Graphics
withRad draws the circle radius.
withLeg draws a legend.
size is the size of the drawing.
The whole parameter {withRad, withLeg} can be omitted.
Returns a Graphics
In[]:=
ClearAll[drawSRs];drawSRs[dists:{(_?NumericQ)..}:distsDef,sensors:{{_?NumericQ,_?NumericQ}..}:sensorsDef]:=drawSRs[dists,{},sensors];drawSRs[dists:{(_?NumericQ)..}:distsDef,{withRad:(_?BooleanQ):True,withLeg:(_?BooleanQ):True,size_:300},sensors:{{_?NumericQ,_?NumericQ}..}:sensorsDef]:=Module[{myName="drawSRs",lvl0=15,cols={Red,Green,Blue},fs=12,sCnt,snames,pCenter,pLR},If[testLvl>=lvl0,Echo[Column[{dists,{withRad,withLeg,size},sensors}],myName<>".{dists,{withRad,withLeg,size},sensors}: "]];sCnt=Length[sensors];assertTxt[Length[dists]==sCnt,myName."Wrong dists call!"];(*Sensornames*)snames=Table[Style[Subscript["S",i],Bold,fs,ScriptMinSize->fs-1],{i,sCnt}];(*Sensorscenter*)pCenter=Mean[sensors];(*Lowerrightpointforlegend*)pLR=sensorsDef+((#*{1,-1})&/@distsDef);pLR={Max[pLR[[All,1]]],Min[pLR[[All,2]]]}+{1,0};(*Draw*)Graphics[{(*sensorsPolygonandcenter*){FaceForm[GrayLevel[0.9]],ConvexHullMesh[sensors]},Black,AbsolutePointSize[3],Point[pCenter],(*Sensorsandreadings*)PointSize[Large],Table[{cols[[Mod[i,3,1]]],If[withRad,{Dashed,Thickness[Medium],Line[{sensors[[i]],sensors[[i]]-dists[[i]]*Normalize[pCenter-sensors[[i]]]}]},Nothing],Point[sensors[[i]]],Thickness[Small],Circle[sensors[[i]],dists[[i]]],Inset[snames[[i]],sensors[[i]],{2,-1}]},{i,sCnt}],(*Legend*)If[withLeg,Inset[Framed[PointLegend[Table[cols[[Mod[i,3,1]]],{i,sCnt}],snames],Background->GrayLevel[0.9],FrameStyle->None],pLR,{-1,-1}],Nothing]},Axes->True,AxesOrigin->{0,0},ImageSize->size]];
In[]:=
Block[{testLvl=0*15},Print[Row[{drawSRs[],drawSRs[distsDef,{False,False}]},"\t"]];Print[Row[{drawSRs[distsDef4,{},sensorsDef4],drawSRs[distsDef4,{False,False},sensorsDef4]},"\t"]];];
drawCPs[{p, αs}, dists:distsDef, sensors:sensorDefs, size:300] draws the locations and distances of a point p from the sensor reading circle points at angles αs.
For the other parameters see function drawSRs.
Returns a Graphics
For the other parameters see function drawSRs.
Returns a Graphics
In[]:=
ClearAll[drawCPs];drawCPs[{p:{_?NumericQ,_?NumericQ},αs:{(_?NumericQ)..}},dists:{(_?NumericQ)..}:distsDef,sensors:{{_?NumericQ,_?NumericQ}..}:sensorsDef,size_:300]:=Module[{myName="drawCPs",lvl0=15,cols={Red,Green,Blue},colP=Darker[Orange],fs=12,sCnt,cnames,cPs},If[testLvl>=lvl0,Echo[Column[{p,αs,dists,sensors,size}],myName<>".{p,αs,dists,sensors,size}: "]];sCnt=Length[sensors];assertTxt[Length[αs]==sCnt,myName."Wrong αs call!"];assertTxt[Length[dists]==sCnt,myName."Wrong dists call!"];(*Circlepoints*)cnames=Table[Style[Subscript["C",i],fs,ScriptMinSize->fs-1],{i,sCnt}];cPs=Table[sensors[[i]]+dists[[i]]*{Cos[αs[[i]]],Sin[αs[[i]]]},{i,sCnt}];(*Draw*)Graphics[{(*circlepointsanddistancestop*)PointSize[Medium],Thickness[Medium],Table[{cols[[Mod[i,3,1]]],Line[{cPs[[i]],p}],Point[cPs[[i]]],Inset[cnames[[i]],cPs[[i]],{2,1}]},{i,sCnt}],(*Pointp*)colP,Point[p],Inset[Style["P",Bold,fs],p,{-2,1}]},Axes->True,AxesOrigin->{0,0},ImageSize->{Automatic,size}]];
In[]:=
Block[{testLvl=0*15},Row[{drawCPs[{{4,5},{0°,0°,0°}}],drawCPs[{{4,5},{0°,0°,0°,0°}},distsDef4,sensorsDef4]},"\t"]]
Out[]=
makePαL[p, αs] returns a well readable text of point p and angles αs.
makeDL[dists] returns a well readable text of distances dists.
draw[{p, αs}, dists:distsDef, {pl:””, withRad:True, withLeg:True, size:400}, sensors:sensorDefs] draws the sensors at locations sensors and their reading circles of radius dists together with the distances of a point p from the sensor reading circle points at angles αs.
pl is a PlotLabel. If None, no label. If “”, a default label.
For the parameters see functions drawSRs and drawCPs.
Returns a Graphics
pl is a PlotLabel. If None, no label. If “”, a default label.
For the parameters see functions drawSRs and drawCPs.
Returns a Graphics
Calculations
Calculations
calcMinCPs - The solution to the problem
calcMinCPs - The solution to the problem
Auto-Save
Auto-Save
General Init
General Init
Initialization Functions
Initialization Functions
Enhanced Assert functions
Enhanced Assert functions
Those functions provide some better readable Assert messages and some enhanced Assert-functions:
assertState[] gets current Assert-state.
onAssert[] switch on Assert with a nicer $AssertFunction. Returns the previous state.
offAssert[] switch off Assert. Returns the previous state.
onoffAssert[], toggles the Assert-state. Returns the previous state.
assertGo[test, tag, goLbl, txt] has an additional Goto-label and text. If the assertion fails, the text is outputted and the program jumps to goLbl.
assertTxt[tes, tag, txt] has an additional text. If the assertion fails, the text is outputted.
assertBody[tes, tag, body] has an additional body of statements. If the assertion fails, the body is executed. body can be a sequence of statements in parentheses, a Block or a Module.
assertState[] gets current Assert-state.
onAssert[] switch on Assert with a nicer $AssertFunction. Returns the previous state.
offAssert[] switch off Assert. Returns the previous state.
onoffAssert[], toggles the Assert-state. Returns the previous state.
assertGo[test, tag, goLbl, txt] has an additional Goto-label and text. If the assertion fails, the text is outputted and the program jumps to goLbl.
assertTxt[tes, tag, txt] has an additional text. If the assertion fails, the text is outputted.
assertBody[tes, tag, body] has an additional body of statements. If the assertion fails, the body is executed. body can be a sequence of statements in parentheses, a Block or a Module.