Skip to content

Commit

Permalink
Merge pull request #15 from daniel-fink/speckle-interop
Browse files Browse the repository at this point in the history
Speckle interop
  • Loading branch information
daniel-fink authored Jun 3, 2023
2 parents 648e3f6 + f6adc16 commit 4cabed1
Show file tree
Hide file tree
Showing 69 changed files with 12,239 additions and 1,572 deletions.
68 changes: 68 additions & 0 deletions RangekeeperGrasshopper/Assembly.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Objects.Organization;
using Speckle.Core.Models;

namespace Rangekeeper;

public class Assembly : Base, IEntity
{
public Assembly() { }

public string entityId { get; }

public string name { get; }

public string type { get; }

// public new string collectionType => "Rangekeeper Assembly";

[DetachProperty]
public HashSet<Base> entities { get; } = new (new Assembly.BaseComparer());

public List<string> entityIds => this.entities
.Select(obj => { obj
.TryGetProperty("entityId", out object entityId);
return (string)entityId; })
.ToList();

public List<Relationship> relationships { get; } = new();

public Assembly(string name, string type)
{
this.name = name;
this.type = type;
this.entityId = Guid.NewGuid().ToString();
this.entities.Add(this);
}

public void AddRelationship(Relationship relationship)
{
if (!this.relationships.Contains(relationship))
{
this.relationships.Add(relationship);
this.entities.Add(relationship.source);
this.entities.Add(relationship.target);
}
}

public class BaseComparer : IEqualityComparer<Base>
{
public bool Equals(Base entity, Base? other)
{
if (other is null) return false;
if (ReferenceEquals(entity, other)) return true;
if (!entity.TryGetProperty("entityId", out object entityId) || !other.TryGetProperty("entityId", out object otherId))
{
throw new ArgumentException("Error: Base Object is not an Entity as it does not have an 'entityId' property");
}
return (string)entityId == (string)otherId;
}

public int GetHashCode(Base entity)
{
return entity.GetHashCode();
}
}
}
62 changes: 62 additions & 0 deletions RangekeeperGrasshopper/Components/AssemblyParam.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;
using System.Drawing;
using Grasshopper.Kernel;
using RangekeeperGrasshopper;

namespace Rangekeeper.Components;

public class AssemblyParam : GH_Param<GH_Assembly>
{
// public bool IsSchemaBuilderOutput;

// public bool UseSchemaTag;

public AssemblyParam(
string name,
string nickname,
string description,
GH_ParamAccess access,
bool isSchemaBuilderOutput = false
)
: this(name, nickname, description, "Params", "Primitive", access)
{
// IsSchemaBuilderOutput = isSchemaBuilderOutput;
}

public AssemblyParam(
string name,
string nickname,
string description,
string category,
string subcategory,
GH_ParamAccess access
)
: base(name, nickname, description, category, subcategory, access) { }

public AssemblyParam() : this(
"Rangekeeper Assembly Object",
"RKA",
"Rangekeeper Assembly, derived from a Speckle Collection",
GH_ParamAccess.item)
{ }

public override Guid ComponentGuid => new("6B901C91-6C3D-40E1-803D-C9226A58A4BB");
protected override Bitmap Icon => Resources.AssemblyParamIcon;
public override GH_Exposure Exposure => GH_Exposure.tertiary;

// public override GH_StateTagList StateTags
// {
// get
// {
// var tags = base.StateTags;
// if (Kind != GH_ParamKind.output)
// return tags;
// if (!IsSchemaBuilderOutput)
// return tags;
// // if (UseSchemaTag)
// // tags.Add(new SchemaTagStateTag());
//
// return tags;
// }
// }
}
155 changes: 155 additions & 0 deletions RangekeeperGrasshopper/Components/CreateAssembly.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 System.Threading.Tasks;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Types;
using Speckle.Core.Models;
using Rangekeeper;
using RangekeeperGrasshopper;

namespace Rangekeeper.Components
{
public class CreateAssembly : GH_Component
{
public CreateAssembly()
: base(
"Create Rangekeeper Assembly",
"CRA",
"Create a Rangekeeper Assembly by providing Source and Target Speckle Object(s), with respective Relationship Type(s) as text.",
"Rangekeeper",
"Rangekeeper"
)
{ }

protected override Bitmap Icon => Resources.CreateAssemblyIcon;

public override Guid ComponentGuid => new("7CE1F751-0A1D-40F1-9B9C-17F71EB9394D");

protected override void RegisterInputParams(GH_InputParamManager pManager)
{
pManager.AddTextParameter(
"Assembly Name",
"N",
"Name of the Assembly",
GH_ParamAccess.item);

pManager.AddTextParameter(
"Type",
"Ty",
"Type of Assembly. (It is best to use a standardised vocabulary)",
GH_ParamAccess.item);

pManager.AddGenericParameter(
"Source Speckle Objects",
"S",
"Speckle Objects from which a Relationship originates. If this is empty, the Assembly itself will be used as source for all Relationships.",
GH_ParamAccess.list);
pManager[2].Optional = true;

pManager.AddGenericParameter(
"Target Speckle Objects",
"T",
"Speckle Objects to which a Relationship is directed. If this is empty, the Assembly itself will be used as target for all Relationships.",
GH_ParamAccess.list);
pManager[3].Optional = true;

pManager.AddTextParameter(
"Relationship Types",
"R",
"Relationship Types that describe how Source Speckle Objects are related to Target Speckle Objects. " +
"(It is best to use a standardised vocabulary.)",
GH_ParamAccess.list);
}

protected override void RegisterOutputParams(GH_OutputParamManager pManager)
{
pManager.AddParameter(new AssemblyParam("Assembly", "A", "Rangekeeper Assembly", GH_ParamAccess.item));
}

protected sealed override void SolveInstance(IGH_DataAccess DA)
{
var name = string.Empty;
DA.GetData(0, ref name);

var type = string.Empty;
DA.GetData(1, ref type);

var sources = new List<IGH_Goo>();
if (!DA.GetDataList(2, sources))
{
this.AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "No Source Objects supplied. Using Assembly itself as source.");
}

var targets = new List<IGH_Goo>();
if (!DA.GetDataList(3, targets))
{
this.AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "No Target Objects supplied. Using Assembly itself as target.");
}

var relationshipTypes = new List<string>();
if (!DA.GetDataList(4, relationshipTypes))
{
this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "No Relationship Types supplied.");
return;
}

var sourceEntities = new List<Base>();
foreach (var source in sources)
{
if (source.CanConvertToBase(null, out Base? baseObject, out string? remark))
{
if (baseObject.TryGetProperty("entityId", out object entityId)) sourceEntities.Add(baseObject);
else
{
this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, string.Format("Error: Source Object does not have an entityId property"));
return;
}
}
else
{
this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, string.Format("Error: Source Object is not a Speckle Object: {0}.", remark));
return;
}
}

var targetEntities = new List<Base>();
foreach (var target in targets)
{
if (target.CanConvertToBase(null, out Base? baseObject, out string? remark))
{
if (baseObject.TryGetProperty("entityId", out object entityId)) targetEntities.Add(baseObject);
else
{
this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, string.Format("Error: Source Object does not have an entityId property: {0}.", remark));
return;
}
}
else
{
this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, string.Format("Error: Source Object is not a Speckle Object: {0}.", remark));
return;
}
}

var assembly = new Assembly(name, type);
if (sourceEntities.Count == 0)
{
sourceEntities.AddRange(Enumerable.Repeat((Base)assembly, targetEntities.Count));
}
if (!(sourceEntities.Count == targetEntities.Count && targetEntities.Count == relationshipTypes.Count))
{
this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Error: Number of Sources, Targets and Relationships must match.");
return;
}

for (int i = 0; i < relationshipTypes.Count; i++)
{
assembly.AddRelationship(new Relationship(sourceEntities[i], targetEntities[i], relationshipTypes[i]));
}

DA.SetData(0, assembly);
}
}
}
63 changes: 63 additions & 0 deletions RangekeeperGrasshopper/Components/GH_Assembly.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using Grasshopper.Kernel.Types;
using Speckle.Core.Models;
using Speckle.Core.Models.Extensions;

namespace Rangekeeper.Components;

public class GH_Assembly : GH_Goo<Assembly>
{
public override IGH_Goo Duplicate() => new GH_Assembly() { m_value = m_value.ShallowCopy() as Assembly };

public override string ToString() => $"Rangekeeper Assembly [{m_value?.name ?? "No name"}]";

public override bool IsValid => m_value != null;
public override string TypeName => "Rangekeeper Assembly";
public override string TypeDescription => "Represents an Assembly object from Rangekeeper, derived from a Speckle Collection";

public override bool CastFrom(object source)
{
switch (source)
{
case Assembly assembly:
Value = assembly;
return true;
case GH_Assembly gooAssembly:
Value = gooAssembly.Value;
return true;
case GH_Goo<Base> goo:
if (goo.Value is Assembly gooBaseAssembly)
{
Value = gooBaseAssembly;
return true;
}
break;
}
return false;
}

public override bool CastTo<Q>(ref Q target)
{
var success = false;
var type = typeof(Q);

if (type == typeof(Assembly))
{
target = (Q)(object)this.Value;
success = true;
}

else if (type == typeof(GH_Assembly))
{
target = (Q)(object)new GH_Assembly { Value = Value };
success = true;
}

else if (type == typeof(GH_Goo<Base>))
{
target = (Q)(object)(Base)this.Value;
success = true;
}

return success;
}
}
Loading

0 comments on commit 4cabed1

Please sign in to comment.