Code Monkey home page Code Monkey logo

elements's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

elements's Issues

IFC Integration

Elements should be able to query information out of an IFC file. Although full coverage of IFC is a long way off, Elements should at least understand the types for which a mapping makes sense (i.e. Walls, Floors, Spaces, Structural).

  • Create an updated NuGet package for IFC-dotnet - > Hypar.IFC.
  • Add Hypar.IFC dependency to Hypar.Elements.
  • Move Elements namespace out of IFC-dotnet into Hypar.IFC
  • Create new api Model.FromIFC(string ifcPath)
  • Implement conversion of IFC BaseIfc instances to Element instances.

Return elements collection.

In Model.ToHypar(), return an the elements collection with the key elements.

  • Update the API to store this value in the db.

Add Polygon class.

A Polygon is closed, planar, n-sided geometry.

  • Use polygons in Spaces, Floors, and other locations where an IEnumerable<Polygon> would make sense.
  • Check planarity and closedness at construction.
  • Check that first and last point are equivalent.

Transform Operations

Create a number of operations on a transform:

var t = new Transform();
t.Scale = new Vector();
t.Rotation = 42.0;
t.Translation = new Vector();

If these don't get us the user experience that we want, we'll do these:

  • Mirror(Geometry, Line) - Reflects Geometry around the delivered line.
  • MoveBy(Geometry, Vector) - Returns Geometry displaced from the original Geometry.
  • MoveTo(Geomtry, FromPoint, ToPoint) - Convenience. Constructs the vector for MoveBy for the user. Otherwise like MoveBy.
  • Rotate(Geometry, Angle, Pivot) - Rotates the Geometry by the delivered radians around its (Center? Centroid? I used Centroid) by default or around a delivered (Vector3? Point Element?)
  • Scale(Geometry, Vector) - Scales the Geometry by the delivered vector factors from its (Center? Centroid? I used Centroid) by default or from a delivered (Vector3? Point Element?)

Provide commonly useful geometric properties, operations, and comparisons

Some of this I'll pull directly from the Shapely functionality set: https://toblerity.org/shapely/manual.html

Polygon Properties

  • Area (For closed shapes. Polygon? BBox?)

  • Bounding box for planar geometry (I realize the user can construct a BBox. If you want to leave this as is, I'm okay with it, but the libraries I've look at all seem to provide this information as a property of the geometric entity)

  • Center - Returns the center of the BBox. Not strictly necessary, occasionally convenient.

  • Centroid

  • Length (in Polygon land, this is equal to the linear circumference).

  • PointWithin - Returns a cheaply computed point that is guaranteed to be within the geometric object. We could relegate this somewhere else as a method that can be performed on a Polygon.

Geometric Comparisons

To keep this simple, I thought these comparisons could happen as if all 2D geometries shared a plane. If you think these should respect z-axis separation, so that Polygons that would return "True" to an overlap test would instead return "False" if they differ in z-axis comparison, just let me know. I'm okay either way, we would just want our implementation to be consistent in this regard.

This is isn't really a design, just a summary of desired functionality. (I realize things like "IsContaining" could just be called "Contains" but I was imagining a consistent convention for comparisons. I'm okay either way.)

Shapely thinks about Polygons as having 3 distinct concepts...

  • Interior
  • Boundary
  • Exterior

...and several of these defintions assume that distinction.

  • ConvexHull - Returns a Polygon representing the convex hull of a set of coplanar points (Vector3?)
  • Difference(Geometry1, Geometry2) Returns a list of Polygons representing the geometric difference between Geometry1 and Geometry2.
  • Distance(Geometry1, Geometry2) Returns the minimum distance between Geometry1 and Geometry2.
  • Intersection(Geometry1, Geometry2) Retruns a list of Polygons representing the geometric intersections between Geometry1 and Geometry2.
  • IsCountainedByGeometry1, Geometry2) - Returns True if Geometry1’s boundary and interior intersect only with the interior Geometry2 (not its boundary or exterior).
  • IsContaining(Geometry1, Geometry2) - Returns True if Geometry2’s boundary and interior intersect only with the interior Geometry1 (not its boundary or exterior).
  • IsCovering(Geometry1, Geometry2) - Returns True if the combination of Geometry1's boundary and interior are wholly coincident with the combination of Geometry2's boundary and interior.
  • IsDisjoint(Geometry1, Geometry2) - Returns True if Geometry1 and Geometry2 do not touch or intersect.
  • IsIntersecting(Geometry1, Geometry2) - Returns True if Geometry1 and Geometry2 boundaries or interiors intersect in any way.
  • IsOverlapping(Geometry1, Geometry2) - Returns True if IsCovering is False and IsIntersecting is True.
  • IsTouching(Geometry1, Geometry2) - Returns True if Geometry1 and Geometry2 have at least one point in common and their interiors do not intersect with any part of the other.
  • Midpoint(Vector3, Vector3) (I realize you can get this with PointAt(0.5) so this would be a mere convenience).
  • RemoveColinear(IEnummerable) Not sure if we need this. I implemented one to safely construct a Polygon with unique points. Not sure if you have that already through Clipper.
  • Union (Geometry1, Geometry2) Returns a Polygon representing the geometric union of Geometry1 and Geometry2.

Geometric Operations
Except in the first case, I don't know if you want to construct a new one or create a transform for the existing Geometry.

  • Copy(Geometry) - Returns a new identical Geometry.
  • Mirror(Geometry, Line) - Reflects Geometry around the delivered line.
  • MoveBy(Geometry, Vector) - Returns Geometry displaced from the original Geometry.
  • MoveTo(Geomtry, FromPoint, ToPoint) - Convenience. Constructs the vector for MoveBy for the user. Otherwise like MoveBy.
  • Rotate(Geometry, Angle, Pivot) - Rotates the Geometry by the delivered radians around its (Center? Centroid? I used Centroid) by default or around a delivered (Vector3? Point Element?)
  • Scale(Geometry, Vector) - Scales the Geometry by the delivered vector factors from its (Center? Centroid? I used Centroid) by default or from a delivered (Vector3? Point Element?)

Elements

  • Add a Point element that implements an IVector interface?

Loading model from serialized JSON results in too many materials which creates failures

Serializing and deserializing model from JSON text seems to have issues. I've created this test in using they hypar generator, but I believe the error lies in the Model.cs class and how it loads from JSON, so I've put the issue here. A mystery new 'black' material gets created on load, which causes errors when the materials are turned into a dictionary later. To do my tests I've had to remove this extra material from the materials after a model is loaded.

To recreate:

  1. Create brand new hypar generator using hypar new
    1a) do hypar init src and return a valid output from your test functions execute method.
    1b) I simply used return new Output(input.Model, 1.0);
  2. add the following line to the Test() function
    System.IO.File.WriteAllText("../../../model.json", output["elements"].ToString());
  3. run the test so that model.json gets written (should be in the same folder as FunctionTests.cs
  4. In the FunctionTest contructor add the following lines (console write just to succinctly write the 3 material GUIDs and names.)
            var modeljson = System.IO.File.ReadAllText("../../../model.json");
            var mdl = Model.FromJson(modeljson);
            Console.WriteLine(string.Join("\n", mdl.Materials.Select(m=>$"{m.Key}: {m.Value.Name}")));
            _data.Model = mdl; 
  1. if you debug and observe the mdl variable, you should see that it has 3 materials. there are two materials with familiar GUIDs from the model.json, but there is an additional material, new GUID, also called 'black'

This will cause the execution to fail at a later step, but it is this moment where there are 3 materials in a model loaded from a json with only 2 materials that I believe the error is introduced.

Serialization of empty model should throw meaningful exception.

A model with no elements should make a valid empty glb or no glb at all. In the latter case, an exception should be thrown that indicates clearly that there’s no elements in the model.

{
  "errorType": "ArgumentOutOfRangeException",
  "errorMessage": "Expected value to be greater than or equal to 1\nParameter name: ByteLength\nActual value was 0.",
  "stackTrace": [
    "at glTFLoader.Schema.Buffer.set_ByteLength(Int32 value)",
    "at Hypar.Elements.Model.InitializeGlTF()",
    "at Hypar.Elements.Model.SaveBase64()",
    "at Hypar.Elements.Model.ToHypar()",
    "at lambda_method(Closure , Stream , Stream , LambdaContextInternal )"
  ]
}

Solid.Split

Feature Proposal

As a developer, I should be able to split a Solid created with the elements library.

Proposed API:

Solid[] Split(Plane p)

Dotnet starter project should contain a test project.

Early adopters identified that the projects generated by hypar new don't have an obvious way to test the results. The starter projects referenced in #24 should include test projects that are bootstrapped to run the function with test data.

  • For .net a .sln file should reference both the function project and the test project. hypar publish should only publish the function project.
  • In Visual Studio code the user should be able to run the tests using a build configuration.
  • From the command line, .net users should be able to run the tests using dotnet test.
  • For python, the user should be able to run the tests using python -m unittest.
  • It is possible that a successful test run could be required prior to publishing the function to hypar, or that hypar can run those tests when we enable webooks.

@MarkThorley

Adjust grid to deal with Vector3 sets only.

Now that Polygon and Polyline are planar, we need to adjust sets of points returned from Grid to be of type IEnumerable<Vector3>.

The constructor should now be:

public Grid(IEnumerable<Vector3> corners, int uDivisions = 1, int vDivisions = 1){...}

A new user with temporary password can not log in successfully after changing password.

I've attempted the following to reproduce:

  • Create a new user, specifying the user name, email, and a temporary password. Unselected "Mark email as verified" to force the user creating a new password through the CLI.
  • hypar publish to get a login prompt.
    • Insert user name.
    • Insert temporary password. (I had to do this a couple of times because cut and paste of password was inserting some garbage characters from my scratch pad.)
    • Prompted to enter new password.
    • Entered new password.
    • Login completes.

Thinking that perhaps there was some AWS configuration stuff that was still being used by the login process, I removed my aws credentials file altogether, and retried the steps above with another test user. And it succeeded.
image

Verified that this fails the same way using the Linux and Windows CLIs.

The user shouldn't have to edit the hypar.json file.

Currently the user has to edit the hypar.json file to associate input parameters with their handler. Although having a json configuration file at the root of your project directory is now common practice for many frameworks (npm, dotnet, etc.), the association was unclear to our early adopters.

There are a few possible solutions:

  • Use reflection to generate the hypar.json automatically. This maintains compatibility with the current API but will only work for dotnet projects.
  • Replace inputs and returns with input and output class types. This would work for both dotnet and python, but the user would need to understand how to edit these files. We would also need to find a way to allow the user to define "attributes" like the description of a property. In C#, this would look something like:
public class FooInput
{
  [Description("The length of the thing.")]
  [Range(0, 10)]
  public double Length{get;set;}

  [Description("The height of the thing.")]
  [Range(0, 10)]
  public double Height{get;set;}

  [Description("The width of the thing.")]
  [Range(0, 10)]
  public double Width{get;set;}
}

Reflection to generate the hypar.json would happen during publish.

@MarkThorley

Consider deterministic ids for hypar elements

Re: https://github.com/hypar-io/sdk/blob/master/src/sdk/Elements/Element.cs#L61

I'm not sure if this has come up in the documentation, and so apologies if I missed a rationale somewhere -- and I haven't actually bumped into this as a problem yet, so this issue might be well suited to be closed wontfix-yagni.

Have you considered allowing elements to have deterministically generated ids? There are a number of workflows that could grow around hypar functions that depend on attaching information to elements, even though the extra data does not originate inside the hypar function itself.

For example, say I have a viewer that allows me to change the visibility of individual items, so that I can eg closely inspect the anchors for curtainwall panels. As I tweak and regenerate the model with randomly generated ids, either the viewer has to reset state with each iteration, or do a lot of work to guess which elements "match" between iterations. Some sort of determinism in id assignment could help with this and similar workflows.

Create Space Element

A Space is a volume created by extruding a set of co-planar polygons to a height, or by projecting a a set of co-planar polygons onto a plane. The first polygon provided in the set is understood to be the outer boundary of the space, with the ensuing polygons understood to be ordered in an CW direction representing "holes" in the space.

public Space(Polygon boundary, IEnumerable<Polygon> voids, double height){...}
public Space(Polygon boundary, IEnumerable<Polygon> voids, Plane plane){...}

Topography

// A topographic mesh derived from a field of Vector3.
public class Topography : IElement, IGeometry3D
{
  public Topography(Vector3[][] points){ ... }

  // Get all subsets of this topography where the slope angle is 
  public Topography[] AreasWithSlopeGreaterThan(double slope){ ... }
  public Topography[] AreasWithSlopeLessThan(double slope){ ... }
  public Topography[] AreasWithSlopeEqualTo(double slope){ ... }

  public void Tesselate(ref Mesh mesh){ ... }
}
  • Update IGeometry3D to accept an interface which supports brep and mesh.
  • Extending the existing mesh class as necessary to support per-facet calculation.

The hypar.json cannot be deserialized.

Unhandled Exception: Newtonsoft.Json.JsonSerializationException: Could not create an instance of type Hypar.Configuration.ParameterData. Type is an interface or abstract class and cannot be instantiated. Path 'parameters.height.min', line 9, position 18.
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateDictionary(IDictionary dictionary, JsonReader reader, JsonDictionaryContract contract, JsonProperty containerProperty, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
   at Hypar.Commands.NewCommand.UpdateHyparJson(String directory, String name) in /Users/ikeough/Documents/hypar/sdk/csharp/src/cli/Commands/NewCommand.cs:line 77
   at Hypar.Commands.NewCommand.New(String functionName) in /Users/ikeough/Documents/hypar/sdk/csharp/src/cli/Commands/NewCommand.cs:line 53
   at Hypar.Program.Main(String[] args) in /Users/ikeough/Documents/hypar/sdk/csharp/src/cli/Program.cs:line 65

Proposal for the introduction of mechanical Element types.

The Elements library should have types which represent mechanical systems and equipment according to @wynged.

  • What's the simplest way that we can define components in a directed mechanical system?
  • What's the simplest representation that we can provide of the connecting elements and the equipment within those systems?
  • How can we enable traversal of the system from terminal->supply and from supply->terminal?
// A component in a directed mechanical system.
public interface IConnection
{
 // The input port.
 Port In{get;}

 // The output ports.
 Port[] Out{get;}
}

// A mechanical Duct.
// The ICurveProvider interface requires an ICurve representing the center line of the Element.
// The IProfileProvider interface requires a Profile representing the cross-section shape of the element.
public class Duct : IElement, IConnection, ICurveProvider, IProfileProvider{...}

// An electrical conduit.
public class Conduit : IElement, IConnection, ICurveProvider, IProfileProvider{...}

// A piece of mechanical equipment which will be represented
// by a box with the given dimensions and have Ports
public interface IEquipment : IConnection
{
  double Width{get;}
  double Length{get;}
  double Height{get;}
}
public class VAV : IElement, IEquipment{...}
public class Fan : IElement, IEquipment{...}
public class Diffuser : IElement, IEquipment{...}
public class Fitting : IElement, IEquipment{...}

Add location support.

  • Generate types for serialization/deserialization of GeoJSON objects.
  • Implement deserialization of Feature array as provided by MapBox.
    • Create custom deserializer to handle Geometry types.
  • Convert GeoJSON polygons to Polyline, using the first position as the origin.

Json to Model deserializer has element type issue

If a new element is added to a hypar model and given a new type (ex. "VAV"), then converted into a JSON, an issue occurs when you attempt to deserialize it. This error occurs.

https://github.com/hypar-io/elements/blob/19e6a752543c3003924888f3ee7c22190925575c/src/Elements/Serialization/ElementConverter.cs#L81

It's likely coming from here, where its referencing the list of acceptable element types. "VAV" may not be in the acceptable list and therefore throws the error.

https://github.com/hypar-io/elements/blob/19e6a752543c3003924888f3ee7c22190925575c/src/Elements/Serialization/ElementConverter.cs#L27

@wynged has also been digging into it.

Add python 2.7 project.

Currently the CLI generates a dotnet C# project. The CLI should also give the option to create a python function. Because we want to share the Hypar SDK between the two, we are considering using the Hypar SDK via Iron Python. We must determine the following:

  • Iron Python can run in the context of a Lambda.
  • Iron Python can import the Hypar SDK.

This will need to use Iron Python 2.7.8.

Hypar CLI should be installed as a NuGet command line tool.

Installing the Hypar CLI as a NuGet command line tool will allow us to use NuGet for distribution. We can reference the Hypar CLI package in the starter repo and have the package synced to the solution. Then we can call dotnet hypar-cli.dll publish during dotnet publish to have the function pushed to Hypar automatically.

CLI does not properly clean names like test_Function_WoW.

Trying to create a function with the name test_Function_WoW results in an inability to create an S3 bucket. Most likely this is due to the limitation of S3 bucket names and _. The name should be cleaned to be test_function_wow.

Elements serialization now creates payloads too large for lambda.

Lambda has a fixed return size of 6mb of JSON. With geometry now being serialized to JSON, the JSON is too large to return uncompressed in many cases. It may be that compressing it will handle most cases, but the geometry is not necessary to be encoded in the JSON all the time. We can generate "one-way" JSON for the element data.

Replace `hypar new` with starter project repos.

The idea of creating a .net project, having to change directories into that project, then building the project, is a workflow that is foreign to some of our early adopters. For these early adopters, the whole project setup and build pipeline is currently handled by Visual Studio.

The CLI doesn't have to do as much work in hypar new. Currently, there is bootstrapping code in the new command which creates a project and a default class file. This can be replaced with a github repository that has everything a starter project needs. We didn't do this initially for fear that having github as a dependency would be a stumbling block. But it seems that some early adopters are more comfortable using github (most likely through the GUI) than they are using the command line.

The workflow would therefore look like this:

  • User does git clone https://github.com/hypar-io/dotnet-starter or git clone https://github.com/hypar-io/python-starter.
  • For a .net project, the user opens Visual Studio and opens the created .sln file. They can build and test from Visual Studio.

For dotnet, the starter project could also have the Hypar CLI as a build tool, so we wouldn't have to distribute the CLI using a zip.

@MarkThorley

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.