Skip to content

Commit

Permalink
Implement component Rule Explicit between 2 lists of Modules and Conn…
Browse files Browse the repository at this point in the history
…ectors

The component `Rule Explicit between 2 lists` constructs Explicit Rules between all Conectors of source Modules with all Connectors of target Modules. Optionally filters out Rules that are invalid with the given Modules based on Module names, Connector counts and Connector Axis and Orientation.
  • Loading branch information
janper authored Mar 13, 2021
1 parent 2c71392 commit 4c5b831
Show file tree
Hide file tree
Showing 13 changed files with 239 additions and 27 deletions.
34 changes: 20 additions & 14 deletions Components/ModuleDeconstruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,28 +71,32 @@ protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager
"in base-plane-aligned XYZ axes. The Module Part Diagonal " +
"must match Envelope's Slot diagonals.",
GH_ParamAccess.item);
pManager.AddBooleanParameter("Is Compact",
"C",
"Does the Module hold together?",
GH_ParamAccess.item);
pManager.AddBooleanParameter("Is Valid",
"V",
"Is the Module valid for the Monoceros WFC Solver?",
GH_ParamAccess.item);
pManager.AddPlaneParameter("Connectors",
"CP",
"Connector planes",
GH_ParamAccess.list);
pManager.AddIntegerParameter("Connector Indices",
"CI",
"Connector indices",
GH_ParamAccess.list);
pManager.AddVectorParameter("Connector Directions",
"CD",
"Directions of connectors as unit vectors aligned to the " +
"base plane - a list parallel to CP.",
GH_ParamAccess.list);
pManager.AddBooleanParameter("Connector Use Pattern",
"UP",
"CU",
"Connector use pattern - a list parallel to CP. " +
"(only if R are provided)",
GH_ParamAccess.list);
pManager.AddBooleanParameter("Is Compact",
"C",
"Does the Module hold together?",
GH_ParamAccess.item);
pManager.AddBooleanParameter("Is Valid",
"V",
"Is the Module valid for the Monoceros WFC Solver?",
GH_ParamAccess.item);
}

/// <summary>
Expand Down Expand Up @@ -155,12 +159,14 @@ protected override void SolveInstance(IGH_DataAccess DA) {
DA.SetDataList(3, new List<Plane> { module.BasePlane });
DA.SetDataList(4, new List<Vector3d> { module.PartDiagonal });

DA.SetData(5, module.Compact);
DA.SetData(6, module.IsValid);

var connectors = module.Connectors;
DA.SetDataList(5, connectors.Select(connector => connector.AnchorPlane));
DA.SetDataList(6, connectors.Select(connector => connector.Direction.ToVector()));
DA.SetDataList(7, existingRules.Count > 0 ? connectorUsePattern : null);
DA.SetData(8, module.Compact);
DA.SetData(9, module.IsValid);
DA.SetDataList(7, connectors.Select(connector => connector.AnchorPlane));
DA.SetDataList(8, connectors.Select((_, i) => i));
DA.SetDataList(9, connectors.Select(connector => connector.Direction.ToVector()));
DA.SetDataList(10, existingRules.Count > 0 ? connectorUsePattern : null);
}

/// <summary>
Expand Down
181 changes: 181 additions & 0 deletions Components/RuleExplicit2Lists.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Grasshopper;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;

namespace Monoceros {

public class ComponentRuleExplicitBetweenTwoSets : GH_Component {
public ComponentRuleExplicitBetweenTwoSets( )
: base("Construct Explicit Rule Between 2 Lists",
"RuleExp2Lists",
"Construct a Monoceros Explicit Rule (connector-to-connector) between " +
"all listed Connectors of all listed Modules of two lists. The existence " +
"of the Module and the Connector as well as whether the Connectors are " +
"opposite is checked only if the optional list of all Modules is provided. " +
"Otherwise use Collect Rules component to remove the invalid 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 ModuleNameParameter(),
"Source Module Names",
"SMN",
"Source Module names",
GH_ParamAccess.tree);
pManager.AddParameter(new ConnectorIndexParameter(),
"Source Connector Indices",
"SC",
"Source Connector numbers",
GH_ParamAccess.tree);
pManager.AddParameter(new ModuleParameter(),
"All Modules",
"M",
"All Monoceros Modules (Optional)",
GH_ParamAccess.list);
pManager[2].Optional = true;
pManager.AddParameter(new ModuleNameParameter(),
"Target Module Names",
"TMN",
"Target Module names",
GH_ParamAccess.tree);
pManager.AddParameter(new ConnectorIndexParameter(),
"Target Connector Indices",
"TC",
"Target Connector numbers",
GH_ParamAccess.tree);
}

/// <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",
// TODO: consider returning a tree
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) {
if (!DA.GetDataTree(0, out GH_Structure<ModuleName> sourceNamesRaw)) {
return;
}
if (!DA.GetDataTree(1, out GH_Structure<ConnectorIndex> sourceConnectorIndicesRaw)) {
return;
}
if (!DA.GetDataTree(3, out GH_Structure<ModuleName> targetNamesRaw)) {
return;
}
if (!DA.GetDataTree(4, out GH_Structure<ConnectorIndex> targetConnectorIndicesRaw)) {
return;
}

var modules = new List<Module>();
var modulesClean = new List<Module>();
var modulesProvided = false;
if (DA.GetDataList(2, modules)) {
modulesProvided = true;
foreach (var module in modules) {
if (module == null || !module.IsValid) {
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "The module is null or invalid.");
continue;
}
modulesClean.Add(module);
}
}

var sourceLongestTreeCount = Math.Max(sourceNamesRaw.PathCount, sourceConnectorIndicesRaw.PathCount);
var targteLongestTreeCount = Math.Max(targetNamesRaw.PathCount, targetConnectorIndicesRaw.PathCount);

var rules = new List<Rule>();

for (var sourceTreeIteration = 0; sourceTreeIteration < sourceLongestTreeCount; sourceTreeIteration++) {
var sourceNamePath = sourceNamesRaw.Paths[Math.Min(sourceNamesRaw.PathCount - 1, sourceTreeIteration)];
var sourceConnectorPath = sourceConnectorIndicesRaw.Paths[Math.Min(sourceConnectorIndicesRaw.PathCount - 1, sourceTreeIteration)];

var sourceNames = sourceNamesRaw.get_Branch(sourceNamePath);
var sourceConnectorIndices = sourceConnectorIndicesRaw.get_Branch(sourceConnectorPath);

var sourceLongestListCount = Math.Max(sourceNames.Count, sourceConnectorIndices.Count);
for (var sourceListIteration = 0; sourceListIteration < sourceLongestListCount; sourceListIteration++) {
var sourceName = ((ModuleName)sourceNames[Math.Min(sourceNames.Count - 1, sourceListIteration)]).Name;
var sourceConnectorIndex = ((ConnectorIndex)sourceConnectorIndices[Math.Min(sourceConnectorIndices.Count - 1, sourceListIteration)]).Index;

for (var targetTreeIteration = 0; targetTreeIteration < targteLongestTreeCount; targetTreeIteration++) {

var targetNamePath = targetNamesRaw.Paths[Math.Min(targetNamesRaw.PathCount - 1, targetTreeIteration)];
var targetConnectorPath = targetConnectorIndicesRaw.Paths[Math.Min(targetConnectorIndicesRaw.PathCount - 1, targetTreeIteration)];

var targetNames = targetNamesRaw.get_Branch(targetNamePath);
var targetConnectorIndices = targetConnectorIndicesRaw.get_Branch(targetConnectorPath);

var targetLongestListCount = Math.Max(targetNames.Count, targetConnectorIndices.Count);
for (var targetListIteration = 0; targetListIteration < targetLongestListCount; targetListIteration++) {
var targetName = ((ModuleName)targetNames[Math.Min(targetNames.Count - 1, targetListIteration)]).Name;
var targetConnectorIndex = ((ConnectorIndex)targetConnectorIndices[Math.Min(targetConnectorIndices.Count - 1, targetListIteration)]).Index;

var rule = new Rule(sourceName, sourceConnectorIndex, targetName, targetConnectorIndex);

if (!rule.IsValid) {
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, rule.IsValidWhyNot);
continue;
}

if (!modulesProvided || rule.IsValidWithModules(modulesClean)) {
rules.Add(rule);
}
}

}
}
}

var rulesDeduplicated = rules.Distinct().ToList();
rulesDeduplicated.Sort();

if (!rulesDeduplicated.Any()) {
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Failed to construct any Rule.");
return;
}


DA.SetDataList(0, rulesDeduplicated);
}


/// <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.primary;

/// <summary>
/// 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_explicit_construct_2_lists;

/// <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("1FD4E379-3A9D-40FD-8A5E-113DC8AF9431");
}
}
20 changes: 11 additions & 9 deletions Components/RuleExplicitConstruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ public class ComponentConstructRuleExplicit : GH_Component {
public ComponentConstructRuleExplicit( )
: base("Construct Explicit Rule",
"RuleExp",
"Construct a Monoceros Explicit Rule (connector-to-connector) from Monoceros Module " +
"name and connector number. The existence of the module and connector as " +
"well as whether the connectors are opposite is not being checked.",
"Construct a Monoceros Explicit Rule (connector-to-connector) from " +
"Monoceros Module name and connector number. The existence " +
"of the Module and the Connector as well as whether the Connectors " +
"are opposite is not being checked. Use Collect Rules component " +
"to remove the invalid Rules.",
"Monoceros",
"Rule") {
}
Expand All @@ -20,24 +22,24 @@ public ComponentConstructRuleExplicit( )
/// </summary>
protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager) {
pManager.AddParameter(new ModuleNameParameter(),
"Source Module",
"Source Module Name",
"SMN",
"Source module name",
"Source Module name",
GH_ParamAccess.item);
pManager.AddParameter(new ConnectorIndexParameter(),
"Source Connector Index",
"SC",
"Source connector number",
"Source Connector number",
GH_ParamAccess.item);
pManager.AddParameter(new ModuleNameParameter(),
"Target Module",
"Target Module Name",
"TMN",
"Target module name",
"Target Module name",
GH_ParamAccess.item);
pManager.AddParameter(new ConnectorIndexParameter(),
"Target Connector Index",
"TC",
"Target connector number",
"Target Connector number",
GH_ParamAccess.item);
}

Expand Down
2 changes: 1 addition & 1 deletion Components/RuleFromSlots.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
namespace Monoceros {
public class ComponentScanSlotsForRules : GH_Component {

public ComponentScanSlotsForRules( ) : base("Scan Slots For rules",
public ComponentScanSlotsForRules( ) : base("Scan Slots for Rules",
"RulesScan",
"Scan solved Slots and extract applied Rules.",
"Monoceros",
Expand Down
5 changes: 5 additions & 0 deletions Components/RuleUnwrap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ protected override void SolveInstance(IGH_DataAccess DA) {
var rulesDeduplicated = rulesExplicit.Concat(rulesTypedUnwrapped).Distinct().ToList();
rulesDeduplicated.Sort();

if (!rulesDeduplicated.Any()) {
AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Failed to unwrap any Rule.");
return;
}

foreach (var rule in rulesDeduplicated) {
if (!rule.IsValid) {
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, rule.IsValidWhyNot);
Expand Down
2 changes: 1 addition & 1 deletion Components/SlotsFromGeometry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace Monoceros {
public class ComponentSlotsFromgeometry : GH_Component {
public ComponentSlotsFromgeometry( ) : base("Slots FromGeometry",
public ComponentSlotsFromgeometry( ) : base("Slots From Geometry",
"SlotsFromGeometry",
"Identify Module geometry and construct Slots containing it. Ignores connection to boundary.",
"Monoceros", "Slot") {
Expand Down
2 changes: 2 additions & 0 deletions Monoceros.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Components\RuleExplicit2Lists.cs" />
<Compile Include="Components\SlotsFromGeometry.cs" />
<Compile Include="Components\RuleFromSlots.cs" />
<Compile Include="Components\RuleAssemble.cs" />
Expand Down Expand Up @@ -128,6 +129,7 @@
<Content Include="DynamicLinkingDependencies\GH_IO.dll" />
<Content Include="DynamicLinkingDependencies\Grasshopper.dll" />
<Content Include="DynamicLinkingDependencies\RhinoCommon.dll" />
<None Include="Resources\rule-explicit-construct-2-lists.png" />
<None Include="Resources\rules-from-slots.png" />
<None Include="Resources\slots-from-geometry.png" />
<None Include="Resources\rule-out-construct.png" />
Expand Down
4 changes: 2 additions & 2 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.3.1")]
[assembly: AssemblyFileVersion("1.2.3.1")]
[assembly: AssemblyVersion("1.2.3.2")]
[assembly: AssemblyFileVersion("1.2.3.2")]
10 changes: 10 additions & 0 deletions Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@
<data name="rule_explicit_construct" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\rule-explicit-construct.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="rule_explicit_construct_2_lists" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\rule-explicit-construct-2-lists.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="rule_explicit_deconstruct" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\rule-explicit-deconstruct.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
Expand Down
Binary file added Resources/rule-explicit-construct-2-lists.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions Types/Rule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,9 @@ public int CompareTo(RuleExplicit other) {
result = TargetModuleName.CompareTo(other.TargetModuleName);
if (result == 0) {
result = SourceConnectorIndex.CompareTo(other.SourceConnectorIndex);
if (result == 0) {
result = TargetConnectorIndex.CompareTo(other.TargetConnectorIndex);
}
}
}
return result;
Expand Down
Binary file modified bin/Monoceros.pdb
Binary file not shown.

0 comments on commit 4c5b831

Please sign in to comment.