public static SpeckleObject fromBrep(Brep o, bool getEncoded, bool getAbstract)
        {
            var encodedObj = "RH:" + SpeckleConverter.getBase64(o);
            var ms         = getMeshFromBrep(o);

            Rhino.Geometry.VolumeMassProperties volumeProps = Rhino.Geometry.VolumeMassProperties.Compute(o);
            Rhino.Geometry.AreaMassProperties   areaProps   = Rhino.Geometry.AreaMassProperties.Compute(o);

            SpeckleObject obj = new SpeckleObject();

            obj.value      = new ExpandoObject();
            obj.properties = new ExpandoObject();

            obj.type                      = "Brep";
            obj.hash                      = "Brep." + SpeckleConverter.getHash(encodedObj);
            obj.encodedValue              = getEncoded ? encodedObj : "";
            obj.value.vertices            = ms.Vertices;
            obj.value.faces               = ms.Faces;
            obj.value.colors              = ms.VertexColors;
            obj.properties.volume         = volumeProps.Volume;
            obj.properties.area           = areaProps.Area;
            obj.properties.volumeCentroid = fromPoint(volumeProps.Centroid);
            obj.properties.areaCentroid   = fromPoint(areaProps.Centroid);

            return(obj);
        }
        public static SpeckleObject fromMesh(Mesh o)
        {
            var encodedObj = "RH:" + SpeckleConverter.getBase64(o);

            Rhino.Geometry.VolumeMassProperties volumeProps = Rhino.Geometry.VolumeMassProperties.Compute(o);
            Rhino.Geometry.AreaMassProperties   areaProps   = Rhino.Geometry.AreaMassProperties.Compute(o);

            SpeckleObject obj = new SpeckleObject();

            obj.value      = new ExpandoObject();
            obj.properties = new ExpandoObject();


            obj.type = "Mesh";
            obj.hash = "Mesh." + SpeckleConverter.getHash(encodedObj);

            obj.value.vertices = o.Vertices.Select(pt => fromPoint(pt));
            obj.value.faces    = o.Faces;
            obj.value.colors   = o.VertexColors.Select(c => c.ToArgb());
            //o.UserData
            obj.properties.volume         = volumeProps.Volume;
            obj.properties.area           = areaProps.Area;
            obj.properties.volumeCentroid = fromPoint(volumeProps.Centroid);
            obj.properties.areaCentroid   = fromPoint(areaProps.Centroid);

            return(obj);
        }
        public static SpeckleObject fromPlane(Plane p)
        {
            SpeckleObject obj = new SpeckleObject();

            obj.value = new ExpandoObject();

            obj.type         = "Plane";
            obj.hash         = "Plane." + SpeckleConverter.getHash("RH:" + SpeckleConverter.getBase64(p));
            obj.value.origin = fromPoint(p.Origin);
            obj.value.xdir   = fromVector(p.XAxis);
            obj.value.ydir   = fromVector(p.YAxis);
            obj.value.normal = fromVector(p.Normal);

            return(obj);
        }
        public static SpeckleObject fromCircle(Circle circle)
        {
            SpeckleObject obj = new SpeckleObject();

            obj.value      = new ExpandoObject();
            obj.properties = new ExpandoObject();

            obj.type = "Circle";
            obj.hash = "Circle." + SpeckleConverter.getHash("RH:" + SpeckleConverter.getBase64(circle));

            obj.value.plane  = fromPlane(circle.Plane);
            obj.value.center = fromPoint(circle.Center);
            obj.value.normal = fromVector(circle.Plane.Normal);
            obj.value.radius = circle.Radius;

            obj.properties.length = circle.Circumference;

            return(obj);
        }
        public static SpeckleObject fromBox(Box box)
        {
            SpeckleObject obj = new SpeckleObject();

            obj.value      = new ExpandoObject();
            obj.properties = new ExpandoObject();

            obj.type              = "Box";
            obj.hash              = "Box." + SpeckleConverter.getHash("RH:" + SpeckleConverter.getBase64(box));
            obj.value.center      = fromPoint(box.Center);
            obj.value.normal      = fromVector(box.Plane.Normal); // use fromVector
            obj.value.plane       = fromPlane(box.Plane);         // to use fromPlane
            obj.value.X           = fromInterval(box.X);
            obj.value.Y           = fromInterval(box.Y);
            obj.value.Z           = fromInterval(box.Z);
            obj.properties.area   = box.Area;
            obj.properties.volume = box.Volume;

            return(obj);
        }
        public static SpeckleObject fromRectangle(Rectangle3d rect)
        {
            SpeckleObject obj = new SpeckleObject();

            obj.value      = new ExpandoObject();
            obj.properties = new ExpandoObject();

            obj.type        = "Rectangle";
            obj.hash        = "Rectangle." + SpeckleConverter.getHash("RH:" + SpeckleConverter.getBase64(rect));
            obj.value.A     = fromPoint(rect.Corner(0));
            obj.value.B     = fromPoint(rect.Corner(1));
            obj.value.C     = fromPoint(rect.Corner(2));
            obj.value.D     = fromPoint(rect.Corner(3));
            obj.value.plane = fromPlane(rect.Plane);

            obj.properties.length = rect.Circumference;
            obj.properties.area   = rect.Area;

            return(obj);
        }
        public static SpeckleObject fromArc(Arc arc)
        {
            SpeckleObject obj = new SpeckleObject();

            obj.value      = new ExpandoObject();
            obj.properties = new ExpandoObject();

            obj.type              = "Arc";
            obj.hash              = "Arc." + SpeckleConverter.getHash("RH:" + SpeckleConverter.getBase64(arc));
            obj.value.center      = fromPoint(arc.Center);
            obj.value.plane       = fromPlane(arc.Plane);
            obj.value.startAngle  = arc.StartAngle;
            obj.value.endAngle    = arc.EndAngle;
            obj.value.startPoint  = fromPoint(arc.StartPoint);
            obj.value.midPoint    = fromPoint(arc.MidPoint);
            obj.value.endPoint    = fromPoint(arc.EndPoint);
            obj.properties.length = arc.Length;

            return(obj);
        }
        public static SpeckleObject fromPolyline(Polyline poly)
        {
            var encodedObj = "RH:" + SpeckleConverter.getBase64(poly.ToNurbsCurve());

            Rhino.Geometry.AreaMassProperties areaProps = Rhino.Geometry.AreaMassProperties.Compute(poly.ToNurbsCurve());

            SpeckleObject obj = new SpeckleObject();

            obj.value      = new ExpandoObject();
            obj.properties = new ExpandoObject();

            obj.type = "Polyline";
            obj.hash = "Polyline." + SpeckleConverter.getHash(encodedObj);

            obj.value                   = poly.Select(pt => fromPoint(pt));
            obj.properties.length       = poly.Length;
            obj.properties.area         = areaProps != null ? areaProps.Area : 0;
            obj.properties.areaCentroid = areaProps != null?fromPoint(areaProps.Centroid) : null;

            return(obj);
        }
        public static SpeckleObject fromCurve(Curve o, bool getEncoded, bool getAbstract)
        {
            var encodedObj = "RH:" + SpeckleConverter.getBase64(o);

            Rhino.Geometry.AreaMassProperties areaProps = Rhino.Geometry.AreaMassProperties.Compute(o);
            var      polyCurve = o.ToPolyline(0, 1, 0, 0, 0, 0.1, 0, 0, true);
            Polyline poly; polyCurve.TryGetPolyline(out poly);

            SpeckleObject obj = new SpeckleObject();

            obj.value      = new ExpandoObject();
            obj.properties = new ExpandoObject();

            obj.type                    = "Curve";
            obj.hash                    = "Curve." + SpeckleConverter.getHash(encodedObj);
            obj.value                   = fromPolyline(poly);
            obj.encodedValue            = getEncoded ? encodedObj : "";
            obj.properties.length       = o.GetLength();
            obj.properties.area         = areaProps != null ? areaProps.Area : 0;
            obj.properties.areaCentroid = areaProps != null?fromPoint(areaProps.Centroid) : null;

            return(obj);
        }
        /// <summary>
        /// Determines object type and calls the appropriate conversion call.
        /// </summary>
        /// <param name="o">Object to convert.</param>
        /// <param name="getEncoded">If set to true, will return a base64 encoded value of more complex objects (ie, breps).</param>
        /// <returns></returns>
        private static SpeckleObject fromGhRhObject(object o, bool getEncoded = false, bool getAbstract = true)
        {
            GH_Interval int1d = o as GH_Interval;

            if (int1d != null)
            {
                return(GhRhConveter.fromInterval(int1d.Value));
            }
            if (o is Interval)
            {
                return(GhRhConveter.fromInterval((Interval)o));
            }

            GH_Interval2D int2d = o as GH_Interval2D;

            if (int2d != null)
            {
                return(GhRhConveter.fromInterval2d(int2d.Value));
            }
            if (o is UVInterval)
            {
                return(GhRhConveter.fromInterval2d((UVInterval)o));
            }

            // basic stuff
            GH_Number num = o as GH_Number;

            if (num != null)
            {
                return(SpeckleConverter.fromNumber(num.Value));
            }
            if (o is double || o is int)
            {
                return(SpeckleConverter.fromNumber((double)o));
            }

            GH_Boolean bul = o as GH_Boolean;

            if (bul != null)
            {
                return(SpeckleConverter.fromBoolean(bul.Value));
            }
            if (o is Boolean)
            {
                return(GhRhConveter.fromBoolean((bool)o));
            }

            GH_String str = o as GH_String;

            if (str != null)
            {
                return(SpeckleConverter.fromString(str.Value));
            }
            if (o is string)
            {
                return(SpeckleConverter.fromString((string)o));
            }

            // simple geometry
            GH_Point point = o as GH_Point;

            if (point != null)
            {
                return(GhRhConveter.fromPoint(point.Value));
            }
            if (o is Point3d)
            {
                return(GhRhConveter.fromPoint((Point3d)o));
            }
            // added because when we assign user data to points they get converted to points.
            // the above comment does makes sense. check the sdk.
            if (o is Rhino.Geometry.Point)
            {
                return(GhRhConveter.fromPoint(((Rhino.Geometry.Point)o).Location));
            }

            GH_Vector vector = o as GH_Vector;

            if (vector != null)
            {
                return(GhRhConveter.fromVector(vector.Value));
            }
            if (o is Vector3d)
            {
                return(GhRhConveter.fromVector((Vector3d)o));
            }

            GH_Plane plane = o as GH_Plane;

            if (plane != null)
            {
                return(GhRhConveter.fromPlane(plane.Value));
            }
            if (o is Plane)
            {
                return(GhRhConveter.fromPlane((Plane)o));
            }

            GH_Line line = o as GH_Line;

            if (line != null)
            {
                return(GhRhConveter.fromLine(line.Value));
            }
            if (o is Line)
            {
                return(GhRhConveter.fromLine((Line)o));
            }

            GH_Arc arc = o as GH_Arc;

            if (arc != null)
            {
                return(GhRhConveter.fromArc(arc.Value));
            }
            if (o is Arc)
            {
                return(GhRhConveter.fromArc((Arc)o));
            }

            GH_Circle circle = o as GH_Circle;

            if (circle != null)
            {
                return(GhRhConveter.fromCircle(circle.Value));
            }
            if (o is Circle)
            {
                return(GhRhConveter.fromCircle((Circle)o));
            }

            GH_Rectangle rectangle = o as GH_Rectangle;

            if (rectangle != null)
            {
                return(GhRhConveter.fromRectangle(rectangle.Value));
            }
            if (o is Rectangle3d)
            {
                return(GhRhConveter.fromRectangle((Rectangle3d)o));
            }

            GH_Box box = o as GH_Box;

            if (box != null)
            {
                return(GhRhConveter.fromBox(box.Value));
            }
            if (o is Box)
            {
                return(GhRhConveter.fromBox((Box)o));
            }

            // getting complex
            GH_Curve curve = o as GH_Curve;

            if (curve != null)
            {
                Polyline poly;
                if (curve.Value.TryGetPolyline(out poly))
                {
                    return(GhRhConveter.fromPolyline(poly));
                }
                return(GhRhConveter.fromCurve(curve.Value, getEncoded, getAbstract));
            }

            if (o is Polyline)
            {
                return(GhRhConveter.fromPolyline((Polyline)o));
            }
            if (o is Curve)
            {
                return(GhRhConveter.fromCurve((Curve)o, getEncoded, getAbstract));
            }

            GH_Surface surface = o as GH_Surface;

            if (surface != null)
            {
                return(GhRhConveter.fromBrep(surface.Value, getEncoded, getAbstract));
            }

            GH_Brep brep = o as GH_Brep;

            if (brep != null)
            {
                return(GhRhConveter.fromBrep(brep.Value, getEncoded, getAbstract));
            }

            if (o is Brep)
            {
                return(GhRhConveter.fromBrep((Brep)o, getEncoded, getAbstract));
            }

            GH_Mesh mesh = o as GH_Mesh;

            if (mesh != null)
            {
                return(GhRhConveter.fromMesh(mesh.Value));
            }
            if (o is Mesh)
            {
                return(GhRhConveter.fromMesh((Mesh)o));
            }

            return(new SpeckleObject()
            {
                hash = "404", value = "Type not supported", type = "404"
            });
        }