Beispiel #1
0
        /// <summary>
        /// De-serialization. Required by Grasshopper for data internalization.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <returns>True when successful.</returns>
        public bool Read(GH_IReader reader)
        {
            var formatter = new BinaryFormatter();

            if (reader.ItemExists("SlotData"))
            {
                var slotBytes = reader.GetByteArray("SlotData");
                using (var slotDataStream = new System.IO.MemoryStream(slotBytes)) {
                    try {
                        var slot = (Slot)formatter.Deserialize(slotDataStream);
                        BasePlane          = slot.BasePlane;
                        RelativeCenter     = slot.RelativeCenter;
                        Diagonal           = slot.Diagonal;
                        AllowsAnyModule    = slot.AllowsAnyModule;
                        AllowedModuleNames = slot.AllowedModuleNames;
                        AllowedPartNames   = slot.AllowedPartNames;
                        AllPartsCount      = slot.AllPartsCount;
                        return(true);
                    } catch (SerializationException e) {
                        throw e;
                    }
                }
            }

            return(false);
        }
Beispiel #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Slot"/> class.
        /// </summary>
        /// <param name="basePlane">The base plane - has to match with the other
        ///     <see cref="Slot"/>s of the World.</param>
        /// <param name="relativeCenter">The relative center.</param>
        /// <param name="diagonal">The <see cref="Slot"/> diagonal - has to
        ///     match with the other <see cref="Slot"/>s of the World and with
        ///     all <see cref="Module"/>s</param>
        /// <param name="allowAnyModule">If true, any part can be placed into
        ///     the <see cref="Slot"/>.</param>
        /// <param name="allowedModules">The allowed modules.</param>
        /// <param name="allowedParts">The allowed parts.</param>
        /// <param name="allPartsCount">The all parts count.</param>
        public Slot(Plane basePlane,
                    Point3i relativeCenter,
                    Vector3d diagonal,
                    bool allowAnyModule,
                    List <string> allowedModules,
                    List <string> allowedParts,
                    int allPartsCount)
        {
            if (diagonal.X <= 0 || diagonal.Y <= 0 || diagonal.Z <= 0)
            {
                throw new Exception("One or more slot dimensions are not larger than 0.");
            }

            if (allPartsCount < 0)
            {
                throw new Exception("All parts count is lower than 0.");
            }

            Diagonal           = diagonal;
            BasePlane          = basePlane;
            RelativeCenter     = relativeCenter;
            AllowsAnyModule    = allowAnyModule;
            AllowedModuleNames = allowedModules;
            AllowedPartNames   = allowedParts;
            AllPartsCount      = allPartsCount;
        }
Beispiel #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 point     = new Point3d();
            var basePlane = new Plane();
            var diagonal  = new Vector3d();

            if (!DA.GetData(0, ref point))
            {
                return;
            }

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

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

            if (diagonal.X <= 0 || diagonal.Y <= 0 || diagonal.Z <= 0)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "One or more slot dimensions are not larger than 0.");
                return;
            }

            // Scale down to unit size
            var normalizationTransform = Transform.Scale(basePlane,
                                                         1 / diagonal.X,
                                                         1 / diagonal.Y,
                                                         1 / diagonal.Z);
            // Orient to the world coordinate system
            var worldAlignmentTransform = Transform.PlaneToPlane(basePlane, Plane.WorldXY);

            point.Transform(normalizationTransform);
            point.Transform(worldAlignmentTransform);
            // Round point location
            // Slot dimension is for the sake of this calculation 1,1,1
            var slotCenterPoint = new Point3i(point);

            var slot = new Slot(basePlane,
                                slotCenterPoint,
                                diagonal,
                                true,
                                new List <string>(),
                                new List <string>(),
                                0);

            if (!slot.IsValid)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, slot.IsValidWhyNot);
                return;
            }

            DA.SetData(0, slot);
        }
Beispiel #4
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 modules   = new List <Module>();
            var rule      = new Rule();
            var basePlane = new Plane();

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

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

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

            var transforms = new DataTree <Transform>();
            var geometry   = new DataTree <GeometryBase>();


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

            if (!rule.IsExplicit)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error,
                                  "Rule Assemble works only with Monoceros Explicit Rules to " +
                                  "make sure a single Rule generate a single assembly. " +
                                  "Unwrap Monoceros Rules first.");
                return;
            }

            //if (rule.Explicit.SourceModuleName == Config.OUTER_MODULE_NAME
            //    || rule.Explicit.TargetModuleName == Config.OUTER_MODULE_NAME
            //    || rule.Explicit.SourceModuleName == Config.EMPTY_MODULE_NAME
            //    || rule.Explicit.TargetModuleName == Config.EMPTY_MODULE_NAME) {
            //    AddRuntimeMessage(GH_RuntimeMessageLevel.Error,
            //                      "Catalog cannot display a Monoceros Rule describing a connection " +
            //                      "to an outer or empty Monoceros Module.");
            //    return;
            //}

            var invalidModuleCount = modules.RemoveAll(module => module == null || !module.IsValid);

            if (invalidModuleCount > 0)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error,
                                  invalidModuleCount + " Modules are null or invalid and were removed.");
            }

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

            if (!rule.IsValidWithModules(modules))
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error,
                                  "The Monoceros Rule is not valid with the given Monoceros Modules.");
                return;
            }

            var sourceModule    = modules.Find(module => module.Name == rule.Explicit.SourceModuleName);
            var sourceConnector = sourceModule.Connectors[rule.Explicit.SourceConnectorIndex];
            var targetModule    = modules.Find(module => module.Name == rule.Explicit.TargetModuleName);
            var targetConnector = targetModule.Connectors[rule.Explicit.TargetConnectorIndex];

            if (sourceModule.BasePlane != targetModule.BasePlane)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error,
                                  "The source and target Modules are not defined with the same Base Plane. " +
                                  "The resulting Slots would be incompatible.");
                return;
            }

            if (sourceModule.PartDiagonal != targetModule.PartDiagonal)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error,
                                  "The source and target Module Part Diagonals are not identical. " +
                                  "The Modules are incompatible.");
                return;
            }

            var allPartsCount = sourceModule.PartCenters.Count + targetModule.PartCenters.Count;

            var sourcePivotOffset = Point3i.FromCartesian(sourceModule.Pivot.Origin,
                                                          sourceModule.BasePlane,
                                                          sourceModule.PartDiagonal);

            var sourceSlots = new List <Slot>();

            for (var i = 0; i < sourceModule.PartNames.Count; i++)
            {
                var sourceModulePartCenter = sourceModule.PartCenters[i] - sourcePivotOffset;
                var sourceModulePartName   = sourceModule.PartNames[i];
                var slot = new Slot(basePlane,
                                    sourceModulePartCenter,
                                    sourceModule.PartDiagonal,
                                    false,
                                    new List <string> {
                    sourceModule.Name
                },
                                    new List <string> {
                    sourceModulePartName
                },
                                    allPartsCount);
                sourceSlots.Add(slot);
            }

            var targetToSourceTransfrom = Transform.PlaneToPlane(targetConnector.AnchorPlane, sourceConnector.AnchorPlane);
            var targetPartCenters       = targetModule.PartCenters.Select(center => center.ToCartesian(targetModule.BasePlane, targetModule.PartDiagonal));

            var targetSlots = new List <Slot>();

            for (var i = 0; i < targetModule.PartNames.Count; i++)
            {
                var targetModulePartCenterCartesian = targetModule
                                                      .PartCenters[i]
                                                      .ToCartesian(targetModule.BasePlane, targetModule.PartDiagonal);
                targetModulePartCenterCartesian.Transform(targetToSourceTransfrom);
                var targetModulePartCenter = Point3i.FromCartesian(targetModulePartCenterCartesian,
                                                                   sourceModule.BasePlane,
                                                                   sourceModule.PartDiagonal) - sourcePivotOffset;
                var targetModulePartName = targetModule.PartNames[i];
                var slot = new Slot(basePlane,
                                    targetModulePartCenter,
                                    targetModule.PartDiagonal,
                                    false,
                                    new List <string> {
                    targetModule.Name
                },
                                    new List <string> {
                    targetModulePartName
                },
                                    allPartsCount);
                targetSlots.Add(slot);
            }

            DA.SetDataList(0, sourceSlots);
            DA.SetDataList(1, targetSlots);
        }
Beispiel #5
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);
        }
Beispiel #6
0
 /// <summary>
 /// Checks if two discrete points are neighbors in one of the 6
 /// directions in the discrete grid world.
 /// </summary>
 /// <param name="other">The other point.</param>
 /// <returns>True if neighbors</returns>
 public bool IsNeighbor(Point3i other)
 {
     return((Math.Abs(X - other.X) == 1 && Y == other.Y && Z == other.Z) ||
            (X == other.X && Math.Abs(Y - other.Y) == 1 && Z == other.Z) ||
            (X == other.X && Y == other.Y && (Math.Abs(Z - other.Z) == 1)));
 }
        /// <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 point             = new Point3d();
            var basePlane         = new Plane();
            var diagonal          = new Vector3d();
            var allowedModulesRaw = new List <ModuleName>();
            var allModules        = new List <Module>();
            var modulesProvided   = false;

            if (!DA.GetData(0, ref point))
            {
                return;
            }

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

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

            if (!DA.GetDataList(3, allowedModulesRaw))
            {
                return;
            }

            if (DA.GetDataList(4, allModules))
            {
                modulesProvided = true;
            }

            var allowedModules = allowedModulesRaw
                                 .Where(name => name != null)
                                 .Select(name => name.Name).Distinct().ToList();

            if (Config.RESERVED_CHARS.Any(chars => allowedModules.Contains(chars)))
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Input text contains " +
                                  "a forbidden content: :, ->, = or newline.");
                return;
            }

            if (diagonal.X <= 0 || diagonal.Y <= 0 || diagonal.Z <= 0)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error,
                                  "One or more slot dimensions are not larger than 0.");
                return;
            }

            // Scale down to unit size
            var normalizationTransform = Transform.Scale(basePlane,
                                                         1 / diagonal.X,
                                                         1 / diagonal.Y,
                                                         1 / diagonal.Z);
            // Orient to the world coordinate system
            var worldAlignmentTransform = Transform.PlaneToPlane(basePlane, Plane.WorldXY);

            point.Transform(normalizationTransform);
            point.Transform(worldAlignmentTransform);
            // Round point location
            // Slot dimension is for the sake of this calculation 1,1,1
            var slotCenterPoint = new Point3i(point);

            var allModulesCount = modulesProvided
                ? allModules.Aggregate(0, (count, module) => count + module.PartCenters.Count)
                : 0;

            var allowedParts = modulesProvided
                ? allModules
                               .Where(module => allowedModules.Contains(module.Name))
                               .SelectMany(module => module.PartNames)
                               .ToList()
                : new List <string>();

            var slot = new Slot(basePlane,
                                slotCenterPoint,
                                diagonal,
                                false,
                                allowedModules,
                                allowedParts,
                                allModulesCount);

            if (!slot.IsValid)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, slot.IsValidWhyNot);
                return;
            }

            DA.SetData(0, slot);
        }