public override List<MeshFilter> apply (HighLevelEdge edge)
		{
			List<MeshFilter> meshes = new List<MeshFilter> ();
			Vector3 cornerDimensions = new Vector3 (1.0f, 1.0f, 1.0f);

			// Get from and translate to world space
			Vector3 from = edge.getFrom ().getVertex().getPoint();
			Vector3 to = edge.getTo ().getVertex().getPoint();
			from = parent.TransformPoint (from);
			to = parent.TransformPoint (to);

			// Get direction and translate to world space
			Vector3 direction = edge.getDirection ();
			direction = parent.TransformDirection (direction);
			direction.Normalize ();

			// Set from and to actual center points of the corner
			from = from + Vector3.Scale (edge.getFrom ().getTranslateVector (), cornerDimensions / 2) + Vector3.Scale(direction, cornerDimensions /2);
			to = to + Vector3.Scale (edge.getTo ().getTranslateVector (), cornerDimensions / 2) - Vector3.Scale(direction, cornerDimensions / 2);

			float edgeMagnitude = (to-from).magnitude;

			// These are all world space
			Vector3 dimensions = this.getCellDimensions ();
			Vector3 scale = this.getCellSize();

			Vector3 normal = edge.getNormal ();

			meshes.AddRange(FillCellModule.fillCell (from, to, scale, dimensions, parent, color, normal));

			return meshes;
		}
		public void createRegionsForEdge(HighLevelEdge hle) {
			Region r1 = new Region ();
			Region r2 = new Region ();
			foreach (Edge e in hle.getEdges()) {
				foreach (Face f in e.getFaces()) {
					// Attempt to add to both regions
					if (r1.addFace (f)) {
						f.setParent (r1);
						r1.addEdge (hle);
						hle.addRegion (r1);
					} else if (r2.addFace (f)) {
						f.setParent (r2);
						r2.addEdge (hle);
						hle.addRegion (r2);
					}
				}
			}
			regions.Add (r1);
			regions.Add (r2);
		}
		public void setParent(HighLevelEdge e) {
			this.parent = e;
		}
		public Edge (Vertex v1, Vertex v2) {
			this.v1 = v1;
			this.v2 = v2;
			this.faces = new List<Face> ();
			this.parent = null;
		}
		public void addEdge(HighLevelEdge e) {
			if (edges.Contains (e))
				return;
			this.edges.Add (e);
		}
		abstract public List<MeshFilter> apply(HighLevelEdge e);
		public override List<MeshFilter> apply (HighLevelEdge edge)
		{
			List<MeshFilter> meshes = new List<MeshFilter> ();
			Vector3 cornerDimensions = new Vector3 (1.0f, 1.0f, 1.0f);

			// Get points of edge and translate to world space
			Corner cFrom = edge.getFrom();
			Vector3 from = edge.getFrom ().getVertex().getPoint();
			Vector3 to = edge.getTo ().getVertex().getPoint();
			from = parent.TransformPoint (from);
			to = parent.TransformPoint (to);

			// Get other two edges for brick direction
			HighLevelEdge e1 = null, e2 = null;
			foreach (HighLevelEdge e in edge.getFrom().getEdges()) {
				if (e.Equals (edge))
					continue;
				else if (e1 == null) {
					e1 = e;
				} else if (e2 == null) {
					e2 = e;
				} else {
					Debug.Log ("Warning more then 3 edges, likely invalid render");
				}
			}

			if (e2 == null) {
				Debug.Log ("Warning, corner with only one edge found, something went wrong!");
				return meshes;
			}

			// Calculate rotation for the two directions
			Vector3 e1Dir = e1.getDirection(cFrom).normalized;
			Vector3 e2Dir = e2.getDirection(cFrom).normalized;

			Quaternion rotationE1 = Quaternion.FromToRotation(Vector3.forward, e1Dir);
			Quaternion rotationE2 = Quaternion.FromToRotation (Vector3.forward, e2Dir);

			// Get direction and translate to world space
			Vector3 direction = edge.getDirection ();
			direction = parent.TransformDirection (direction);
			float edgeMagnitude = parent.TransformVector (direction).magnitude - cornerDimensions.y * 2;

			direction.Normalize ();

			// Set from and to actual center points of the corner
			from = from + Vector3.Scale (edge.getFrom ().getTranslateVector (), cornerDimensions/2) + Vector3.Scale(direction, cornerDimensions/2);
			to = to + Vector3.Scale (edge.getTo ().getTranslateVector (), cornerDimensions/2) - Vector3.Scale(direction, cornerDimensions/2);

			edgeMagnitude = (to-from).magnitude;

			// These are all world space
			Vector3 dimensions = this.getCellDimensions ();
			Vector3 scale = this.getCellSize();

			// Calculate start position
			Vector3 start = from + direction * dimensions.y / 2;

			// Create each cell
			int maxCount = (int) Mathf.Floor(edgeMagnitude / scale.y) - 1;
			int i = 0;
			bool takeDir1 = direction.y >= 0;

			float stepSize = dimensions.y;

			for (Vector3 p = start; i < maxCount; p += direction * stepSize) {
				Cell c;
				Color finalColor = Color.Lerp (color, Color.black, UnityEngine.Random.value * 0.3f);
				if (takeDir1) {
					c = new Cell (parent, p + (dimensions.z / 2 - cornerDimensions.z / 2) * e1Dir, scale, rotationE1, "CornerEdgeBrick");
				} else {
					c = new Cell (parent, p + (dimensions.z / 2 - cornerDimensions.z / 2) * e2Dir, scale, rotationE2, "CornerEdgeBrick");
				}
				takeDir1 = !takeDir1;
				c.setColor (finalColor);
				i++;
				meshes.Add(c.getCell().GetComponent<MeshFilter>());
			}

			return meshes;
		}
		public HighLevelEdge processSingleDirectionEdge(Edge.EdgeLabel eLabel, Vector3 direction, Corner source) {
			bool changed = true;
			Vertex sourceVertex = source.getVertex ();
			Vertex current = sourceVertex;
			List<Edge> usedEdges = new List<Edge> ();
			while (changed) {
				changed = false;
				foreach (Edge e in current.getEdges()) {
					if (e.hasParent()) {
						continue;
					}
					if (e.getLabel() != eLabel) {
						// If this isn't a correct type of edge, go to the next
						continue;
					}
					// Get our target
					Vertex target = e.getTo () == sourceVertex ? e.getFrom () : e.getTo ();
					// Calculate direction
					Vector3 newDirection = (target.getPoint () - current.getPoint ()).normalized;

					// If the direction isn't the same, we're done
					if (direction != newDirection) {
						continue;
					}

					usedEdges.Add (e);
					// Get the target label
					Vertex.VertexLabel targetLabel = target.getLabel ();
					if (targetLabel == Vertex.VertexLabel.cornerConcave ||
						targetLabel == Vertex.VertexLabel.cornerConvex ||
						targetLabel == Vertex.VertexLabel.cornerSaddle) {
						// Create HLE, this is the end of our HLE
						HighLevelEdge hle = new HighLevelEdge();
						hle.addEdgeRange (usedEdges);
						// Get target corner
						Corner c = target.getParent();
						// Set from and to of hle
						hle.setFrom (source);
						hle.setTo (c);

						// Add edges to the corners
						c.addEdge (hle);
						source.addEdge (hle);

						// Set all edges to processed
						foreach (Edge en in usedEdges) {
							en.setParent (hle);
						}
						return hle;
					} else {
						Debug.Log ("next edge in sequence!");
						current = target;
						changed = true;
					}
				}
			}
			// No valid HLE :(
			return null;
		}
		public void addEdge(HighLevelEdge e) {
			this.edges.Add (e);
		}