2 using System.Collections.Generic;
5 using System.Threading.Tasks;
103 get {
return _prev; }
163 Expr point = Start.Expr;
164 Expr normal =
ML[
"Normalize[Cross[{0},{1}]]"].Format(this.AsVectorExpr, Next.AsVectorExpr).FullSimplify().Eval();
165 return new Plane(point, normal);
174 get {
return ML[
"Dot[{0},{1}]"].Format(this.Plane.Normal, Opposite.Plane.Normal).Eval(); }
192 outHE.Opposite = backHE;
193 backHE.Opposite = outHE;
198 outHE._next = backHE;
199 backHE._prev = outHE;
200 backHE._next = oldNext;
214 var d =
new Dictionary<HalfEdge, HalfEdge>();
236 prev.LinkNext(Opposite.Next);
237 Opposite.Prev.LinkNext(
Next);
238 Opposite.Facet.Head = null;
239 foreach (var halfEdge
in prev.HEsFromHere)
241 halfEdge.Facet =
Facet;
247 return String.Format(
"[{0} to {1}]",
Start,
End);
269 var he = this.Next.Opposite;
273 he = he.Next.Opposite;
283 get {
return ML[
"Dot"].Bracket(this.AsVectorExpr, this.Next.EndPointPacket.Opposite.AsVector).Eval(); }
293 return ML[
"ArcCos[{0}] / ({1} * {2})"].Format(this.DotNext, this.EndPointPacket.Magnitude,
294 this.Next.EndPointPacket.Magnitude).Eval();
305 return this.CycleAboutEndPoint.Select(he => he.AngleToNext).Aggregate((a1, a2) =>
ML[
"{0} + {1}"].Format(a1,a2).Eval());
314 get {
return ML[
"2*Pi - {0}"].Format(
SumAngles).Eval(); }
322 get {
return ML[
"List[ {{ Thick, Red, Arrow[ {{ {0},{1} }} ] }} ]"].Format(Start.Expr, End.Expr).Eval(); }
336 get {
return littleLine; }
348 LittleLine.LinkNext(line2);
349 line2.LinkNext(line3);
361 get {
return ML[
"List[ {{Purple, Arrow[ {{ {0}, {0} + {1} }} ] }} ]"].Format(End.Expr,
Plane.Normal).Eval(); }
380 || (Opposite.Start !=
End)
388 public void Unfold(IEnumerable<PointRef> stowaways = null, IEnumerable<HalfEdge> stowawayHalfEdges = null)
391 if (stowaways == null)
393 stowaways = Enumerable.Empty<
PointRef>();
395 if (stowawayHalfEdges == null)
397 stowawayHalfEdges = Enumerable.Empty<
HalfEdge>();
400 var transVect = Vector.FromPoints(this.Start.Expr, Opposite.End.Expr);
401 var translation =
ML[
"TranslationTransform"].Bracket(transVect.Expr).Eval();
403 foreach (var stowaway
in stowaways)
405 stowaway.Transform(translation);
407 foreach (var halfedge
in stowawayHalfEdges)
409 halfedge.Transform(translation,
410 includeStart: !halfedge.Start.EqualsAny(
Start,
End),
411 includeEnd: !halfedge.End.EqualsAny(Start,
End));
414 var rotation1 =
ML[
"RotationTransform"].Bracket(
417 Opposite.Plane.Normal
422 foreach (var stowaway
in stowaways)
424 stowaway.Transform(rotation1);
426 foreach (var halfedge
in stowawayHalfEdges)
428 halfedge.Transform(rotation1,
429 includeStart: !halfedge.Start.EqualsAny(
Start,
End),
430 includeEnd: !halfedge.End.EqualsAny(Start,
End));
433 var rotation2 =
ML[
"RotationTransform"].Bracket(
436 ML[
"-1 * {0}"].Format(Opposite.AsVectorExpr).Eval()
441 foreach (var stowaway
in stowaways)
443 stowaway.Transform(rotation2);
445 foreach (var halfedge
in stowawayHalfEdges)
447 halfedge.Transform(rotation2,
448 includeStart: !halfedge.Start.EqualsAny(
Start,
End),
449 includeEnd: !halfedge.End.EqualsAny(Start,
End));
455 Start = Opposite.End;
456 End = Opposite.Start;
470 halfEdge.Transform(matrix);
475 halfEdge.Next.Start = halfEdge.End;
484 var m =
ML[
"TranslationTransform"].Bracket(
"{0,0,0}").Eval();
492 public void Anchor(IEnumerable<PointRef> stowaways)
494 if (stowaways == null)
496 stowaways = Enumerable.Empty<
PointRef>();
500 var translation =
ML[
"TranslationTransform"].Bracket(transVec).Eval();
502 foreach (var stowaway
in stowaways)
504 stowaway.Transform(translation);
508 var rotation1 =
ML[
"RotationTransform"].Bracket(
516 foreach (var stowaway
in stowaways)
518 stowaway.Transform(rotation1);
521 var rotation2 =
ML[
"RotationTransform"].Bracket(
528 foreach (var stowaway
in stowaways)
530 stowaway.Transform(rotation2);
533 var rotation3 =
ML[
"RotationTransform"].Bracket(
541 foreach (var stowaway
in stowaways)
543 stowaway.Transform(rotation3);
550 public void Transform(Expr transform,
bool includeStart =
true,
bool includeEnd =
true)
556 ML[
"{0}[{1}]"].Format(transform,
Start.
Expr).Eval());
561 ML[
"{0}[{1}]"].Format(transform,
End.
Expr).Eval());
574 return ML[
"List[{{ Dashed, Arrow[ {{ {0}, {1} }}] }}]"].Format(Start.Expr, Opposite.End.Expr).Eval();
586 var translation =
ML[
"TranslationTransform[-{0}]"].Format(v.Expr).Eval();
597 var clonePairs = HEsFromHere
598 .NetZip(clone.HEsFromHere,
599 (o, c) =>
new WorkingCopy<HalfEdge>(o,c));
600 foreach (var cp
in clonePairs)
602 cp.Copy.Facet = cp.Original.Facet;
603 cp.Copy.Opposite = cp.Original.Opposite;
616 var cloneRing = HEsFromHere
617 .Select(he => he.ShallowClone).Skip(1);
621 foreach (var he
in cloneRing.Concat(
new[] { myClone }))
623 he.Start = he.Start.DeepClone;
636 protected HalfEdge ShallowClone
656 get {
return ML[
"Mean"].Bracket(
657 ML[
"List"].Bracket(Start.Expr, End.Expr).Eval()).Eval(); }
667 var labelPoint = ML[
"{0} + .05*{1}"].Format(Midpoint,
Plane.Normal).Eval();
668 return ML[
"Inset"].Bracket(i, labelPoint,
"BaseStyle -> {Darker[Blue], Italic}").Eval();
677 public Facet ForceNewFacet
681 return new Facet(
this);
692 var dontGrab =
new HashSet<HalfEdge>();
693 var queue =
new Queue<HalfEdge>();
694 var grab =
new List<HalfEdge>();
697 dontGrab.UnionWith(this.Opposite.HEsFromHere.ToHashSet());
699 while (queue.Count > 0)
701 var he = queue.Dequeue();
702 if (dontGrab.Contains(he))
706 dontGrab.UnionWith(he.HEsFromHere.ToHashSet());
708 var opposites = he.HEsFromHere.Skip(1).Select(h => h.Opposite).ToList();
709 var validOpps = opposites
710 .Where(h => !dontGrab.Contains(h))
711 .Where(h => includeTorn || !h.Torn).ToList();
712 foreach (var halfedge
in validOpps)
714 queue.Enqueue(halfedge);
721 public IEnumerable<PointRef> StartPointsFromHere
723 get {
return HEsFromHere.Select(he => he.Start); }
732 var facetHesTorn = HEsFromHere.Select(he => he.Torn).ToList();
734 var hes = BreadthFirstGrabAll();
740 var facetHes_facetHesTorn = HEsFromHere.NetZip(facetHesTorn, (he, b) =>
new Tuple<HalfEdge,bool>(he,b));
741 foreach (var tuple
in facetHes_facetHesTorn)
744 bool wasTorn = tuple.Item2;
748 h.Start = h.Opposite.End;
749 h.End = h.Opposite.Start;
756 return BreadthFirstGrab().Except(
new[] {
this}).SelectMany(he => he.StartPointsFromHere).Except(
new[] {Start,End}).ToHashSet();
761 return BreadthFirstGrab().Except(
new[] {
this}).SelectMany(he => he.HEsFromHere).ToHashSet();
Expr Graphics
Give a graphical representation of the link between this HalfEdge and its opposite.
void Transform(Expr transform, bool includeStart=true, bool includeEnd=true)
Transforms just this HalfEdge.
HalfEdge FacetRingClone
Clones all the HalfEdges in this HalfEdge's facet
IEnumerable< HalfEdge > BreadthFirstGrabAll()
void MergeAcross()
Removes this HalfEdge and joins two neighboring facets
PointRef End
Reference to the end point of this HalfEdge.
IEnumerable< PointRef > BreadthFirstPoints()
Expr SumAngles
Sum of all angles around this vertex
static HalfEdge Facetable
For testing
IEnumerable< HalfEdge > HEsFromHereReversed
Enumerates the halfedges around the facet that this binds, but in reverse order.
Vector AsVector
Gives the displacement vector from Start to End, as a Vector object.
static HalfEdge LittleLine
For testing
HalfEdge Opposite
The HalfEdge which represnts the same edge but bounds a neighboring facet
string Tag
A string used to identify this HalfEdge. Not used in code, but useful for debugging.
HalfEdge Next
The next HalfEdge going counterclockwise
HalfEdge(PointRef start, PointRef end)
Expr Expr
Mathematica expression that represents a point in space
EndPointPacket Opposite
An EndPointPacket with the start and end points swapped
HalfEdge[] DetourToVertex(PointRef p)
Create a pair of Half-Edges following this one, which go from this's End to p, and back again ...
PointRef Start
Reference to the start point of this HalfEdge.
void Unfold(IEnumerable< PointRef > stowaways=null, IEnumerable< HalfEdge > stowawayHalfEdges=null)
Moves the entire Facet so that it is coplanar with the neighbor opposite this HalfEdge.
void Anchor(IEnumerable< PointRef > stowaways)
Moves the facet so that this HalfEdge's start point is at the origin, the EndPoint is in the directio...
A container for a Halfedge's start and end points. An immutable container.
Holds a reference to a point in the form of a Mathematica expression
static PointRef Ref010
For testing use
bool OppIsNull
Returns true iff opposite is null
IEnumerable< HalfEdge > CycleAboutEndPoint
Enumerates all HalfEdges which have End as their end point
void UselessTransform()
Transforms the facet by translating it {0,0,0}. In other words, doesn't move the facet at all...
Plane Plane
Gives the plane containing this HalfEdge
EndPointPacket EndPointPacket
Exports the EndpointPacket for this HalfEdge
static PointRef OriginRef
For testing use
HalfEdge Prev
The previous Halfedge
Facet Facet
Reference to the Facet that owns this HalfEdge.
bool DontCycle
Designates that this HalfEdge should break the cycle if the CycleBoutEndPoint property is called...
The building blocks of a geometric model, a HalfEdge consists of a reference to a start and end point...
Expr Label(int i)
Returns a Mathematica graphics primitive for an inset label above this HalfEdge.
HalfEdge FacetCloneWithOriginalOpposites
Clones all the HalfEdges in this HalfEdge's facet, then gives each HalfEdge a link to the (original) ...
bool Torn
Returns true iff this HalfEdge's opposite is not made of the same point reference as this...
Facets are little more than a link to a HalfEdge, but they provide a convenient interface for manipul...
Expr DotNext
Turns the dot product of this and next
void MoveStartPoint(Expr p)
Expr AsVector
The displacement vector from Start to End
Dictionary< HalfEdge, HalfEdge > LinkNext(HalfEdge he)
Links a HalfEdge to this one and saves references to possibly unlinked HalfEdges
Expr NormalGraphics
Graphics Primitive to visualize the Normal of this HalfEdge.
Expr Highlight
A graphics primitive that indicates this HalfEdge with a Thick Red Arrow.
A polyhedron! It contains a list of facets.
static PointRef Ref100
For testing use
void TransformFacet(Expr matrix)
Transforms every HalfEdge in the facet by a matrix.
Expr Normal
Normal to the plane
EndPointPacket OppositesEndPointPacket
Exports the OppositeEndpointPacket for this HalfEdge
Expr AngleToNext
Angle between this and next
string Tag
A tag string for this facet. Useful for debugging.
Expr Curvature
Curvature of this vertex
IEnumerable< HalfEdge > HEsFromHere
Enumerates the halfedges around the facet that this binds
Point-normal representation of the plane containing this HalfEdge. An immutable container.
override string ToString()
void CascadingUnfold(Polyhedron p)
Unfolds along a halfedge and moves whole sections of the polyhedron with it.
static Expr Origin
For testing use
Expr DotOpposite
Dots this halfedge's facet with the facet's neighbor along this halfedge.
HalfEdge ShallowClone
Creates a "Shallow Clone" of this HalfEdge, using the original Start, End, Next, and Prev...
IEnumerable< HalfEdge > BreadthFirstGrab(bool includeTorn=false)
Creates a list of all connected half-edges in Breadth-First order, starting from here.
Expr AsVectorExpr
Gives the displacement vector from Start to End
void NegativeTranslate(Vector v)
Translates this HalfEdge in the opposite direction as the vector v.