Hello everyone,
I am trying to construct a brilliant cut with c# in grasshopper with all the important attributes given from diamond reports.
the kite facettes seem to be a problem though:
here a plan how I planned to get the kite facets (turquise polyline) planar:
the red lines are given (r of rc and all offsets in z and y direction.)
22.5° are given by the 1/16 division by the brilliant cut, and therefor 67.5° the relevant angle.
then the blue circle, resp. its radius is calculated by radius= fc.radius/math.sin(67.5°).
This seems not very complicated to me, but in the result the facet is never drawn, as its not REALLY planar and therefor returns null:
Now am I missing some basic math skills or is it the good old rounding problem of double values having x.000000000000000344 fragments on it? How would I get around this?
brilliantCut_0.gh (11.5 KB)
and here the relevant pieces of code:
//settings defs
int div = 16;
double alpha = 360 / div;
double beta = 90 - alpha;
double cfRatio = 0.5;
//input checks
if(Pl == null) Pl = new Plane(Plane.WorldXY);
if(crownRatio == 0.0) crownRatio = 0.180;
if(girdleRatio == 0.0)girdleRatio = 0.022;
if(pavillionRatio == 0.0)pavillionRatio = 0.380;
if(tableRatio == 0.0)tableRatio = 0.600;
//geo defs
Vector3d plNorm = Pl.ZAxis;
plNorm.Unitize();
//diameter to use
BoundingBox bbox = C.GetBoundingBox(true);
Point3d[] corners = bbox.GetCorners();
//double avgDiam = Math.Round((corners[0].DistanceTo(corners[1]) + corners[0].DistanceTo(corners[3])) / 2, 2);
double avgDiam = C.GetLength() / Math.PI;
//
//curve.table
var tcX = Transform.Translation(plNorm * avgDiam * (girdleRatio + crownRatio));
Curve tC = offsetInside(C, Pl, avgDiam / 2 * (1 - tableRatio));
tC.Transform(tcX);
//
//curve.crownfacette
double midRadius = ((avgDiam * (1 - tableRatio) / 4) + (avgDiam / 2 * tableRatio));
double cfRadius = midRadius / Math.Sin(RhinoMath.ToRadians(beta));
var cfcX = Transform.Translation(plNorm * avgDiam * (girdleRatio + (crownRatio * cfRatio)));
Curve cfC = offsetInside(C, Pl, avgDiam / 2 - cfRadius);
cfC.Transform(cfcX);
//
//curve.rondist
var rcX = Transform.Translation(plNorm * avgDiam * girdleRatio);
Curve rC = C.DuplicateCurve();
rC.Transform(rcX);
//
//points.oncurves
//points.table
List<Point3d> tcP = new List<Point3d>(filterList(divideCurve(tC, div), true));
//points.crownfacette
List<Point3d> cfcP = new List<Point3d>(filterList(divideCurve(cfC, div), false));
//points.rondiste
List<Point3d> rcP = new List<Point3d>(divideCurve(rC, div));
//breps
List<Brep> breps = new List<Brep>();
//breps.kitefacette
for(int i = 0; i < cfcP.Count - 1;i++)
{
List<Point3d> kite = new List<Point3d>();
kite.Add(cfcP[i]);
kite.Add(tcP[i + 1]);
kite.Add(cfcP[i + 1]);
kite.Add(rcP[i * 2 + 2]);
kite.Add(kite[0]);
Curve plln = new Polyline(kite).ToNurbsCurve();
bool tst = plln.IsPlanar();
Rhino.RhinoApp.WriteLine(tst.ToString());
Brep[] tmpbrep = Brep.CreatePlanarBreps(new Polyline(kite).ToNurbsCurve(), 0.001);
if(tmpbrep != null) breps.AddRange(tmpbrep);
}
G = breps;
}
// <Custom additional code>
public List<Point3d> divideCurve(Curve C, int n)
{
List<Point3d> lOut = new List<Point3d>();
double[] divT = C.DivideByCount(16, true);
List<double> tL = new List<double>(divT);
foreach(double t in tL)
{
lOut.Add(C.PointAt(t));
}
lOut.Add(lOut[0]);
return lOut;
}
public List<Point3d> filterList(List<Point3d> input, bool pair)
{
List<Point3d> lOut = new List<Point3d>();
int start = pair ? 0 : 1;
for(int i = start;i < input.Count;i = i + 2)
{
lOut.Add(input[i]);
}
return lOut;
}
public Curve offsetInside(Curve C, Plane Pl, double dist)
{
Curve[] c0 = C.Offset(Pl, dist, 0.001, CurveOffsetCornerStyle.Round);
Curve[] c1 = C.Offset(Pl, -dist, 0.001, CurveOffsetCornerStyle.Round);
Curve oC = c0[0].GetLength() < c1[0].GetLength() && c0[0].IsClosed ? c0[0] : c1[0];
return oC;
}
thank you in advance
Ben
EDIT: the constructed length (which works) is 4.330 for the blue radius, while the calculated is at 4.3295688.