using System;
using System.Collections.Generic;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Types;
using Rhino.Geometry;
namespace WIP
{
///
/// BoatShell class, this class defines the basic properties and methods for any Boatshell.
///
public class BoatShell
{
#region fields
private double m_width;
private double m_length;
private Point3d m_mast;
private Brep m_shape;
private Curve m_waterLine;
#endregion
#region constructors
public BoatShell()
{
m_width = 0.0;
m_length = 0.0;
m_mast = Point3d.Unset;
}
public BoatShell(double width, double length, Brep shape, Point3d mast)
{
m_width = width;
m_length = length;
m_shape = shape;
m_mast = mast;
}
public BoatShell Duplicate()
{
BoatShell dup = new BoatShell(Width, Length, Shape, Mast);
if (m_waterLine != null)
dup.m_waterLine = m_waterLine.DuplicateCurve();
return dup;
}
#endregion
#region properties
public bool IsValid
{
get
{
if (Width <= 0.0) { return false; }
if (Length <= 0.0) { return false; }
if (m_shape == null) { return false; }
if (!Rhino.RhinoMath.IsValidDouble(Width)) { return false; }
if (!Rhino.RhinoMath.IsValidDouble(Length)) { return false; }
return true;
}
}
public double Width
{
get { return m_width; }
set { m_width = value; }
}
public double Length
{
get { return m_length; }
set { m_length = value; }
}
public Point3d Mast
{
get { return m_mast; }
set { m_mast = value; }
}
public Point3d Flag
{
get { return Mast + new Vector3d(0, 0, 10); }
}
public double Area
{
get { return Length * Width; }
}
public Brep Shape
{
get { return m_shape; }
set
{
m_shape = value;
m_waterLine = null;
}
}
public Curve WaterLine
{
get
{
if (m_waterLine != null) { return m_waterLine; }
if (m_shape == null) { return null; }
m_waterLine = ComputeWaterLine();
return m_waterLine;
}
}
#endregion
#region methods
public override string ToString()
{
return string.Format("W:{0:0.00}, L:{1:0.00}", Width, Length);
}
///
/// Compute the water line curve (elevation == 0.0)
///
/// A section plane curve through the hull.
private Curve ComputeWaterLine()
{
if (m_shape == null) { return null; }
Curve[] curves;
Point3d[] points;
if (!Rhino.Geometry.Intersect.Intersection.BrepPlane(m_shape, Plane.WorldXY, 0.01, out curves, out points))
{
return null;
}
if (curves == null) { return null; }
if (curves.Length == 0) { return null; }
if (curves.Length == 1) { return curves[0]; }
curves = Curve.JoinCurves(curves, 0.05);
if (curves == null) { return null; }
return curves[0];
}
#endregion
}
///
/// BoatShell Goo wrapper class, makes sure BoatShell can be used in Grasshopper.
///
public class BoatShellGoo : GH_GeometricGoo, IGH_PreviewData
{
#region constructors
public BoatShellGoo()
{
this.Value = new BoatShell();
}
public BoatShellGoo(BoatShell shell)
{
if (shell == null)
shell = new BoatShell();
this.Value = shell;
}
public override IGH_GeometricGoo DuplicateGeometry()
{
return DuplicateBoatShell();
}
public BoatShellGoo DuplicateBoatShell()
{
return new BoatShellGoo(Value == null ? new BoatShell() : Value.Duplicate());
}
#endregion
#region properties
public override bool IsValid
{
get
{
if (Value == null) { return false; }
return Value.IsValid;
}
}
public override string IsValidWhyNot
{
get
{
if (Value == null) { return "No internal BoatShell instance"; }
if (Value.IsValid) { return string.Empty; }
return "Invalid BoatShell instance"; //Todo: beef this up to be more informative.
}
}
public override string ToString()
{
if (Value == null)
return "Null BoatShell";
else
return Value.ToString();
}
public override string TypeName
{
get { return ("BoatShell"); }
}
public override string TypeDescription
{
get { return ("Defines a single boat shell shape"); }
}
public override BoundingBox Boundingbox
{
get
{
if (Value == null) { return BoundingBox.Empty; }
if (Value.Shape == null) { return BoundingBox.Empty; }
return Value.Shape.GetBoundingBox(true);
}
}
public override BoundingBox GetBoundingBox(Transform xform)
{
if (Value == null) { return BoundingBox.Empty; }
if (Value.Shape == null) { return BoundingBox.Empty; }
return Value.Shape.GetBoundingBox(xform);
}
#endregion
#region casting methods
public override bool CastTo(out Q target)
{
//Cast to BoatShell.
if (typeof(Q).IsAssignableFrom(typeof(BoatShell)))
{
if (Value == null)
target = default(Q);
else
target = (Q)(object)Value;
return true;
}
//Cast to Brep.
if (typeof(Q).IsAssignableFrom(typeof(Brep)))
{
if (Value == null)
target = default(Q);
else if (Value.Shape == null)
target = default(Q);
else
target = (Q)(object)Value.Shape.DuplicateShallow();
return true;
}
//Todo: cast to point, number, mesh, curve?
target = default(Q);
return false;
}
public override bool CastFrom(object source)
{
if (source == null) { return false; }
//Cast from BoatShell
if (typeof(BoatShell).IsAssignableFrom(source.GetType()))
{
Value = (BoatShell)source;
return true;
}
return false;
}
#endregion
#region transformation methods
public override IGH_GeometricGoo Transform(Transform xform)
{
//It's debatable whether you should maintain a BoatShell through transformations.
//It might not be easy/make sense to apply scaling/rotations, shears etc.
//In this example, I'll convert the shell to a brep.
//Perhaps you will want to check for translations/rotations only, operations that make sense.
if (Value == null) { return null; }
if (Value.Shape == null) { return null; }
Brep brep = Value.Shape.DuplicateBrep();
brep.Transform(xform);
return new GH_Brep(brep);
}
public override IGH_GeometricGoo Morph(SpaceMorph xmorph)
{
if (Value == null) { return null; }
if (Value.Shape == null) { return null; }
Brep brep = Value.Shape.DuplicateBrep();
xmorph.Morph(brep);
return new GH_Brep(brep);
}
#endregion
#region drawing methods
public BoundingBox ClippingBox
{
get { return Boundingbox; }
}
public void DrawViewportMeshes(GH_PreviewMeshArgs args)
{
//No meshes are drawn.
}
public void DrawViewportWires(GH_PreviewWireArgs args)
{
if (Value == null) { return; }
//Draw hull shape.
if (Value.Shape != null)
{
args.Pipeline.DrawBrepWires(Value.Shape, args.Color, -1);
}
//Draw waterline.
if (Value.WaterLine != null)
{
//You could also try and draw your waterline as dotted,
//but that would involve further caching.
args.Pipeline.DrawCurve(Value.WaterLine, System.Drawing.Color.SkyBlue, 4);
}
//Draw mast.
if (Value.Mast.IsValid)
{
Point3d p0 = Value.Mast;
Point3d p1 = Value.Flag;
args.Pipeline.DrawPoint(p0, Rhino.Display.PointStyle.ControlPoint, 4, args.Color);
args.Pipeline.DrawPoint(p1, Rhino.Display.PointStyle.ControlPoint, 2, args.Color);
args.Pipeline.DrawLine(p0, p1, args.Color);
}
}
#endregion
}
///
/// This class provides a Parameter interface for the Data_BoatShell type.
///
public class BoatShellParameter : GH_PersistentGeometryParam, IGH_PreviewObject
{
public BoatShellParameter()
: base(new GH_InstanceDescription("Boat Shell", "Shell", "Maintains a collection of Boat Shell data.", "WIP", "Boat"))
{
}
protected override System.Drawing.Bitmap Icon
{
get
{
return null; //Todo, provide an icon.
}
}
public override GH_Exposure Exposure
{
get
{
// If you want to provide this parameter on the toolbars, use something other than hidden.
return GH_Exposure.hidden;
}
}
public override Guid ComponentGuid
{
get { return new Guid("ee30da59-f7e4-45b1-8fac-45cf6a057bed"); }
}
//We do not allow users to pick boatshells,
//therefore the following 4 methods disable all this ui.
protected override GH_GetterResult Prompt_Plural(ref List values)
{
return GH_GetterResult.cancel;
}
protected override GH_GetterResult Prompt_Singular(ref BoatShellGoo value)
{
return GH_GetterResult.cancel;
}
protected override System.Windows.Forms.ToolStripMenuItem Menu_CustomSingleValueItem()
{
System.Windows.Forms.ToolStripMenuItem item = new System.Windows.Forms.ToolStripMenuItem();
item.Text = "Not available";
item.Visible = false;
return item;
}
protected override System.Windows.Forms.ToolStripMenuItem Menu_CustomMultiValueItem()
{
System.Windows.Forms.ToolStripMenuItem item = new System.Windows.Forms.ToolStripMenuItem();
item.Text = "Not available";
item.Visible = false;
return item;
}
#region preview methods
public BoundingBox ClippingBox
{
get
{
return Preview_ComputeClippingBox();
}
}
public void DrawViewportMeshes(IGH_PreviewArgs args)
{
//Meshes aren't drawn.
}
public void DrawViewportWires(IGH_PreviewArgs args)
{
//Use a standard method to draw gunk, you don't have to specifically implement this.
Preview_DrawWires(args);
}
private bool m_hidden = false;
public bool Hidden
{
get { return m_hidden; }
set { m_hidden = value; }
}
public bool IsPreviewCapable
{
get { return true; }
}
#endregion
}
public class BoatShellComponent : GH_Component
{
public BoatShellComponent()
: base("Boat Shell", "Shell", "Create a new Boat shell", "WIP", "Boat") { }
protected override System.Drawing.Bitmap Icon
{
get
{
return null; //Todo: create an icon.
}
}
public override GH_Exposure Exposure
{
get
{
return GH_Exposure.primary;
}
}
public override Guid ComponentGuid
{
get { return new Guid("243d7d74-3890-4a41-b87f-04f143a1576a"); }
}
protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
{
pManager.Register_DoubleParam("Width", "W", "Boat shell width.");
pManager.Register_DoubleParam("Length", "L", "Boat shell length.");
pManager.Register_BRepParam("Shape", "S", "Boat shell shape.");
pManager.Register_PointParam("Mast", "M", "Boat mast location.");
pManager.HideParameter(2);
pManager.HideParameter(3);
}
protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
{
pManager.RegisterParam(new BoatShellParameter(), "Shell", "S", "Boat shell");
}
protected override void SolveInstance(IGH_DataAccess DA)
{
double width = 0.0;
double length = 0.0;
Brep shape = null;
Point3d mast = Point3d.Unset;
if (!DA.GetData(0, ref width)) { return; }
if (!DA.GetData(1, ref length)) { return; }
if (!DA.GetData(2, ref shape)) { return; }
if (!DA.GetData(3, ref mast)) { return; }
BoatShell BS = new BoatShell(width, length, shape, mast);
DA.SetData(0, BS);
}
}
public class HarbourComponent : GH_Component
{
public HarbourComponent()
: base("Harbour", "Harbour", "Harbour", "WIP", "Boat")
{
}
protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
{
pManager.RegisterParam(new BoatShellParameter(), "Boat A", "A", "First boat shell");
pManager.RegisterParam(new BoatShellParameter(), "Boat B", "B", "Second boat shell");
}
protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
{
pManager.Register_StringParam("TotalArea", "A", "Boat shell total area");
pManager.Register_BRepParam("Flags", "F", "Boat shell flags location");
}
protected override void SolveInstance(IGH_DataAccess DA)
{
BoatShell A = null;
BoatShell B = null;
if (!DA.GetData(0, ref A)) { return; }
if (!DA.GetData(1, ref B)) { return; }
double area = A.Area + B.Area;
Point3d[] flags = new Point3d[2] { A.Flag, B.Flag };
DA.SetData("TotalArea", area);
DA.SetDataList("Flags", flags);
}
protected override System.Drawing.Bitmap Icon
{
get
{
return base.Icon; //Todo: create icon.
}
}
public override GH_Exposure Exposure
{
get
{
return GH_Exposure.primary;
}
}
public override Guid ComponentGuid
{
get { return new Guid("243d7d74-3890-4a41-b87f-04f143a1577b"); }
}
}
}