PolyLink
A library to allow manipulation of geometry from within Mathematica
 All Classes Namespaces Files Functions Variables Properties
VectorCone.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 PolyLink
9 {
10  public struct ConeReturn
11  {
12  public VectorCone Left { get; set; }
13  public VectorCone Right { get; set; }
14 
15  public static ConeReturn Failed
16  {
17  get
18  {
19  return new ConeReturn
20  {
21  Left = null,
22  Right = null,
23  };
24  }
25  }
26  }
27 
28  public class VectorCone : MathLinked
29  {
30  private bool _valid;
31 
32  private readonly VectorCone _parent;
33  private VectorCone _left;
34  private VectorCone _right;
35  private readonly WorkingCopy<HalfEdge> _currentEdge;
36  private readonly Vector _lBind;
37  private readonly Vector _rBind;
38  private readonly VectorCSPF _cspf;
39  private readonly PointRef _transformedEndPoint;
40 
41  public VectorCone(VectorCone parent, WorkingCopy<HalfEdge> currentEdge, VectorCSPF cspf, Vector lBind, Vector rBind, PointRef transformedEndPoint)
42  {
43  _parent = parent;
44  _currentEdge = currentEdge;
45  _cspf = cspf;
46  _lBind = lBind;
47  _rBind = rBind;
48  _valid = true;
49  _transformedEndPoint = transformedEndPoint;
50  }
51 
52  public Facet CurrentFacet
53  {
54  get { return CurrentEdge.Original.Facet; }
55  }
56 
57  public string CurrentFacetTag
58  {
59  get { return CurrentEdge.Original.Facet.Tag; }
60  }
61 
62  public bool Valid
63  {
64  get { return _valid; }
65  }
66 
67  public WorkingCopy<HalfEdge> CurrentEdge
68  {
69  get { return _currentEdge; }
70  }
71 
72  public Vector LBind
73  {
74  get { return _lBind; }
75  }
76 
77  public Vector RBind
78  {
79  get { return _rBind; }
80  }
81 
82  public void Invalidate()
83  {
84  if (_left != null)
85  {
86  _left.Invalidate();
87  }
88  if (_right != null)
89  {
90  _right.Invalidate();
91  }
92  _valid = false;
93  }
94 
96  {
97  if (_transformedEndPoint != null)
98  {
99  var vectorToEnd = new Vector(_transformedEndPoint.Expr);
100  if (!_cspf.SeeIfConeHasShortestPath(this, vectorToEnd, _cspf.EndPoint))
101  {
102  Invalidate();
103  return ConeReturn.Failed;
104  }
105  }
106 
107  var oppPoint = CurrentEdge.Copy.Next.End;
108  var vectorToOpp = new Vector(oppPoint.Expr);
109 
110  var lCompare = VectorMath.SignedAngle(vectorToOpp, LBind).CompareTo();
111  var rCompare = VectorMath.SignedAngle(vectorToOpp, RBind).CompareTo();
112 
113  if (lCompare == 0 || lCompare != rCompare)
114  {
115  if (!_cspf.SeeIfConeHasShortestPath(this, vectorToOpp, CurrentEdge.Original.Next.End))
116  {
117  Invalidate();
118  return ConeReturn.Failed;
119  }
120  }
121 
122  if (lCompare.EqualsAny(0, 1))
123  {
124  var leftHE = CurrentEdge.Original.Prev.Opposite;
125  var newHE = new WorkingCopy<HalfEdge>(leftHE, leftHE.FacetCloneWithOriginalOpposites);
126 
127  IEnumerable<PointRef> newEndPoint = null;
128 
129  //Move the new working copy.
130  if (newHE.Original.Facet == _cspf.EndFacet)
131  {
132  newEndPoint = new[] {_cspf.EndPoint.DeepClone};
133  }
134  newHE.Copy.Opposite = CurrentEdge.Copy.Prev;
135  newHE.Copy.Unfold(newEndPoint);
136  newHE.Copy.Opposite = CurrentEdge.Original.Prev;
137 
138  var rBind = (rCompare > 0) ? vectorToOpp : RBind;
139 
140  PointRef endPoint = (newEndPoint != null) ? newEndPoint.First() : null;
141 
142  _left = new VectorCone(
143  parent: this,
144  currentEdge: newHE,
145  cspf: _cspf,
146  lBind: LBind,
147  rBind: rBind,
148  transformedEndPoint: endPoint
149  );
150  }
151 
152  if (rCompare.EqualsAny(0, -1))
153  {
154  var rightHE = CurrentEdge.Original.Next.Opposite;
155  var newHE = new WorkingCopy<HalfEdge>(rightHE, rightHE.FacetCloneWithOriginalOpposites);
156 
157  IEnumerable<PointRef> newEndPoint = null;
158 
159  //Move the new working copy.
160  if (newHE.Original.Facet == _cspf.EndFacet)
161  {
162  newEndPoint = new[] { _cspf.EndPoint.DeepClone };
163  }
164  newHE.Copy.Opposite = CurrentEdge.Copy.Next;
165  newHE.Copy.Unfold(newEndPoint);
166  newHE.Copy.Opposite = CurrentEdge.Original.Next;
167 
168  PointRef endPoint = (newEndPoint != null) ? newEndPoint.First() : null;
169 
170  var lBind = (lCompare < 0) ? vectorToOpp : LBind;
171 
172  _right = new VectorCone(
173  parent: this,
174  currentEdge: newHE,
175  cspf: _cspf,
176  lBind: lBind,
177  rBind: RBind,
178  transformedEndPoint: endPoint
179  );
180  }
181 
182  return new ConeReturn
183  {
184  Left = _left,
185  Right = _right,
186  };
187  }
188 
189  public Expr Aperture
190  {
191  get { return VectorMath.SignedAngle(RBind, LBind); }
192  }
193 
194  public IEnumerable<VectorCone> ChainToParents
195  {
196  get
197  {
198  var x = this;
199  while (x != null)
200  {
201  yield return x;
202  x = x._parent;
203  }
204  }
205  }
206 
207  public string Representation
208  {
209  get
210  {
211  return "Graphics3D[" + ML["List"].Bracket(
212  ML["List"].Bracket(ChainToParents.Select(p => p.CurrentEdge.Copy.ForceNewFacet.Graphics)).Eval(),
213  ML["Arrow"].Bracket(ML["List"].Bracket(PointRef.Origin, LBind.Expr).Eval()).Eval(),
214  ML["Arrow"].Bracket(ML["List"].Bracket(PointRef.Origin, RBind.Expr).Eval()).Eval(),
215  _cspf.StartGraphics
216  ).Eval().ToString() + "]";
217  }
218  }
219  }
220 
221  static class VectorMath
222  {
223  public static Expr SignedAngle(Vector vector1, Vector vector2)
224  {
225  return "Sign[Dot[{{ -{0}[[2]], {0}[[1]], 0 }}, {1}]]*ArcCos[Dot[Normalize[{0}], Normalize[{1}]]]"
226  .MsEvalWith(vector1.Expr, vector2.Expr);
227  }
228  }
229 }