PolyLink
A library to allow manipulation of geometry from within Mathematica
 All Classes Namespaces Files Functions Variables Properties
Polyhedron.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 using MoreLinq;
8 
9 namespace PolyLink
10 {
14  public class Polyhedron : MathLinked
15  {
16  public Polyhedron()
17  {
18  _facets = new List<Facet>();
19  }
20 
21  private List<Facet> _facets;
22 
23  public IEnumerable<Facet> Facets
24  {
25  get { _facets.RemoveAll(f => f.Head == null);
26  return _facets;
27  }
28  }
29 
30  public Facet[] FacetArray
31  {
32  get { return Facets.ToArray(); }
33  }
34 
35  public Expr Graphics
36  {
37  get
38  {
39  return ML["List"].Bracket(
40  ML["List"].Bracket(Facets.Select(f => f.Graphics)).Eval()
41  ).Eval();
42  }
43  }
44 
45  public IEnumerable<HalfEdge> HalfEdges
46  {
47  get { return Facets.SelectMany(f => f.HalfEdges); }
48  }
49 
50  public void AddFacet(Facet f)
51  {
52  _facets.Add(f);
53  }
54 
55  public void AddFacets(IEnumerable<Facet> facets)
56  {
57  _facets.AddRange(facets);
58  }
59 
60  public void AddFacets(Facet[] facets)
61  {
62  _facets.AddRange(facets);
63  }
64 
65  public IEnumerable<HalfEdge> OutOfOrderHalfEdges
66  {
67  get
68  {
69  return HalfEdges.Where(he => he.Next.Start != he.End);
70  }
71  }
72 
73  public Expr HalfEdgeGraphics
74  {
75  get
76  {
77  return ML["List"].Bracket(
78  ML["List"].Bracket(HalfEdges.Select(he => he.Graphics).Where(g => g != null)).Eval()
79  ).Eval();
80  }
81  }
82 
83  public IEnumerable<Facet[]> SlowDangerousIntersectionTest()
84  {
85  return (from f1 in _facets
86  from f2 in _facets
87  where (_facets.IndexOf(f1) > _facets.IndexOf(f2))
88  select new[] {f1, f2})
89  .Where(fp =>
90  fp[0].CheckIntersectSlow(fp[1]) ||
91  fp[1].CheckIntersectSlow(fp[0])
92  );
93  }
94 
95  public IEnumerable<Facet[]> ConvexAssumingInteresectionTest()
96  {
97  if (!Facets.All(f => f.Convex))
98  {
99  throw new Exception("Only run this when all the facets are convex!");
100  }
101 
102  return (from f1 in _facets
103  from f2 in _facets
104  where (_facets.IndexOf(f1) > _facets.IndexOf(f2))
105  select new[] { f1, f2 })
106  .Where(fp =>
107  fp[0].CheckIntersectSlow(fp[1]) ||
108  fp[1].CheckIntersectSlow(fp[0])
109  );
110  }
111 
112  public void Triangulate()
113  {
114  var newFacets = Facets.SelectMany(f => f.Triangulate()).ToList();
115  _facets.AddRange(newFacets);
116  }
117 
118  public void MakeNumerical()
119  {
120  var prs = HalfEdges.Select(he => he.Start).Distinct();
121  foreach (var pointRef in prs)
122  {
123  pointRef.Expr = ML["N"].Bracket(pointRef.Expr).Eval();
124  }
125  }
126 
128  {
129 
130  var clonePoly = new Polyhedron();
131 
132  var cloneDex = new Dictionary<HalfEdge, HalfEdge>();
133 
134  foreach (var facet in Facets)
135  {
136  var f = facet.CloneWithAllHalfEdgesCloned;
137 
138  var originalClonePairs = facet.HalfEdges
139  .NetZip(f.HalfEdges,
140  (orignal, clone) => new KeyValuePair<HalfEdge, HalfEdge>(orignal, clone));
141 
142  foreach (var pair in originalClonePairs)
143  {
144  cloneDex.Add(pair.Key, pair.Value);
145  }
146 
147  clonePoly.AddFacet(f);
148  }
149 
150  foreach (var kvp in cloneDex)
151  {
152  var oppositeClone = cloneDex[kvp.Key.Opposite];
153  kvp.Value.Opposite = oppositeClone;
154  }
155 
156  return clonePoly;
157 
158  }
159 
161  {
162  foreach (var f in Facets)
163  {
164  f.ForceHalfEdgesToReferenceThis();
165  }
166  }
167 
168 
169  public Expr NormalGraphics
170  {
171  get { return Labelize((i, f) => f.NormalGraphics); }
172  }
173 
174  public Expr Labels
175  {
176  get { return Labelize((i, f) => f.ClipLabel(i)); }
177  }
178 
179  public Expr InsetLabels
180  {
181  get { return Labelize((i, f) => f.InsetLabel(i)); }
182  }
183 
184  public void TagFacets()
185  {
186  var facetIndices = Enumerable.Range(1, int.MaxValue)
187  .NetZip(Facets, (i, f) => new Tuple<int, Facet>(i,f));
188  foreach (var fi in facetIndices)
189  {
190  fi.Item2.Tag = fi.Item1.ToString();
191  }
192 
193  }
194 
195  public Expr Labelize(Func<int, Facet, Expr> labelizer)
196  {
197  var labels = Enumerable.Range(1, int.MaxValue).NetZip(Facets, labelizer);
198  return
199  ML["List"].Bracket
200  (
201  ML["List"]
202  .Bracket(labels)
203  .Eval()
204  ).Eval();
205  }
206 
207  public Facet PickFacet(int n)
208  {
209  return _facets[n-1];
210  }
211 
212  public Expr AllLabels
213  {
214  get
215  {
216  return Labelize((i, f) =>
217  ML["List"].Bracket
218  (
219  ML["List"]
220  .Bracket(f.InsetLabel(i), f.HELabels)
221  .Eval()
222  ).Eval());
223  }
224  }
225 
226  public HalfEdge PickHalfEdge(int fNumber, int hNumber)
227  {
228  return PickFacet(fNumber).PickHalfEdge(hNumber);
229  }
230 
234  public void FusePoints()
235  {
236 
237  var masters = new Dictionary<string, PointRef>();
238 
239  foreach (var halfEdge in HalfEdges)
240  {
241 
242  if (!masters.ContainsKey(halfEdge.Start.Expr.ToString()))
243  {
244  masters[halfEdge.Start.Expr.ToString()] = halfEdge.Start;
245  }
246  if (!masters.ContainsKey(halfEdge.End.Expr.ToString()))
247  {
248  masters[halfEdge.End.Expr.ToString()] = halfEdge.End;
249  }
250  }
251 
252  foreach (var halfEdge in HalfEdges)
253  {
254  halfEdge.Start = masters[halfEdge.Start.Expr.ToString()];
255  halfEdge.End = masters[halfEdge.End.Expr.ToString()];
256  }
257  }
258 
259  public IEnumerable<HalfEdge> TornHalfEdges
260  {
261  get { return HalfEdges.Where(he => he.Torn); }
262  }
263  }
264 }