Problem
Writing curves to a file has some special considerations. Curves come in many variations: the curve could be a circle, simple curve, or a polycurve. You cannot know in advance what the user will be selecting. As such, the class containing my data declares it as an ON_Curve
.
Writing the data is not an issue. You simply call ON_Curve::Write
. However, things don’t go so well when you try to read the data. You need a way to simply read curve data without going to a non-abstract class. What is needed is a way to read/write curve data that represents any kind of curve possible.
Solution
It is probably best not to call ON_Curve::Write
for this very reason. When serializing anything derived from ON_Object
, just use ON_BinaryArchive::WriteObject
and ON_BinaryArchive::ReadObject
…
Write
static bool WriteCurveFile(FILE* fp, const ON_Curve* curve) { if (nullptr == fp || nullptr == curve) return false; ON_BinaryFile archive(ON::archive_mode::write3dm, fp); int major_version = 1; int minor_version = 0; bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK, major_version, minor_version); if (!rc) return false; for (;;) { // version 1.0 fields rc = (archive.WriteObject(curve) ? true : false); if (!rc) break; // todo... break; } if (!archive.EndWrite3dmChunk()) rc = false; return rc; }
Read
static bool ReadCurveFile(FILE* fp, ON_Curve*& curve) { if (nullptr == fp) return false; ON_BinaryFile archive(ON::archive_mode::read3dm, fp); int major_version = 0; int minor_version = 0; bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK, &major_version, &minor_version); if (!rc) return false; for (;;) { rc = (1 == major_version); if (!rc) break; // version 1.0 fields ON_Object* object = 0; rc = (archive.ReadObject(&object) ? true : false); if (!rc) break; curve = ON_Curve::Cast(object); // todo... break; } if (!archive.EndRead3dmChunk()) rc = false; return (rc && curve); }
Sample
To use the above functions, you could do the following:
bool rc = false; FILE* fp = ON::OpenFile(filename, L"wb"); if (fp) { rc = WriteCurveFile(fp, curve); ON::CloseFile(fp); } if (rc) RhinoApp().Print(L"Successfully wrote %s.\n", filename); else RhinoApp().Print(L"Errors while writing %s.\n", filename);
and
bool rc = false; ON_Curve* curve = nullptr; FILE* fp = ON::OpenFile(filename, L"rb"); if (fp) { rc = ReadCurveFile(fp, curve); ON::CloseFile(fp); } if (rc) { CRhinoCurveObject* curve_object = new CRhinoCurveObject(); curve_object->SetCurve(curve); context.m_doc.AddObject(curve_object); context.m_doc.Redraw(); } else { RhinoApp().Print(L"Errors while reading %s.\n", filename); }