PolyLink
A library to allow manipulation of geometry from within Mathematica
 All Classes Namespaces Files Functions Variables Properties
Cone2.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6 using Wolfram.NETLink;
7 
8 namespace Defunct
9 {
10  /*public class Cone : MathLinked
11  {
12  private bool _valid;
13 
14  private readonly Cone _parent;
15  private Cone _left;
16  private Cone _right;
17  private readonly Expr _relativeSource;
18  private readonly Expr _relativeAngleL;
19  private readonly Expr _relativeAngleR;
20  private readonly Expr _absoluteSourceToCorner;
21  private readonly ConvexShortestPathFinder _cspf;
22  private readonly Expr _anchorMatrix;
23 
24  private readonly HalfEdge _currentCrossedHalfEdge;
25  private readonly HalfEdge _workingHECopy;
26 
27  public string Tag { get; set; }
28  public Facet CurrentFacet
29  {
30  get { return _currentCrossedHalfEdge.Facet; }
31  }
32  public string CurrentFacetTag
33  {
34  get { return _currentCrossedHalfEdge.Facet.Tag; }
35  }
36 
47  public Cone(Cone parent, Expr relativeAngleL, Expr relativeAngleR,
48  Expr absoluteSourceToCorner, Expr relativeSource,
49  HalfEdge currentCrossedHalfEdge,
50  ConvexShortestPathFinder cspf)
51  {
52  _parent = parent;
53  _relativeAngleL = relativeAngleL;
54  _relativeAngleR = relativeAngleR;
55  _relativeSource = relativeSource;
56  _currentCrossedHalfEdge = currentCrossedHalfEdge;
57  _cspf = cspf;
58  _absoluteSourceToCorner = absoluteSourceToCorner;
59  _workingHECopy = _currentCrossedHalfEdge.FacetRingClone;
60  _valid = true;
61  _anchorMatrix = _workingHECopy.AnchorMatrix;
62 
63  _workingHECopy.Anchor();
64  }
65 
66  public Cone Parent
67  {
68  get { return _parent; }
69  }
70 
71  public Cone Left
72  {
73  get { return _left; }
74  }
75 
76  public Cone Right
77  {
78  get { return _right; }
79  }
80 
81  public bool Valid
82  {
83  get { return _valid; }
84  }
85 
86  public void Invalidate()
87  {
88  if (Left != null)
89  {
90  Left.Invalidate();
91  }
92  if (Right != null)
93  {
94  Right.Invalidate();
95  }
96  _valid = false;
97  }
98 
99  public Tuple<Cone, Cone> TryExtend()
100  {
101  switch (CheckIfShortestPath())
102  {
103  case ShortestPathResult.Shortest:
104  return new Tuple<Cone, Cone>(null, null);
105  case ShortestPathResult.NotShortest:
106  Invalidate(); return new Tuple<Cone, Cone>(null, null);
107  case ShortestPathResult.NotViable:
108  break;
109  default:
110  throw new ArgumentOutOfRangeException();
111  }
112 
113  var oppositeVertex = _currentCrossedHalfEdge.Next.End;
114 
115  var sourceToOppEpp = (new EndPointPacket(new PointRef(RelativeSource), TransformOppositeVertex));
116  var sourceToOpp = sourceToOppEpp.AsVector;
117 
118  //TODO originToSource might be the opposite of what value we need in some uses. :/ :help:
119  var originToSource = ML["- {0}"].Format(RelativeSource).Eval();
120 
121  var splitAngle = SignedAngle(originToSource, sourceToOpp);
122 
123  var lCompare = _relativeAngleL.CompareTo(splitAngle);
124  var rCompare = _relativeAngleR.CompareTo(splitAngle);
125 
126  if (rCompare > lCompare)
127  {
128  throw new Exception("Right angle is left of left angle");
129  }
130  if (lCompare == 0 || lCompare != rCompare)
131  {
132  if (!_cspf.SeeIfConeHasShortestPath(this, sourceToOppEpp.Magnitude, oppositeVertex))
133  {
134  Invalidate();
135  return new Tuple<Cone, Cone>(null, null);
136  }
137  }
138  //TODO the angles need to be absolute, not relative. Otherwise this whole thing is useless!
139  //I shouldn't be using the split angle all the time, some times it is outside of the bounds of angleL and angleR
140  if (lCompare.EqualsAny(0, 1))
141  {
142  var leftHalfEdge = _currentCrossedHalfEdge.Prev.Opposite;
143 
144  var rightAngle = ML["Max"].Bracket(splitAngle, _relativeAngleR).Eval();
145 
146  _left = new Cone(parent: this,
147  relativeSource: TransformSourceLeft,
148  currentCrossedHalfEdge: leftHalfEdge,
149  relativeAngleL: _relativeAngleL,
150  relativeAngleR: rightAngle,
151  absoluteSourceToCorner: _absoluteSourceToCorner,
152  cspf: _cspf)
153  {Tag = Tag + " Left"};
154  }
155  if (rCompare.EqualsAny(0, -1))
156  {
157  var newAbsolute = ML["{0} + {1}"].Format(_absoluteSourceToCorner, splitAngle).Eval();
158 
159 
160  var rightHalfEdge = _currentCrossedHalfEdge.Next.Opposite;
161 
162  var leftAngle = ML["Min"].Bracket(
163  ML["{0}-{1}"].Format(_relativeAngleL,splitAngle).Eval(),
164  "0").Eval();
165 
166  Expr rightAngle = ML["{0} - {1}"].Format(_relativeAngleR, splitAngle).Eval();
167 
168  _right = new Cone(parent: this,
169  relativeSource: TransformSourceRight,
170  currentCrossedHalfEdge: rightHalfEdge,
171  relativeAngleL: leftAngle,
172  relativeAngleR: rightAngle,
173  absoluteSourceToCorner: newAbsolute,
174  cspf: _cspf)
175  {Tag = Tag + " Right"};
176  }
177  return new Tuple<Cone, Cone>(Left, Right);
178  }
179 
180  private enum ShortestPathResult
181  {
182  Shortest,
183  NotShortest,
184  NotViable
185  }
186 
187  private ShortestPathResult CheckIfShortestPath()
188  {
189  var originToSource = ML["- {0}"].Format(RelativeSource).Eval();
190 
191  //TODO the cone might not be able to reach the endpoint, even if it reaches the facet.
192  if (AtEndFacet)
193  {
194  var relativeEndPoint = "{0}[{1}]".MsEvalWith(_anchorMatrix, _cspf.EndPoint.Expr);
195  var sourceToEnd = new EndPointPacket((new PointRef(RelativeSource)), new PointRef(relativeEndPoint));
196  if (_cspf.SeeIfConeHasShortestPath(this, sourceToEnd.Magnitude, _cspf.EndPoint))
197  {
198  var angleToEnd = SignedAngle(originToSource, sourceToEnd.AsVector);
199  TrueAngle = "{0} + {1}".MsEvalWith(_absoluteSourceToCorner, angleToEnd);
200  return ShortestPathResult.Shortest;
201  }
202  return ShortestPathResult.NotShortest;
203  }
204  return ShortestPathResult.NotViable;
205  }
206 
207  private PointRef TransformOppositeVertex
208  {
209  get
210  {
211  return _workingHECopy.Next.End;
212  }
213  }
214 
218  private Expr TransformSourceLeft
219  {
220  get
221  {
222  var lCopy = _currentCrossedHalfEdge.Prev.Opposite.FacetRingClone;
223  lCopy.Opposite = _workingHECopy.Prev;
224  lCopy.Unfold();
225  var transform = lCopy.AnchorMatrix;
226  return ML["{0}[{1}]"].Format(transform, RelativeSource).Eval();
227  }
228  }
229 
233  private Expr TransformSourceRight
234  {
235  //TODO use AnchorMatrix instead perhaps
236  get
237  {
238  var rCopy = _currentCrossedHalfEdge.Next.Opposite.FacetRingClone;
239  rCopy.Opposite = _workingHECopy.Next;
240  rCopy.Unfold();
241  var transform = rCopy.AnchorMatrix;
242 
243  return ML["{0}[{1}]"].Format(transform, RelativeSource).Eval();
244  }
245  }
246 
247  public Expr TrueAngle { get; set; }
248 
249  public ConvexShortestPathFinder Cspf
250  {
251  get { return _cspf; }
252  }
253 
254  private Expr SignedAngle(Expr vector1, Expr vector2)
255  {
256  return VectorMath.SignedAngle(vector1, vector2);
257  }
258 
259  public Expr ApproxAperture
260  {
261  get { return ML["N[Mod[({0} - {1}), 2*Pi]]"].Format(_relativeAngleL, _relativeAngleR).Eval(); }
262  }
263 
264  public bool AtEndFacet
265  {
266  get { return _cspf.EndFacet.HalfEdges.Contains(_currentCrossedHalfEdge); }
267  }
268 
269  public Expr ApproxLength
270  {
271  get
272  {
273  var mag = (new EndPointPacket(new PointRef(RelativeSource), PointRef.OriginRef)).Magnitude;
274  return ML["N"].Bracket(mag).Eval();
275  }
276  }
277 
278  public Expr RelativeSource
279  {
280  get { return _relativeSource; }
281  }
282  }
283 
284  public static class VectorMath
285  {
286  public static Expr SignedAngle(Expr vector1, Expr vector2)
287  {
288  return "Sign[Dot[{{ -{0}[[2]], {0}[[1]], 0 }}, {1}]]*ArcCos[Dot[Normalize[{0}], Normalize[{1}]]]"
289  .MsEvalWith(vector1, vector2);
290  }
291  }*/
292 }