public void FillInsideWithFootprints() { ClearUnmodifiedFootprints(false); //List<Footprint> instantiatedFootprints = new List<Footprint>(); Vector3 bPos; Quaternion bRot; Vector3 closestPoint; //GameObject footprintObj; Footprint footprint; Primitive primitive = graph.mainPrimitives[0]; List <Node> nodes = primitive.nodes; List <Edge> edges = primitive.edges; int failedPosCount = 0; int failedPosMax = 1000; int safeCount = 0; Vector3 point; Vector3 pointWorld; while (failedPosCount < failedPosMax && safeCount < 1000) { safeCount++; //Get random point inside the boundaries float randX = UnityEngine.Random.Range(primitive.minX, primitive.maxX); float randZ = UnityEngine.Random.Range(primitive.minZ, primitive.maxZ); point = new Vector3(randX, 0f, randZ); //If point is inside the polygon, proceed if (EdgeGraphUtility.PointIsInside(point, nodes, edges)) { pointWorld = transform.TransformPoint(point); int footprintIdx = GetRandomInsideFootPrintIdx(); GetFootprintPosAndRotAtTarget(pointWorld, out bPos, out bRot, out closestPoint, footprintIdx, false); footprint = UtilityTools.Helper.GetComponentInPrefabChildren <Footprint>(footprintPrefabsOnEdge[footprintIdx]); Matrix4x4 footprintTRSMatrix = Matrix4x4.TRS(bPos, bRot, Vector3.one); if (!FootprintOverlapsOthers(footprint, footprintTRSMatrix) && FootprintIsInsideGraph(footprint, footprintTRSMatrix)) { PlaceFootprint(bPos, bRot, footprintIdx, false); } else { failedPosCount++; } } if (failedPosCount >= failedPosMax || safeCount >= 1000) { break; } } }
bool FootprintIsInsideGraph(Footprint footprint, Matrix4x4 footprintTRSMatrix) { for (int i = 0; i < footprint.edges.Count; i++) { Vector3 n1PosWorld = footprintTRSMatrix.MultiplyPoint3x4(EdgeGraphUtility.GetNode(footprint.edges[i].Node1, ref footprint.nodes).Position); Vector3 n2PosWorld = footprintTRSMatrix.MultiplyPoint3x4(EdgeGraphUtility.GetNode(footprint.edges[i].Node2, ref footprint.nodes).Position); Vector3 n1PosGraph = graph.transform.InverseTransformPoint(n1PosWorld); Vector3 n2PosGraph = graph.transform.InverseTransformPoint(n2PosWorld); if (!EdgeGraphUtility.PointIsInside(n1PosGraph, graph.mainPrimitives[0].nodes, graph.mainPrimitives[0].edges) || !EdgeGraphUtility.PointIsInside(n2PosGraph, graph.mainPrimitives[0].nodes, graph.mainPrimitives[0].edges)) { return(false); } } return(true); }
void OnSceneGUI() { if (placer.handPlacementEnabled && placer.footprintPrefabsOnEdge.Count > 0) { controls.Update(); Vector3 newFootprintPos = Vector3.zero; Quaternion newFootprintRot = Quaternion.identity; bool placeInside = EdgeGraphUtility.PointIsInside(controls.cursorLocalPosition, placer.graph.mainPrimitives[0].nodes, placer.graph.mainPrimitives[0].edges); if (controls.controlIsPressed) { if (placer.handPlacementOnEdge) { if (handPlacedIndex >= placer.footprintPrefabsOnEdge.Count) { handPlacedIndex = placer.footprintPrefabsOnEdge.Count - 1; } } else { if (handPlacedIndex >= placer.footprintPrefabsInside.Count) { handPlacedIndex = placer.footprintPrefabsInside.Count - 1; } } if (Event.current.isKey && Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.W) { if (placer.handPlacementOnEdge) { handPlacedIndex = UtilityTools.Helper.GetNextIndex <GameObject>(placer.footprintPrefabsOnEdge, handPlacedIndex); } else { handPlacedIndex = UtilityTools.Helper.GetNextIndex <GameObject>(placer.footprintPrefabsInside, handPlacedIndex); } } else if (Event.current.isKey && Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Q) { if (placer.handPlacementOnEdge) { handPlacedIndex = UtilityTools.Helper.GetPrevIndex <GameObject>(placer.footprintPrefabsOnEdge, handPlacedIndex); } else { handPlacedIndex = UtilityTools.Helper.GetPrevIndex <GameObject>(placer.footprintPrefabsInside, handPlacedIndex); } } else if (Event.current.isKey && Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.E) { placer.handPlacementOnEdge = !placer.handPlacementOnEdge; } Quaternion rot; Vector3 closestPoint; placer.GetFootprintPosAndRotAtTarget(controls.cursorWorldPosition, out newFootprintPos, out rot, out closestPoint, handPlacedIndex, placer.handPlacementOnEdge, placeInside); if (placer.handPlacementOnEdge) { newFootprintRot = rot; } Footprint fp; if (placer.handPlacementOnEdge) { fp = UtilityTools.Helper.GetComponentInPrefabChildren <Footprint>(placer.footprintPrefabsOnEdge[handPlacedIndex]); } else { fp = UtilityTools.Helper.GetComponentInPrefabChildren <Footprint>(placer.footprintPrefabsInside[handPlacedIndex]); } if (fp != null) { Handles.color = Color.yellow; Matrix4x4 newPosMatrix = Matrix4x4.TRS(newFootprintPos, newFootprintRot, Vector3.one); for (int i = 0; i < fp.nodes.Count; i++) { Node cur = fp.nodes[i]; Node next; if (i == fp.nodes.Count - 1) { next = fp.nodes[0]; } else { next = fp.nodes[i + 1]; } Handles.DrawLine(newPosMatrix.MultiplyPoint3x4(cur.Position), newPosMatrix.MultiplyPoint3x4(next.Position)); Handles.CubeCap(0, newPosMatrix.MultiplyPoint3x4(cur.Position), Quaternion.LookRotation(newPosMatrix.GetColumn(2), newPosMatrix.GetColumn(1)), .2f); if (placer.handPlacementOnEdge) { Handles.Label(controls.cursorWorldPosition, placer.footprintPrefabsOnEdge[handPlacedIndex].name, "box"); } else { Handles.Label(controls.cursorWorldPosition, placer.footprintPrefabsInside[handPlacedIndex].name, "box"); } Handles.SphereCap(0, newFootprintPos, Quaternion.identity, .2f); Handles.SphereCap(0, closestPoint, Quaternion.identity, .2f); } } } if (controls.MouseClickedDown()) { if (controls.controlIsPressed) { placer.PlaceFootprint(newFootprintPos, newFootprintRot, handPlacedIndex, placer.handPlacementOnEdge, true); if (!placer.handPlacementOnEdge) { newFootprintRot = Quaternion.AngleAxis(UnityEngine.Random.Range(0f, 360f), Vector3.up); } } } } Handles.BeginGUI(); GUILayout.Window(1, new Rect(16f, 232f, 150f, 50f), DrawSceneWindow, "Placement by hand"); Handles.EndGUI(); }
bool FootprintOverlapsOthers(Footprint footprint, Matrix4x4 footprintTRSMatrix) { // Check if any footprint edges cross each other for (int i = 0; i < footprint.edges.Count; i++) { Vector3 n1Pos = footprintTRSMatrix.MultiplyPoint3x4(EdgeGraphUtility.GetNode(footprint.edges[i].Node1, ref footprint.nodes).Position); Vector3 n2Pos = footprintTRSMatrix.MultiplyPoint3x4(EdgeGraphUtility.GetNode(footprint.edges[i].Node2, ref footprint.nodes).Position); for (int j = 0; j < instantiatedFootprints.Count; j++) { List <Node> placedFootprintWorldNodes = new List <Node>(); instantiatedFootprints[j].nodes.ForEach((node) => { Node newNode = new Node(node); newNode.Position = instantiatedFootprints[j].transform.TransformPoint(node.Position); placedFootprintWorldNodes.Add(newNode); }); for (int k = 0; k < instantiatedFootprints[j].edges.Count; k++) { Vector3 n3Pos = instantiatedFootprints[j].transform.TransformPoint(EdgeGraphUtility.GetNode(instantiatedFootprints[j].edges[k].Node1, ref instantiatedFootprints[j].nodes).Position); Vector3 n4Pos = instantiatedFootprints[j].transform.TransformPoint(EdgeGraphUtility.GetNode(instantiatedFootprints[j].edges[k].Node2, ref instantiatedFootprints[j].nodes).Position); Vector3 intersect; if (UtilityTools.MathHelper.AreIntersecting(out intersect, n1Pos, n2Pos, n3Pos, n4Pos) == 1) { return(true); } } } } // Check if footprint is inside placed footprint Vector3 nodePosWorld; for (int i = 0; i < footprint.nodes.Count; i++) { nodePosWorld = footprintTRSMatrix.MultiplyPoint3x4(footprint.nodes[i].Position); for (int j = 0; j < instantiatedFootprints.Count; j++) { List <Node> placedFootprintWorldNodes = new List <Node>(); instantiatedFootprints[j].nodes.ForEach((node) => { Node newNode = new Node(node); newNode.Position = instantiatedFootprints[j].transform.TransformPoint(node.Position); placedFootprintWorldNodes.Add(newNode); }); if (EdgeGraphUtility.PointIsInside(nodePosWorld, placedFootprintWorldNodes, instantiatedFootprints[j].edges)) { return(true); } } } // Check if any placed footprint is inside the footprint List <Node> footprintWorldNodes = new List <Node>(); footprint.nodes.ForEach((node) => { Node newNode = new Node(node); newNode.Position = footprintTRSMatrix.MultiplyPoint3x4(node.Position); footprintWorldNodes.Add(newNode); }); for (int i = 0; i < instantiatedFootprints.Count; i++) { List <Node> placedFootprintWorldNodes = new List <Node>(); instantiatedFootprints[i].nodes.ForEach((node) => { Node newNode = new Node(node); newNode.Position = instantiatedFootprints[i].transform.TransformPoint(node.Position); placedFootprintWorldNodes.Add(newNode); }); for (int j = 0; j < placedFootprintWorldNodes.Count; j++) { if (EdgeGraphUtility.PointIsInside(placedFootprintWorldNodes[j].Position, footprintWorldNodes, footprint.edges)) { return(true); } } } return(false); }