public Primitive(Primitive _p) { id = Guid.NewGuid().ToString(); type = _p.type; edges = _p.edges; nodes = _p.nodes; CopyNodesAndEdges(); }
// Algorithms from http://www.geometrictools.com/Documentation/MinimalCycleBasis.pdf // The Minimal Cycle Basis for a Planar Graph by David Eberly /// <summary> /// Attempts to find minimal cycles /// </summary> public static void ExtractPrimitive(Node _n0, ref List<Node> _nodes, ref List<Edge> _edges, ref List<Primitive> _primitives) { List<Node> visited = new List<Node>(); List<Node> sequence = new List<Node>(); EdgeGraphUtility.CheckAdjacentNodes(ref _nodes, ref _edges); if (_n0.adjacents.Count == 0) { EdgeGraphUtility.RemoveNodeAndCleanAdjacents(_n0, ref _nodes, ref _edges); return; } sequence.Add(_n0); Node _n1 = GetClockwiseMostAdjacent(null, _n0, ref _nodes); Node prev = _n0; Node curr = _n1; while (curr != null && curr != _n0 && !visited.Contains(curr)) { sequence.Add(curr); visited.Add(curr); Node next = GetCounterClockwiseMostAdjacent(prev, curr, ref _nodes); prev = curr; curr = next; } if (curr == null) { // Filament found, not necessarily rooted at prev ExtractFilament(prev, EdgeGraphUtility.GetNode(prev.adjacents[0], ref _nodes), ref _nodes, ref _edges, ref _primitives); } else if (curr == _n0) { // Minimal cycle found Primitive primitive = new Primitive(Primitive.PrimitiveType.MinimalCycle); primitive.nodes.AddRange(sequence); for (int i = 0; i < sequence.Count; i++) { Node n1; Node n2; if (i == sequence.Count - 1) { n1 = sequence[i]; n2 = sequence[0]; } else { n1 = sequence[i]; n2 = sequence[i + 1]; } Edge e = EdgeGraphUtility.FindEdgeByNodes(n1, n2, _edges); if (e != null) { primitive.edges.Add(e); e.isPartOfCycle = true; } } EdgeGraphUtility.RemoveEdgeAndCleanAdjacents(_n0, _n1, ref _nodes, ref _edges); if (_n0.adjacents.Count == 1) { // Remove the filament rooted at v0 ExtractFilament(_n0, EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes), ref _nodes, ref _edges, ref _primitives); } if (_n1.adjacents.Count == 1) { // Remove the filament rooted at v1 ExtractFilament(_n1, EdgeGraphUtility.GetNode(_n1.adjacents[0], ref _nodes), ref _nodes, ref _edges, ref _primitives); } _primitives.Add(primitive); } else // curr was visited earlier { // A cycle has been found, but is not guaranteed to be a minimal cycle. // This implies v0 is part of a filament // Locate the starting point for the filament by traversing from v0 away from the initial v1 while (_n0.adjacents.Count == 2) { if (_n0.adjacents[0] != _n1.ID) { _n1 = _n0; _n0 = EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes); } else { _n1 = _n0; _n0 = EdgeGraphUtility.GetNode(_n0.adjacents[1], ref _nodes); } } ExtractFilament(_n0, _n1, ref _nodes, ref _edges, ref _primitives); } }
/// <summary> /// Extracts filament consisting of nodes and edges /// </summary> public static void ExtractFilament(Node _n0, Node _n1, ref List<Node> _nodes, ref List<Edge> _edges, ref List<Primitive> _primitives) { Edge e = EdgeGraphUtility.FindEdgeByNodes(_n0, _n1, _edges); if (e != null && e.isPartOfCycle) { if (_n0.adjacents.Count >= 3) { EdgeGraphUtility.RemoveEdgeAndCleanAdjacents(_n0, _n1, ref _nodes, ref _edges); _n0 = _n1; if (_n0.adjacents.Count == 1) _n1 = EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes); } while (_n0.adjacents.Count == 1) { _n1 = EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes); Edge ee = EdgeGraphUtility.FindEdgeByNodes(_n0, _n1, _edges); if (ee != null && e.isPartOfCycle) { EdgeGraphUtility.RemoveNodeAndCleanAdjacents(_n0, ref _nodes, ref _edges); EdgeGraphUtility.RemoveEdgeAndCleanAdjacents(_n0, _n1, ref _nodes, ref _edges); } else break; } if (_n0.adjacents.Count == 0) { EdgeGraphUtility.RemoveNodeAndCleanAdjacents(_n0, ref _nodes, ref _edges); } } else { Primitive primitive = new Primitive(Primitive.PrimitiveType.Filament); if (_n0.adjacents.Count >= 3) { primitive.nodes.Add(_n0); primitive.edges.Add(e); EdgeGraphUtility.RemoveEdgeAndCleanAdjacents(_n0, _n1, ref _nodes, ref _edges); _n0 = _n1; if (_n0.adjacents.Count == 1) _n1 = EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes); } while (_n0.adjacents.Count == 1) { primitive.nodes.Add(_n0); _n1 = EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes); EdgeGraphUtility.RemoveNodeAndCleanAdjacents(_n0, ref _nodes, ref _edges); Edge _e = EdgeGraphUtility.RemoveEdgeAndCleanAdjacents(_n0, _n1, ref _nodes, ref _edges); if (_e != null) primitive.edges.Add(_e); _n0 = _n1; } primitive.nodes.Add(_n0); if (_n0.adjacents.Count == 0) { EdgeGraphUtility.RemoveNodeAndCleanAdjacents(_n0, ref _nodes, ref _edges); } _primitives.Add(primitive); } }
void ProcessSubPrimitives(Primitive p) { if (p.subEdges == null || p.subEdges.Count <= 0) return; // Copy local lists from primitive's sub nodes and edges List<Node> _nodes = new List<Node>(); List<Edge> _edges = new List<Edge>(); EdgeGraphUtility.CopyNodesAndEdges(p.subNodes, p.subEdges, out _nodes, out _edges); EdgeGraphUtility.CheckAdjacentNodes(ref _nodes, ref _edges); //subPrimitives = new List<Primitive>(); List<Primitive> _subPrimitives = new List<Primitive>(); // Extract primitives inside main primitives try { MinimalCycle.Extract(ref _nodes, ref _edges, ref _subPrimitives); } catch (Exception e) { Debug.LogWarning("Graph::GeneratePrimitiveSubPrimitives() - Error while extracting primitives: " + e.Message); return; } _subPrimitives.ForEach((sp) => { sp.Process(); }); for (int i = _subPrimitives.Count - 1; i >= 0; i--) { if (!_subPrimitives[i].EvaluationResult) _subPrimitives.RemoveAt(i); } _subPrimitives.ForEach((sp) => { sp.parent = p.ID; GameObject subGraphObj = new GameObject("SubGraph"); subGraphObj.transform.SetParent(transform); subGraphObj.transform.localPosition = Vector3.zero; subGraphObj.transform.localScale = Vector3.one; Graph subGraph = subGraphObj.AddComponent<Graph>(); subGraph.GraphID = Guid.NewGuid().GetHashCode(); subGraphObj.name += subGraph.GraphID; subGraph.nodes = new List<Node>(); foreach (var node in sp.nodes) { subGraph.nodes.Add(node); } subGraph.edges = new List<Edge>(); foreach (var edge in sp.edges) { edge.Width = 0f; subGraph.edges.Add(edge); } subGraph.ProcessMinimalCycles(); subGraph.mainPrimitives[0].parent = p.ID; subGraphs.Add(subGraph); //subPrimitives.Add(subGraph.mainPrimitives[0]); FacadeBuilder builder = GetComponent<FacadeBuilder>(); if (builder != null) { FacadeBuilder subBuilder = subGraph.gameObject.AddComponent<FacadeBuilder>(); subBuilder.inSet = builder.inSet; subBuilder.facadeStretchPrefab = builder.facadeStretchPrefab; subBuilder.facadePrefabs = builder.facadePrefabs; subBuilder.roofMiddleMaterial = builder.roofMiddleMaterial; subBuilder.roofSideMaterial = builder.roofSideMaterial; subBuilder.roofHeight = builder.roofHeight; subBuilder.roofMiddleAddHeight = builder.roofMiddleAddHeight; subBuilder.roofAccentWidth = builder.roofAccentWidth; } FootprintPlacer placer = GetComponent<FootprintPlacer>(); if (placer != null) { FootprintPlacer _placer = subGraph.gameObject.AddComponent<FootprintPlacer>(); _placer.footprintPrefabsOnEdge = placer.footprintPrefabsOnEdge; _placer.footprintPrefabsInside = placer.footprintPrefabsInside; _placer.UpdateData(); } }); }
void GenerateSubEdges(int seed, Primitive p) { p.Generate(seed); }
void ClearSubPrimitives(Primitive p) { //for (int i = 0; i < subPrimitives.Count; i++) //{ // if (subPrimitives[i].parent == p.ID) // { // subPrimitives[i].subNodes = new List<Node>(); // subPrimitives[i].subEdges = new List<Edge>(); // subPrimitives.RemoveAt(i); // i--; // } //} for (int i = 0; i < subGraphs.Count; i++) { if (subGraphs[i] == null) { subGraphs.RemoveAt(i); i--; continue; } if (subGraphs[i].mainPrimitives[0].parent == p.ID) { DestroyImmediate(subGraphs[i].gameObject); subGraphs.RemoveAt(i); i--; } } }
// Algorithms from http://www.geometrictools.com/Documentation/MinimalCycleBasis.pdf // The Minimal Cycle Basis for a Planar Graph by David Eberly /// <summary> /// Attempts to find minimal cycles /// </summary> public static void ExtractPrimitive(Node _n0, ref List <Node> _nodes, ref List <Edge> _edges, ref List <Primitive> _primitives) { List <Node> visited = new List <Node>(); List <Node> sequence = new List <Node>(); EdgeGraphUtility.CheckAdjacentNodes(ref _nodes, ref _edges); if (_n0.adjacents.Count == 0) { EdgeGraphUtility.RemoveNodeAndCleanAdjacents(_n0, ref _nodes, ref _edges); return; } sequence.Add(_n0); Node _n1 = GetClockwiseMostAdjacent(null, _n0, ref _nodes); Node prev = _n0; Node curr = _n1; while (curr != null && curr != _n0 && !visited.Contains(curr)) { sequence.Add(curr); visited.Add(curr); Node next = GetCounterClockwiseMostAdjacent(prev, curr, ref _nodes); prev = curr; curr = next; } if (curr == null) { // Filament found, not necessarily rooted at prev ExtractFilament(prev, EdgeGraphUtility.GetNode(prev.adjacents[0], ref _nodes), ref _nodes, ref _edges, ref _primitives); } else if (curr == _n0) { // Minimal cycle found Primitive primitive = new Primitive(Primitive.PrimitiveType.MinimalCycle); primitive.nodes.AddRange(sequence); for (int i = 0; i < sequence.Count; i++) { Node n1; Node n2; if (i == sequence.Count - 1) { n1 = sequence[i]; n2 = sequence[0]; } else { n1 = sequence[i]; n2 = sequence[i + 1]; } Edge e = EdgeGraphUtility.FindEdgeByNodes(n1, n2, _edges); if (e != null) { primitive.edges.Add(e); e.isPartOfCycle = true; } } EdgeGraphUtility.RemoveEdgeAndCleanAdjacents(_n0, _n1, ref _nodes, ref _edges); if (_n0.adjacents.Count == 1) { // Remove the filament rooted at v0 ExtractFilament(_n0, EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes), ref _nodes, ref _edges, ref _primitives); } if (_n1.adjacents.Count == 1) { // Remove the filament rooted at v1 ExtractFilament(_n1, EdgeGraphUtility.GetNode(_n1.adjacents[0], ref _nodes), ref _nodes, ref _edges, ref _primitives); } _primitives.Add(primitive); } else // curr was visited earlier { // A cycle has been found, but is not guaranteed to be a minimal cycle. // This implies v0 is part of a filament // Locate the starting point for the filament by traversing from v0 away from the initial v1 while (_n0.adjacents.Count == 2) { if (_n0.adjacents[0] != _n1.ID) { _n1 = _n0; _n0 = EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes); } else { _n1 = _n0; _n0 = EdgeGraphUtility.GetNode(_n0.adjacents[1], ref _nodes); } } ExtractFilament(_n0, _n1, ref _nodes, ref _edges, ref _primitives); } }
/// <summary> /// Extracts filament consisting of nodes and edges /// </summary> public static void ExtractFilament(Node _n0, Node _n1, ref List <Node> _nodes, ref List <Edge> _edges, ref List <Primitive> _primitives) { Edge e = EdgeGraphUtility.FindEdgeByNodes(_n0, _n1, _edges); if (e != null && e.isPartOfCycle) { if (_n0.adjacents.Count >= 3) { EdgeGraphUtility.RemoveEdgeAndCleanAdjacents(_n0, _n1, ref _nodes, ref _edges); _n0 = _n1; if (_n0.adjacents.Count == 1) { _n1 = EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes); } } while (_n0.adjacents.Count == 1) { _n1 = EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes); Edge ee = EdgeGraphUtility.FindEdgeByNodes(_n0, _n1, _edges); if (ee != null && e.isPartOfCycle) { EdgeGraphUtility.RemoveNodeAndCleanAdjacents(_n0, ref _nodes, ref _edges); EdgeGraphUtility.RemoveEdgeAndCleanAdjacents(_n0, _n1, ref _nodes, ref _edges); } else { break; } } if (_n0.adjacents.Count == 0) { EdgeGraphUtility.RemoveNodeAndCleanAdjacents(_n0, ref _nodes, ref _edges); } } else { Primitive primitive = new Primitive(Primitive.PrimitiveType.Filament); if (_n0.adjacents.Count >= 3) { primitive.nodes.Add(_n0); primitive.edges.Add(e); EdgeGraphUtility.RemoveEdgeAndCleanAdjacents(_n0, _n1, ref _nodes, ref _edges); _n0 = _n1; if (_n0.adjacents.Count == 1) { _n1 = EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes); } } while (_n0.adjacents.Count == 1) { primitive.nodes.Add(_n0); _n1 = EdgeGraphUtility.GetNode(_n0.adjacents[0], ref _nodes); EdgeGraphUtility.RemoveNodeAndCleanAdjacents(_n0, ref _nodes, ref _edges); Edge _e = EdgeGraphUtility.RemoveEdgeAndCleanAdjacents(_n0, _n1, ref _nodes, ref _edges); if (_e != null) { primitive.edges.Add(_e); } _n0 = _n1; } primitive.nodes.Add(_n0); if (_n0.adjacents.Count == 0) { EdgeGraphUtility.RemoveNodeAndCleanAdjacents(_n0, ref _nodes, ref _edges); } _primitives.Add(primitive); } }