Skip to content

Commit

Permalink
Implement components for rule suggestion by example
Browse files Browse the repository at this point in the history
  • Loading branch information
janper authored Mar 9, 2021
1 parent 13a09e9 commit b3ab254
Show file tree
Hide file tree
Showing 30 changed files with 636 additions and 44 deletions.
2 changes: 1 addition & 1 deletion Components/ModuleConstruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ protected override void SolveInstance(IGH_DataAccess DA) {
return;
}

if (name.Contains("\n") || name.Contains(":") || name.Contains("=")) {
if (Config.RESERVED_CHARS.Any(chars => name.Contains(chars))) {
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Monoceros Module name contains " +
"a forbidden content: :, ->, = or newline.");
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ private uint DirectionToSingleModuleConnectorIndex(Direction direction) {
/// Provides an Icon for every component that will be visible in the
/// User Interface. Icons need to be 24x24 pixels.
/// </summary>
protected override System.Drawing.Bitmap Icon => Properties.Resources.rule_out;
protected override System.Drawing.Bitmap Icon => Properties.Resources.rule_out_construct;

/// <summary>
/// Each component must have a unique Guid to identify it. It is vital
Expand Down
File renamed without changes.
9 changes: 3 additions & 6 deletions Components/RuleExplicitConstruct.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using Grasshopper.Kernel;

namespace Monoceros {
Expand Down Expand Up @@ -83,12 +84,8 @@ protected override void SolveInstance(IGH_DataAccess DA) {
var sourceName = sourceNameRaw.Name;
var targetName = targetNameRaw.Name;

if (sourceName.Contains("\n")
|| sourceName.Contains(":")
|| sourceName.Contains("=")
|| targetName.Contains("\n")
|| targetName.Contains(":")
|| targetName.Contains("=")) {
if (Config.RESERVED_CHARS.Any(chars => sourceName.Contains(chars))
|| Config.RESERVED_CHARS.Any(chars => targetName.Contains(chars))) {
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Input text contains " +
"a forbidden content: :, ->, = or newline.");
return;
Expand Down
155 changes: 155 additions & 0 deletions Components/RuleFromSlots.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using Grasshopper;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Rhino;
using Rhino.DocObjects;
using Rhino.Geometry;

namespace Monoceros {
public class ComponentScanSlotsForRules : GH_Component {

public ComponentScanSlotsForRules( ) : base("Scan Slots For rules",
"RulesScan",
"Scan solved Slots and extract applied Rules.",
"Monoceros",
"Rule") {
}

/// <summary>
/// Registers all the input parameters for this component.
/// </summary>
protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) {
pManager.AddParameter(new SlotParameter(),
"Slots",
"S",
"Monoceros Slots",
GH_ParamAccess.list);
pManager.AddParameter(new ModuleParameter(),
"Modules",
"M",
"All Monoceros Modules",
GH_ParamAccess.list);
}

/// <summary>
/// Registers all the output parameters for this component.
/// </summary>
protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager) {
pManager.AddParameter(new RuleParameter(),
"Rules Explicit",
"R",
"Explicit Monoceros Rules",
GH_ParamAccess.list);
}

/// <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 modulesRaw = new List<Module>();
var slotsRaw = new List<Slot>();

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

if (!DA.GetDataList(1, modulesRaw)) {
return;
}

var slotsClean = new List<Slot>();
foreach (var slot in slotsRaw) {
if (slot == null || !slot.IsValid) {
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Slot is null or invalid and will be skipped.");
continue;
}
if (!slot.IsDeterministic) {
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Slot is not deterministic and will be skipped.");
continue;
}
slotsClean.Add(slot);
}

var modulesClean = new List<Module>();
foreach (var module in modulesRaw) {
if (module == null || !module.IsValid) {
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Module is null or invalid.");
continue;
}
if (module.Geometry.Count + module.ReferencedGeometry.Count == 0) {
AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Module \"" + module.Name + "\" contains " +
"no geometry and therefore will be skipped.");
continue;
}

modulesClean.Add(module);
}

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

var slotsNonEmpty = slotsClean.Where(slot =>
modulesClean.Any(module => module.ContainsPart(slot.AllowedPartNames[0]))
);

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

var rulesOut = new List<Rule>();
foreach (var slot in slotsNonEmpty) {
foreach (var slotOther in slotsNonEmpty) {
if (slot.RelativeCenter.IsNeighbor(slotOther.RelativeCenter)) {
var neighborVector = (slotOther.RelativeCenter - slot.RelativeCenter).ToVector3d();
if (Direction.FromVector(neighborVector, out var direction)
&& direction.Orientation == Orientation.Positive) {
var currentPart = slot.AllowedPartNames[0];
var otherPart = slotOther.AllowedPartNames[0];
var ruleForSolver = new RuleForSolver(direction.Axis, currentPart, otherPart);
if (RuleExplicit.FromRuleForSolver(ruleForSolver, modulesClean, out var ruleExplicit)) {
var rule = new Rule(ruleExplicit);
if (!rulesOut.Contains(rule)) {
rulesOut.Add(rule);
}
}
}
}
}
}

rulesOut.Sort();
DA.SetDataList(0, rulesOut);
}

/// <summary>
/// The Exposure property controls where in the panel a component icon
/// will appear. There are seven possible locations (primary to
/// septenary), each of which can be combined with the
/// GH_Exposure.obscure flag, which ensures the component will only be
/// visible on panel dropdowns.
/// </summary>
public override GH_Exposure Exposure => GH_Exposure.quinary;

/// <summary>
/// Provides an Icon for every component that will be visible in the
/// User Interface. Icons need to be 24x24 pixels.
/// </summary>
protected override Bitmap Icon => Properties.Resources.rules_from_slots;

/// <summary>
/// Each component must have a unique Guid to identify it. It is vital
/// this Guid doesn't change otherwise old ghx files that use the old ID
/// will partially fail during loading.
/// </summary>
public override Guid ComponentGuid => new Guid("14CD0308-26FC-4134-AB5A-C7B89B6405BF");
}
}
2 changes: 1 addition & 1 deletion Components/RuleIndifferentConstruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ protected override void SolveInstance(IGH_DataAccess DA) {
/// Provides an Icon for every component that will be visible in the
/// User Interface. Icons need to be 24x24 pixels.
/// </summary>
protected override System.Drawing.Bitmap Icon => Properties.Resources.rule_indifferent;
protected override System.Drawing.Bitmap Icon => Properties.Resources.rule_indifferent_construct;

/// <summary>
/// Each component must have a unique Guid to identify it. It is vital
Expand Down
9 changes: 3 additions & 6 deletions Components/RuleTypedConstruct.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using Grasshopper.Kernel;

namespace Monoceros {
Expand Down Expand Up @@ -68,12 +69,8 @@ protected override void SolveInstance(IGH_DataAccess DA) {

var moduleName = moduleNameRaw.Name;

if (moduleName.Contains("\n")
|| moduleName.Contains(":")
|| moduleName.Contains("=")
|| type.Contains("\n")
|| type.Contains(":")
|| type.Contains("=")) {
if (Config.RESERVED_CHARS.Any(chars => moduleName.Contains(chars))
|| Config.RESERVED_CHARS.Any(chars => type.Contains(chars))) {
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Input text contains " +
"a forbidden content: :, ->, = or newline.");
return;
Expand Down
4 changes: 1 addition & 3 deletions Components/RuleTypedFromPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,7 @@ protected override void SolveInstance(IGH_DataAccess DA) {
return;
}

if (type.Contains("\n")
|| type.Contains(":")
|| type.Contains("=")) {
if (Config.RESERVED_CHARS.Any(chars => type.Contains(chars))) {
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Input text contains " +
"a forbidden content: :, ->, = or newline.");
return;
Expand Down
File renamed without changes.
6 changes: 2 additions & 4 deletions Components/SlotConstructWithModules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,9 @@ protected override void SolveInstance(IGH_DataAccess DA) {

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

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

Expand Down
2 changes: 1 addition & 1 deletion Components/SlotDeconstruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ protected override void SolveInstance(IGH_DataAccess DA) {
} else {
DA.SetDataList(4, new List<bool>() { slot.AllowsAnyModule });
}
DA.SetDataList(5, new List<bool>() { slot.AllowsNothing });
DA.SetDataList(5, new List<bool>() { slot.IsContradictory });
if (modulesProvided
&& moduleNames != null
&& (slot.AllowedModuleNames.Count > moduleNames.Count
Expand Down
2 changes: 1 addition & 1 deletion Components/SlotsAddBoundary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ protected override void SolveInstance(IGH_DataAccess DA) {
/// Provides an Icon for every component that will be visible in the
/// User Interface. Icons need to be 24x24 pixels.
/// </summary>
protected override Bitmap Icon => Properties.Resources.slot_add_boundary_2;
protected override Bitmap Icon => Properties.Resources.slot_add_boundary;

/// <summary>
/// Each component must have a unique Guid to identify it. It is vital
Expand Down
Loading

0 comments on commit b3ab254

Please sign in to comment.