Esempio n. 1
0
        /// <summary>
        /// Wrap input geometry into module cages.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from
        ///     input parameters and to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            var geometryRaw = new List <IGH_GeometricGoo>();
            var module      = new Module();
            var basePlane   = new Plane();

            if (!DA.GetDataList(0, geometryRaw))
            {
                return;
            }

            if (!DA.GetData(1, ref module))
            {
                return;
            }

            if (!DA.GetData(2, ref basePlane))
            {
                return;
            }

            if (module == null || !module.IsValid)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Module is null or invalid.");
                return;
            }

            // Transform the geometry to be oriented to world XYZ fore easier scanning
            var geometryTransform = Transform.PlaneToPlane(basePlane, Plane.WorldXY);
            var geometryClean     = geometryRaw
                                    .Select(goo => GH_Convert.ToGeometryBase(goo))
                                    .Where(geo => geo != null)
                                    .Select(geo => {
                var transformedGeometry = geo.Duplicate();
                transformedGeometry.Transform(geometryTransform);
                return(transformedGeometry);
            }).ToList();

            if (!geometryClean.Any())
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Warning,
                                  "Failed to collect any valid geometry to scan.");
                return;
            }

            var moduleGeometry = module.Geometry
                                 .Concat(module.ReferencedGeometry);

            if (!moduleGeometry.Any())
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Warning,
                                  "Module \"" + module.Name + "\" contains " +
                                  "no geometry and therefore will be skipped.");
                return;
            }

            var moduleGeometryBBoxes = moduleGeometry.Select(geo => geo.GetBoundingBox(true));

            var bBoxUnionModule = BoundingBox.Empty;

            bBoxUnionModule.Union(module.Pivot.Origin);
            foreach (var moduleBBox in moduleGeometryBBoxes)
            {
                bBoxUnionModule.Union(moduleBBox);
            }
            var moduleDimensionSafetyBuffer = new Point3i(
                (int)Math.Ceiling(bBoxUnionModule.Diagonal.X / module.PartDiagonal.X) + 1,
                (int)Math.Ceiling(bBoxUnionModule.Diagonal.Y / module.PartDiagonal.Y) + 1,
                (int)Math.Ceiling(bBoxUnionModule.Diagonal.Z / module.PartDiagonal.Z) + 1);

            var geometryBBoxes    = geometryClean.Select(geo => geo.GetBoundingBox(true)).ToList();
            var bBoxUnionGeometry = BoundingBox.Empty;

            foreach (var bBox in geometryBBoxes)
            {
                bBoxUnionGeometry.Union(bBox);
            }

            var slots = new List <Slot>();

            for (int z = (int)Math.Floor(bBoxUnionGeometry.Min.Z / module.PartDiagonal.Z) - moduleDimensionSafetyBuffer.Z;
                 z < Math.Ceiling(bBoxUnionGeometry.Max.Z / module.PartDiagonal.Z) + moduleDimensionSafetyBuffer.Z;
                 z++)
            {
                for (int y = (int)Math.Floor(bBoxUnionGeometry.Min.Y / module.PartDiagonal.Y) - moduleDimensionSafetyBuffer.Y;
                     y < Math.Ceiling(bBoxUnionGeometry.Max.Y / module.PartDiagonal.Y) + moduleDimensionSafetyBuffer.Y;
                     y++)
                {
                    for (int x = (int)Math.Floor(bBoxUnionGeometry.Min.X / module.PartDiagonal.X) - moduleDimensionSafetyBuffer.X;
                         x < Math.Ceiling(bBoxUnionGeometry.Max.X / module.PartDiagonal.X) + moduleDimensionSafetyBuffer.X;
                         x++)
                    {
                        var currentRelativePosition = new Point3i(x, y, z);
                        var currentPivot            = Plane.WorldXY;
                        currentPivot.Origin = currentRelativePosition.ToCartesian(Plane.WorldXY, module.PartDiagonal);

                        var transformModuleToCurrentPivot      = Transform.PlaneToPlane(module.Pivot, currentPivot);
                        var moduleGeometryBBoxesAtCurrentPivot = moduleGeometryBBoxes.Select(bBox => {
                            var transformedBBox = bBox;
                            transformedBBox.Transform(transformModuleToCurrentPivot);
                            return(transformedBBox);
                        });

                        var indicesOfSimilarBBoxes = moduleGeometryBBoxesAtCurrentPivot.Select(moduleGeometryBBox =>
                                                                                               geometryBBoxes.Select((geometryBBox, index) => {
                            var moduleCorners   = moduleGeometryBBox.GetCorners().ToList();
                            var geometryCorners = geometryBBox.GetCorners().ToList();
                            moduleCorners.Sort();
                            geometryCorners.Sort();
                            if (Enumerable.SequenceEqual(moduleCorners, geometryCorners))
                            {
                                return(index);
                            }
                            else
                            {
                                return(-1);
                            }
                        }).Where(index => index != -1)
                                                                                               );

                        // If any module geometry doesn't have a bbox similar to any geometry, then early continue
                        if (!indicesOfSimilarBBoxes.All(similarBBoxes => similarBBoxes.Any()))
                        {
                            continue;
                        }

                        // Heavy calculations

                        var transformedModuleGeometry = moduleGeometry.Select(geo => {
                            var transformedGeometry = geo.Duplicate();
                            transformedGeometry.Transform(transformModuleToCurrentPivot);
                            return(transformedGeometry);
                        });

                        var geometriesToCheck = indicesOfSimilarBBoxes.Select(indices => indices.Select(index => geometryClean[index]));

                        var geometryEqualityPattern = transformedModuleGeometry
                                                      .Zip(geometriesToCheck, (current, others) => others.Any(other =>
                                                                                                              // TODO: when the original geometry is moved, the meshes become unequal
                                                                                                              // TODO: replace with visual similarity check (pull random points to geometry)
                                                                                                              // TODO: check if the two are of the same type first
                                                                                                              GeometryBase.GeometryEquals(current, other)
                                                                                                              ));

                        if (geometryEqualityPattern.All(equal => equal))
                        {
                            var firstModulePartRelativeCenter = module.PartCenters[0];
                            var modulePartsRelativeCentersRelativeToModulePivot = module.PartCenters.Select(center => center - firstModulePartRelativeCenter);

                            var currentModuleSlots = modulePartsRelativeCentersRelativeToModulePivot
                                                     .Zip(
                                module.PartNames,
                                (partCenter, partName) => new Slot(basePlane,
                                                                   currentRelativePosition + partCenter,
                                                                   module.PartDiagonal,
                                                                   false,
                                                                   new List <string>()
                            {
                                module.Name
                            },
                                                                   new List <string>()
                            {
                                partName
                            },
                                                                   0));
                            slots.AddRange(currentModuleSlots);
                        }
                    }
                }
            }

            if (!Slot.AreSlotLocationsUnique(slots))
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Slot centers are not unique.");
            }

            DA.SetDataList(0, slots);
        }
Esempio n. 2
0
        /// <summary>
        /// Wrap input geometry into module cages.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from
        ///     input parameters and to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            var slots  = new List <Slot>();
            var layers = 1;

            if (!DA.GetDataList(0, slots))
            {
                return;
            }

            if (!DA.GetData(1, ref layers))
            {
                return;
            }

            var slotsClean = new List <Slot>();

            foreach (var slot in slots)
            {
                if (slot == null || !slot.IsValid)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Slot is null or invalid.");
                }
                else
                {
                    slotsClean.Add(slot);
                }
            }

            if (!slotsClean.Any())
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "No valid Slots collected.");
                return;
            }

            if (!Slot.AreSlotDiagonalsCompatible(slotsClean))
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error,
                                  "Slots are not defined with the same diagonal.");
                return;
            }
            var diagonal = slotsClean.First().Diagonal;

            if (!Slot.AreSlotBasePlanesCompatible(slotsClean))
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error,
                                  "Slots are not defined with the same base plane.");
                return;
            }
            var basePlane = slotsClean.First().BasePlane;

            if (!Slot.AreSlotLocationsUnique(slotsClean))
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Slot centers are not unique.");
                return;
            }

            var potentialRelativeNeighborCenters = new List <Point3i> {
                new Point3i(-1, 0, 0),
                new Point3i(0, -1, 0),
                new Point3i(0, 0, -1),
                new Point3i(1, 0, 0),
                new Point3i(0, 1, 0),
                new Point3i(0, 0, 1)
            };

            var allSlotCenters     = slotsClean.Select(slot => slot.RelativeCenter).ToList();
            var newNeighborCenters = new List <Point3i>();

            for (int l = 0; l < layers; l++)
            {
                var currentNewNeighborCenters = new List <Point3i>();

                for (var i = 0; i < allSlotCenters.Count; i++)
                {
                    var slotCenter             = allSlotCenters[i];
                    var currentNeighborCenters = new List <Point3i>();
                    foreach (var other in allSlotCenters)
                    {
                        if (slotCenter.IsNeighbor(other))
                        {
                            currentNeighborCenters.Add(other);
                            if (currentNeighborCenters.Count == 6)
                            {
                                break;
                            }
                        }
                    }
                    if (currentNeighborCenters.Count < 6)
                    {
                        var potentialNeighborCenters = potentialRelativeNeighborCenters
                                                       .Select(relativeNeighborCenter => slotCenter + relativeNeighborCenter);
                        var currentNewlNeighborCenters = potentialNeighborCenters.Except(currentNeighborCenters);
                        currentNewNeighborCenters.AddRange(currentNewlNeighborCenters);
                    }
                }

                newNeighborCenters = newNeighborCenters
                                     .Concat(currentNewNeighborCenters)
                                     .Distinct()
                                     .ToList();
                allSlotCenters.AddRange(currentNewNeighborCenters);
            }

            var newNeighborCentersP3d = newNeighborCenters
                                        .Select(p3i => p3i.ToCartesian(basePlane, diagonal));

            DA.SetDataList(0, newNeighborCentersP3d);
        }
Esempio n. 3
0
        /// <summary>
        /// Wrap input geometry into module cages.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from
        ///     input parameters and to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            var slots  = new List <Slot>();
            var layers = 1;

            if (!DA.GetDataList(0, slots))
            {
                return;
            }

            if (!DA.GetData(1, ref layers))
            {
                return;
            }

            var slotsClean = new List <Slot>();

            foreach (var slot in slots)
            {
                if (slot == null || !slot.IsValid)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Slot is null or invalid.");
                }
                else
                {
                    slotsClean.Add(slot);
                }
            }

            if (!slotsClean.Any())
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "No valid Slots collected.");
                return;
            }

            var diagonal = slotsClean.First().Diagonal;

            if (slotsClean.Any(slot => slot.Diagonal != diagonal))
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error,
                                  "Slots are not defined with the same diagonal.");
                return;
            }

            if (!Slot.AreSlotLocationsUnique(slotsClean))
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Slot locations are not unique.");
                return;
            }

            var boundaryPattern = Enumerable.Repeat(false, slotsClean.Count).ToList();

            for (int l = 0; l < layers; l++)
            {
                var currentBoundaryPattern = Enumerable.Repeat(true, slotsClean.Count).ToList();
                for (var i = 0; i < slotsClean.Count; i++)
                {
                    if (!boundaryPattern[i])
                    {
                        var slot           = slotsClean[i];
                        var neighborsCount = 0;
                        for (var j = 0; j < slotsClean.Count; j++)
                        {
                            if (!boundaryPattern[j])
                            {
                                var other = slotsClean[j];
                                if (slot.RelativeCenter.IsNeighbor(other.RelativeCenter) && ++neighborsCount == 6)
                                {
                                    currentBoundaryPattern[i] = false;
                                    break;
                                }
                            }
                        }
                    }
                }

                for (var i = 0; i < currentBoundaryPattern.Count; i++)
                {
                    boundaryPattern[i] |= currentBoundaryPattern[i];
                }
            }

            DA.SetDataList(0, boundaryPattern);
        }