// Path: src/org/twak/camp/Output.java
// public class Face
// {
//     // first is outside, others are holes
//     public LoopL<Point3d> points = null;
// 
//     public Set<Tag> plan = new HashSet<>(), profile = new HashSet<>();
// 
//     // bottom edges
//     public Set<SharedEdge> definingSE = new LinkedHashSet<>();
//     // defining edges of child (top) edges
//     public Set<SharedEdge> topSE = new LinkedHashSet<>();
// 
//     // face below us in the skeleton - can be traced back to an originator
//     public Face parent;
//         
//     public GraphMap<Point3d> results = new GraphMap<>();
// 
//     // a typical edge that defines the plane normal
//     public Edge edge;
// 
//     // subset of results who are horizontal edges and whose nextL are edge, or similar.
//     public Set<Corner> definingCorners = new LinkedHashSet<>();
// 
//     public LoopL<SharedEdge> edges = new LoopL<>();
// 
//     public LoopL<Point3d> getLoopL()
//     {
//         return points;
//     }
// 
//     public int pointCount()
//     {
//         return points.count();
//     }
//     // is a defining edges of the above (child) edges
//     public boolean isTop (SharedEdge edge)
//     {
//         return topSE.contains( edge );
//     }
//     // is a defining edge
//     public boolean isBottom(SharedEdge edge)
//     {
//         return definingSE.contains(  edge );
//     }
//     // isn't a top or bottom edges
//     public boolean isSide (SharedEdge edge)
//     {
//         return !( isTop( edge ) || isBottom( edge ) );
//     }
// 
//     /**
//      * When caculating an offset, we can assume that all edges add a face at every interval
//      * this returns the number of faces below this face.
//      * @return
//      */
//     public int getParentCount()
//     {
//         int count = -1;
//         Face f = this;
//         while (f != null)
//         {
//             count++;
//             f = f.parent;
//         }
//         return count;
//     }
// 
//     private void findSharedEdges()
//     {
//         edges = new LoopL<>();
//         for (Loop <Point3d> ptLoop : points)
//         {
//             Loop<SharedEdge> loop = new Loop<>();
//             edges.add (loop);
//             // start and end points of SharedEdges **aren't** shared
//             for (Loopable<Point3d> loopable : ptLoop.loopableIterator())
//             {
//                 SharedEdge e = createEdge( loopable.get(), loopable.getNext().get() );
//                     
//                 e.setLeft (loopable.get(), loop.append( e ), this );
//             }
//         }
//     }
// }


import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.vecmath.Point3d;
import javax.vecmath.Tuple3d;
import javax.vecmath.Vector3d;
import org.twak.camp.Output.Face;
import org.twak.utils.Cache;
import org.twak.utils.IdentityLookup;
import org.twak.utils.Triple;
import org.twak.utils.collections.ConsecutiveTriples;
import org.twak.utils.collections.Loop;
import org.twak.utils.collections.LoopL;
import org.twak.utils.collections.Loopable;
import org.twak.utils.geom.AngleAccumulator;
import org.twak.utils.geom.GraphMap;
package org.twak.camp;




/**
 * @author twak
 */
public class Output
{
    // marker for horizontal input edges (other edges can also be horizontal...)
    public static Tag isCreatedHorizontal = new Tag ("horizontal");

// Path: src/org/twak/camp/Output.java
// public class Face
// {
//     // first is outside, others are holes
//     public LoopL<Point3d> points = null;
// 
//     public Set<Tag> plan = new HashSet<>(), profile = new HashSet<>();
// 
//     // bottom edges
//     public Set<SharedEdge> definingSE = new LinkedHashSet<>();
//     // defining edges of child (top) edges
//     public Set<SharedEdge> topSE = new LinkedHashSet<>();
// 
//     // face below us in the skeleton - can be traced back to an originator
//     public Face parent;
//         
//     public GraphMap<Point3d> results = new GraphMap<>();
// 
//     // a typical edge that defines the plane normal
//     public Edge edge;
// 
//     // subset of results who are horizontal edges and whose nextL are edge, or similar.
//     public Set<Corner> definingCorners = new LinkedHashSet<>();
// 
//     public LoopL<SharedEdge> edges = new LoopL<>();
// 
//     public LoopL<Point3d> getLoopL()
//     {
//         return points;
//     }
// 
//     public int pointCount()
//     {
//         return points.count();
//     }
//     // is a defining edges of the above (child) edges
//     public boolean isTop (SharedEdge edge)
//     {
//         return topSE.contains( edge );
//     }
//     // is a defining edge
//     public boolean isBottom(SharedEdge edge)
//     {
//         return definingSE.contains(  edge );
//     }
//     // isn't a top or bottom edges
//     public boolean isSide (SharedEdge edge)
//     {
//         return !( isTop( edge ) || isBottom( edge ) );
//     }
// 
//     /**
//      * When caculating an offset, we can assume that all edges add a face at every interval
//      * this returns the number of faces below this face.
//      * @return
//      */
//     public int getParentCount()
//     {
//         int count = -1;
//         Face f = this;
//         while (f != null)
//         {
//             count++;
//             f = f.parent;
//         }
//         return count;
//     }
// 
//     private void findSharedEdges()
//     {
//         edges = new LoopL<>();
//         for (Loop <Point3d> ptLoop : points)
//         {
//             Loop<SharedEdge> loop = new Loop<>();
//             edges.add (loop);
//             // start and end points of SharedEdges **aren't** shared
//             for (Loopable<Point3d> loopable : ptLoop.loopableIterator())
//             {
//                 SharedEdge e = createEdge( loopable.get(), loopable.getNext().get() );
//                     
//                 e.setLeft (loopable.get(), loop.append( e ), this );
//             }
//         }
//     }
// }


// Path: src/org/twak/camp/Output.java
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.vecmath.Point3d;
import javax.vecmath.Tuple3d;
import javax.vecmath.Vector3d;
import org.twak.camp.Output.Face;
import org.twak.utils.Cache;
import org.twak.utils.IdentityLookup;
import org.twak.utils.Triple;
import org.twak.utils.collections.ConsecutiveTriples;
import org.twak.utils.collections.Loop;
import org.twak.utils.collections.LoopL;
import org.twak.utils.collections.Loopable;
import org.twak.utils.geom.AngleAccumulator;
import org.twak.utils.geom.GraphMap;

package org.twak.camp;




/**
 * @author twak
 */
public class Output
{
    // marker for horizontal input edges (other edges can also be horizontal...)
    public static Tag isCreatedHorizontal = new Tag ("horizontal");

    public Map<Corner, Face> faces = new LinkedHashMap<>(); // the faces represented by each edge