From 7dcde5ec3c61d9caf67edc1014af799701a12a8b Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 17 Oct 2023 10:43:08 +0200 Subject: [PATCH 1/3] Extern : - aggiunta della libreria openNURBS. --- opennurbs/Include/dwrite_1_x32.h | 1926 ++ opennurbs/Include/dwrite_2_x32.h | 976 + opennurbs/Include/dwrite_x32.h | 5141 +++++ opennurbs/Include/opennurbs.h | 180 + opennurbs/Include/opennurbs_3dm.h | 532 + opennurbs/Include/opennurbs_3dm_attributes.h | 590 + opennurbs/Include/opennurbs_3dm_properties.h | 186 + opennurbs/Include/opennurbs_3dm_settings.h | 1737 ++ opennurbs/Include/opennurbs_annotationbase.h | 1181 + opennurbs/Include/opennurbs_apple_nsfont.h | 45 + opennurbs/Include/opennurbs_arc.h | 602 + opennurbs/Include/opennurbs_arccurve.h | 387 + opennurbs/Include/opennurbs_archive.h | 5814 +++++ opennurbs/Include/opennurbs_array.h | 1794 ++ opennurbs/Include/opennurbs_array_defs.h | 2186 ++ opennurbs/Include/opennurbs_atomic_op.h | 22 + opennurbs/Include/opennurbs_base32.h | 126 + opennurbs/Include/opennurbs_base64.h | 345 + opennurbs/Include/opennurbs_beam.h | 1000 + opennurbs/Include/opennurbs_bezier.h | 1973 ++ opennurbs/Include/opennurbs_bitmap.h | 524 + opennurbs/Include/opennurbs_bounding_box.h | 914 + opennurbs/Include/opennurbs_box.h | 120 + opennurbs/Include/opennurbs_brep.h | 4811 ++++ opennurbs/Include/opennurbs_circle.h | 325 + opennurbs/Include/opennurbs_color.h | 448 + opennurbs/Include/opennurbs_compress.h | 493 + opennurbs/Include/opennurbs_compstat.h | 884 + opennurbs/Include/opennurbs_cone.h | 190 + opennurbs/Include/opennurbs_convex_poly.h | 427 + opennurbs/Include/opennurbs_cpp_base.h | 108 + opennurbs/Include/opennurbs_crc.h | 152 + opennurbs/Include/opennurbs_curve.h | 1474 ++ opennurbs/Include/opennurbs_curveonsurface.h | 201 + opennurbs/Include/opennurbs_curveproxy.h | 467 + opennurbs/Include/opennurbs_cylinder.h | 152 + opennurbs/Include/opennurbs_date.h | 108 + opennurbs/Include/opennurbs_defines.h | 2949 +++ opennurbs/Include/opennurbs_detail.h | 95 + opennurbs/Include/opennurbs_dimension.h | 1161 + opennurbs/Include/opennurbs_dimensionformat.h | 87 + opennurbs/Include/opennurbs_dimensionstyle.h | 2580 +++ opennurbs/Include/opennurbs_dll_resource.h | 14 + opennurbs/Include/opennurbs_ellipse.h | 135 + opennurbs/Include/opennurbs_error.h | 272 + opennurbs/Include/opennurbs_evaluate_nurbs.h | 461 + opennurbs/Include/opennurbs_extensions.h | 2104 ++ opennurbs/Include/opennurbs_file_utilities.h | 1794 ++ opennurbs/Include/opennurbs_font.h | 6674 ++++++ opennurbs/Include/opennurbs_fpoint.h | 1161 + opennurbs/Include/opennurbs_freetype.h | 122 + .../Include/opennurbs_freetype_include.h | 293 + opennurbs/Include/opennurbs_fsp.h | 920 + opennurbs/Include/opennurbs_fsp_defs.h | 148 + opennurbs/Include/opennurbs_function_list.h | 132 + opennurbs/Include/opennurbs_geometry.h | 398 + opennurbs/Include/opennurbs_gl.h | 246 + opennurbs/Include/opennurbs_group.h | 83 + opennurbs/Include/opennurbs_hash_table.h | 199 + opennurbs/Include/opennurbs_hatch.h | 975 + opennurbs/Include/opennurbs_hsort_template.h | 106 + opennurbs/Include/opennurbs_input_libsdir.h | 43 + opennurbs/Include/opennurbs_instance.h | 790 + .../opennurbs_internal_V2_annotation.h | 377 + .../opennurbs_internal_V5_annotation.h | 2117 ++ .../Include/opennurbs_internal_V5_dimstyle.h | 731 + .../Include/opennurbs_internal_defines.h | 165 + opennurbs/Include/opennurbs_internal_glyph.h | 261 + .../Include/opennurbs_internal_unicode_cp.h | 151 + opennurbs/Include/opennurbs_intersect.h | 271 + opennurbs/Include/opennurbs_ipoint.h | 433 + opennurbs/Include/opennurbs_knot.h | 492 + opennurbs/Include/opennurbs_layer.h | 772 + opennurbs/Include/opennurbs_leader.h | 196 + opennurbs/Include/opennurbs_light.h | 287 + opennurbs/Include/opennurbs_line.h | 606 + opennurbs/Include/opennurbs_linecurve.h | 385 + opennurbs/Include/opennurbs_linestyle.h | 139 + opennurbs/Include/opennurbs_linetype.h | 219 + opennurbs/Include/opennurbs_locale.h | 713 + opennurbs/Include/opennurbs_lock.h | 123 + opennurbs/Include/opennurbs_lookup.h | 461 + opennurbs/Include/opennurbs_mapchan.h | 224 + opennurbs/Include/opennurbs_material.h | 796 + opennurbs/Include/opennurbs_math.h | 2406 ++ opennurbs/Include/opennurbs_matrix.h | 614 + opennurbs/Include/opennurbs_md5.h | 320 + opennurbs/Include/opennurbs_memory.h | 101 + opennurbs/Include/opennurbs_mesh.h | 6288 ++++++ opennurbs/Include/opennurbs_model_component.h | 1908 ++ opennurbs/Include/opennurbs_model_geometry.h | 250 + opennurbs/Include/opennurbs_nurbscurve.h | 1346 ++ opennurbs/Include/opennurbs_nurbssurface.h | 2162 ++ opennurbs/Include/opennurbs_object.h | 1193 + opennurbs/Include/opennurbs_object_history.h | 359 + opennurbs/Include/opennurbs_objref.h | 328 + opennurbs/Include/opennurbs_offsetsurface.h | 365 + opennurbs/Include/opennurbs_optimize.h | 101 + opennurbs/Include/opennurbs_parse.h | 2648 +++ opennurbs/Include/opennurbs_photogrammetry.h | 406 + opennurbs/Include/opennurbs_plane.h | 621 + opennurbs/Include/opennurbs_planesurface.h | 566 + opennurbs/Include/opennurbs_pluginlist.h | 66 + opennurbs/Include/opennurbs_point.h | 3699 ++++ opennurbs/Include/opennurbs_pointcloud.h | 276 + opennurbs/Include/opennurbs_pointgeometry.h | 92 + opennurbs/Include/opennurbs_pointgrid.h | 153 + opennurbs/Include/opennurbs_polycurve.h | 812 + opennurbs/Include/opennurbs_polyedgecurve.h | 311 + opennurbs/Include/opennurbs_polyline.h | 273 + opennurbs/Include/opennurbs_polylinecurve.h | 541 + opennurbs/Include/opennurbs_private_wrap.h | 1 + .../Include/opennurbs_private_wrap_defs.h | 93 + .../Include/opennurbs_progress_reporter.h | 292 + opennurbs/Include/opennurbs_public.h | 83 + opennurbs/Include/opennurbs_public_examples.h | 54 + opennurbs/Include/opennurbs_public_version.h | 82 + opennurbs/Include/opennurbs_qsort_template.h | 322 + .../Include/opennurbs_quacksort_template.h | 333 + opennurbs/Include/opennurbs_quaternion.h | 356 + opennurbs/Include/opennurbs_rand.h | 197 + opennurbs/Include/opennurbs_rendering.h | 218 + opennurbs/Include/opennurbs_revsurface.h | 527 + opennurbs/Include/opennurbs_rtree.h | 863 + opennurbs/Include/opennurbs_sha1.h | 658 + opennurbs/Include/opennurbs_sleeplock.h | 239 + opennurbs/Include/opennurbs_sphere.h | 129 + opennurbs/Include/opennurbs_std_string.h | 1318 ++ opennurbs/Include/opennurbs_string.h | 5411 +++++ opennurbs/Include/opennurbs_string_value.h | 725 + opennurbs/Include/opennurbs_subd.h | 18164 ++++++++++++++++ opennurbs/Include/opennurbs_subd_data.h | 3060 +++ opennurbs/Include/opennurbs_sumsurface.h | 500 + opennurbs/Include/opennurbs_surface.h | 940 + opennurbs/Include/opennurbs_surfaceproxy.h | 359 + opennurbs/Include/opennurbs_symmetry.h | 1046 + opennurbs/Include/opennurbs_system.h | 755 + opennurbs/Include/opennurbs_system_compiler.h | 496 + opennurbs/Include/opennurbs_system_runtime.h | 213 + opennurbs/Include/opennurbs_terminator.h | 180 + opennurbs/Include/opennurbs_testclass.h | 168 + opennurbs/Include/opennurbs_text.h | 628 + opennurbs/Include/opennurbs_text_style.h | 181 + opennurbs/Include/opennurbs_textcontext.h | 45 + opennurbs/Include/opennurbs_textdraw.h | 56 + opennurbs/Include/opennurbs_textglyph.h | 19 + opennurbs/Include/opennurbs_textiterator.h | 935 + opennurbs/Include/opennurbs_textlog.h | 571 + opennurbs/Include/opennurbs_textobject.h | 163 + opennurbs/Include/opennurbs_textrun.h | 442 + opennurbs/Include/opennurbs_texture.h | 504 + opennurbs/Include/opennurbs_texture_mapping.h | 735 + opennurbs/Include/opennurbs_topology.h | 280 + opennurbs/Include/opennurbs_torus.h | 194 + opennurbs/Include/opennurbs_unicode.h | 4245 ++++ opennurbs/Include/opennurbs_userdata.h | 602 + opennurbs/Include/opennurbs_uuid.h | 610 + opennurbs/Include/opennurbs_version.h | 227 + opennurbs/Include/opennurbs_version_number.h | 428 + opennurbs/Include/opennurbs_viewport.h | 1793 ++ opennurbs/Include/opennurbs_win_dwrite.h | 57 + .../Include/opennurbs_windows_targetver.h | 48 + opennurbs/Include/opennurbs_wip.h | 26 + opennurbs/Include/opennurbs_workspace.h | 452 + opennurbs/Include/opennurbs_xform.h | 2106 ++ opennurbs/Include/opennurbs_zlib.h | 54 + opennurbs/Lib/opennurbs_publicD32.lib | Bin 0 -> 11255422 bytes opennurbs/Lib/opennurbs_publicD32.pdb | Bin 0 -> 16822272 bytes opennurbs/Lib/opennurbs_publicD64.lib | Bin 0 -> 7989422 bytes opennurbs/Lib/opennurbs_publicD64.pdb | Bin 0 -> 23760896 bytes opennurbs/Lib/opennurbs_publicR32.lib | Bin 0 -> 11255422 bytes opennurbs/Lib/opennurbs_publicR32.pdb | Bin 0 -> 27127808 bytes opennurbs/Lib/opennurbs_publicR64.lib | Bin 0 -> 7989422 bytes opennurbs/Lib/opennurbs_publicR64.pdb | Bin 0 -> 25169920 bytes 174 files changed, 153790 insertions(+) create mode 100644 opennurbs/Include/dwrite_1_x32.h create mode 100644 opennurbs/Include/dwrite_2_x32.h create mode 100644 opennurbs/Include/dwrite_x32.h create mode 100644 opennurbs/Include/opennurbs.h create mode 100644 opennurbs/Include/opennurbs_3dm.h create mode 100644 opennurbs/Include/opennurbs_3dm_attributes.h create mode 100644 opennurbs/Include/opennurbs_3dm_properties.h create mode 100644 opennurbs/Include/opennurbs_3dm_settings.h create mode 100644 opennurbs/Include/opennurbs_annotationbase.h create mode 100644 opennurbs/Include/opennurbs_apple_nsfont.h create mode 100644 opennurbs/Include/opennurbs_arc.h create mode 100644 opennurbs/Include/opennurbs_arccurve.h create mode 100644 opennurbs/Include/opennurbs_archive.h create mode 100644 opennurbs/Include/opennurbs_array.h create mode 100644 opennurbs/Include/opennurbs_array_defs.h create mode 100644 opennurbs/Include/opennurbs_atomic_op.h create mode 100644 opennurbs/Include/opennurbs_base32.h create mode 100644 opennurbs/Include/opennurbs_base64.h create mode 100644 opennurbs/Include/opennurbs_beam.h create mode 100644 opennurbs/Include/opennurbs_bezier.h create mode 100644 opennurbs/Include/opennurbs_bitmap.h create mode 100644 opennurbs/Include/opennurbs_bounding_box.h create mode 100644 opennurbs/Include/opennurbs_box.h create mode 100644 opennurbs/Include/opennurbs_brep.h create mode 100644 opennurbs/Include/opennurbs_circle.h create mode 100644 opennurbs/Include/opennurbs_color.h create mode 100644 opennurbs/Include/opennurbs_compress.h create mode 100644 opennurbs/Include/opennurbs_compstat.h create mode 100644 opennurbs/Include/opennurbs_cone.h create mode 100644 opennurbs/Include/opennurbs_convex_poly.h create mode 100644 opennurbs/Include/opennurbs_cpp_base.h create mode 100644 opennurbs/Include/opennurbs_crc.h create mode 100644 opennurbs/Include/opennurbs_curve.h create mode 100644 opennurbs/Include/opennurbs_curveonsurface.h create mode 100644 opennurbs/Include/opennurbs_curveproxy.h create mode 100644 opennurbs/Include/opennurbs_cylinder.h create mode 100644 opennurbs/Include/opennurbs_date.h create mode 100644 opennurbs/Include/opennurbs_defines.h create mode 100644 opennurbs/Include/opennurbs_detail.h create mode 100644 opennurbs/Include/opennurbs_dimension.h create mode 100644 opennurbs/Include/opennurbs_dimensionformat.h create mode 100644 opennurbs/Include/opennurbs_dimensionstyle.h create mode 100644 opennurbs/Include/opennurbs_dll_resource.h create mode 100644 opennurbs/Include/opennurbs_ellipse.h create mode 100644 opennurbs/Include/opennurbs_error.h create mode 100644 opennurbs/Include/opennurbs_evaluate_nurbs.h create mode 100644 opennurbs/Include/opennurbs_extensions.h create mode 100644 opennurbs/Include/opennurbs_file_utilities.h create mode 100644 opennurbs/Include/opennurbs_font.h create mode 100644 opennurbs/Include/opennurbs_fpoint.h create mode 100644 opennurbs/Include/opennurbs_freetype.h create mode 100644 opennurbs/Include/opennurbs_freetype_include.h create mode 100644 opennurbs/Include/opennurbs_fsp.h create mode 100644 opennurbs/Include/opennurbs_fsp_defs.h create mode 100644 opennurbs/Include/opennurbs_function_list.h create mode 100644 opennurbs/Include/opennurbs_geometry.h create mode 100644 opennurbs/Include/opennurbs_gl.h create mode 100644 opennurbs/Include/opennurbs_group.h create mode 100644 opennurbs/Include/opennurbs_hash_table.h create mode 100644 opennurbs/Include/opennurbs_hatch.h create mode 100644 opennurbs/Include/opennurbs_hsort_template.h create mode 100644 opennurbs/Include/opennurbs_input_libsdir.h create mode 100644 opennurbs/Include/opennurbs_instance.h create mode 100644 opennurbs/Include/opennurbs_internal_V2_annotation.h create mode 100644 opennurbs/Include/opennurbs_internal_V5_annotation.h create mode 100644 opennurbs/Include/opennurbs_internal_V5_dimstyle.h create mode 100644 opennurbs/Include/opennurbs_internal_defines.h create mode 100644 opennurbs/Include/opennurbs_internal_glyph.h create mode 100644 opennurbs/Include/opennurbs_internal_unicode_cp.h create mode 100644 opennurbs/Include/opennurbs_intersect.h create mode 100644 opennurbs/Include/opennurbs_ipoint.h create mode 100644 opennurbs/Include/opennurbs_knot.h create mode 100644 opennurbs/Include/opennurbs_layer.h create mode 100644 opennurbs/Include/opennurbs_leader.h create mode 100644 opennurbs/Include/opennurbs_light.h create mode 100644 opennurbs/Include/opennurbs_line.h create mode 100644 opennurbs/Include/opennurbs_linecurve.h create mode 100644 opennurbs/Include/opennurbs_linestyle.h create mode 100644 opennurbs/Include/opennurbs_linetype.h create mode 100644 opennurbs/Include/opennurbs_locale.h create mode 100644 opennurbs/Include/opennurbs_lock.h create mode 100644 opennurbs/Include/opennurbs_lookup.h create mode 100644 opennurbs/Include/opennurbs_mapchan.h create mode 100644 opennurbs/Include/opennurbs_material.h create mode 100644 opennurbs/Include/opennurbs_math.h create mode 100644 opennurbs/Include/opennurbs_matrix.h create mode 100644 opennurbs/Include/opennurbs_md5.h create mode 100644 opennurbs/Include/opennurbs_memory.h create mode 100644 opennurbs/Include/opennurbs_mesh.h create mode 100644 opennurbs/Include/opennurbs_model_component.h create mode 100644 opennurbs/Include/opennurbs_model_geometry.h create mode 100644 opennurbs/Include/opennurbs_nurbscurve.h create mode 100644 opennurbs/Include/opennurbs_nurbssurface.h create mode 100644 opennurbs/Include/opennurbs_object.h create mode 100644 opennurbs/Include/opennurbs_object_history.h create mode 100644 opennurbs/Include/opennurbs_objref.h create mode 100644 opennurbs/Include/opennurbs_offsetsurface.h create mode 100644 opennurbs/Include/opennurbs_optimize.h create mode 100644 opennurbs/Include/opennurbs_parse.h create mode 100644 opennurbs/Include/opennurbs_photogrammetry.h create mode 100644 opennurbs/Include/opennurbs_plane.h create mode 100644 opennurbs/Include/opennurbs_planesurface.h create mode 100644 opennurbs/Include/opennurbs_pluginlist.h create mode 100644 opennurbs/Include/opennurbs_point.h create mode 100644 opennurbs/Include/opennurbs_pointcloud.h create mode 100644 opennurbs/Include/opennurbs_pointgeometry.h create mode 100644 opennurbs/Include/opennurbs_pointgrid.h create mode 100644 opennurbs/Include/opennurbs_polycurve.h create mode 100644 opennurbs/Include/opennurbs_polyedgecurve.h create mode 100644 opennurbs/Include/opennurbs_polyline.h create mode 100644 opennurbs/Include/opennurbs_polylinecurve.h create mode 100644 opennurbs/Include/opennurbs_private_wrap.h create mode 100644 opennurbs/Include/opennurbs_private_wrap_defs.h create mode 100644 opennurbs/Include/opennurbs_progress_reporter.h create mode 100644 opennurbs/Include/opennurbs_public.h create mode 100644 opennurbs/Include/opennurbs_public_examples.h create mode 100644 opennurbs/Include/opennurbs_public_version.h create mode 100644 opennurbs/Include/opennurbs_qsort_template.h create mode 100644 opennurbs/Include/opennurbs_quacksort_template.h create mode 100644 opennurbs/Include/opennurbs_quaternion.h create mode 100644 opennurbs/Include/opennurbs_rand.h create mode 100644 opennurbs/Include/opennurbs_rendering.h create mode 100644 opennurbs/Include/opennurbs_revsurface.h create mode 100644 opennurbs/Include/opennurbs_rtree.h create mode 100644 opennurbs/Include/opennurbs_sha1.h create mode 100644 opennurbs/Include/opennurbs_sleeplock.h create mode 100644 opennurbs/Include/opennurbs_sphere.h create mode 100644 opennurbs/Include/opennurbs_std_string.h create mode 100644 opennurbs/Include/opennurbs_string.h create mode 100644 opennurbs/Include/opennurbs_string_value.h create mode 100644 opennurbs/Include/opennurbs_subd.h create mode 100644 opennurbs/Include/opennurbs_subd_data.h create mode 100644 opennurbs/Include/opennurbs_sumsurface.h create mode 100644 opennurbs/Include/opennurbs_surface.h create mode 100644 opennurbs/Include/opennurbs_surfaceproxy.h create mode 100644 opennurbs/Include/opennurbs_symmetry.h create mode 100644 opennurbs/Include/opennurbs_system.h create mode 100644 opennurbs/Include/opennurbs_system_compiler.h create mode 100644 opennurbs/Include/opennurbs_system_runtime.h create mode 100644 opennurbs/Include/opennurbs_terminator.h create mode 100644 opennurbs/Include/opennurbs_testclass.h create mode 100644 opennurbs/Include/opennurbs_text.h create mode 100644 opennurbs/Include/opennurbs_text_style.h create mode 100644 opennurbs/Include/opennurbs_textcontext.h create mode 100644 opennurbs/Include/opennurbs_textdraw.h create mode 100644 opennurbs/Include/opennurbs_textglyph.h create mode 100644 opennurbs/Include/opennurbs_textiterator.h create mode 100644 opennurbs/Include/opennurbs_textlog.h create mode 100644 opennurbs/Include/opennurbs_textobject.h create mode 100644 opennurbs/Include/opennurbs_textrun.h create mode 100644 opennurbs/Include/opennurbs_texture.h create mode 100644 opennurbs/Include/opennurbs_texture_mapping.h create mode 100644 opennurbs/Include/opennurbs_topology.h create mode 100644 opennurbs/Include/opennurbs_torus.h create mode 100644 opennurbs/Include/opennurbs_unicode.h create mode 100644 opennurbs/Include/opennurbs_userdata.h create mode 100644 opennurbs/Include/opennurbs_uuid.h create mode 100644 opennurbs/Include/opennurbs_version.h create mode 100644 opennurbs/Include/opennurbs_version_number.h create mode 100644 opennurbs/Include/opennurbs_viewport.h create mode 100644 opennurbs/Include/opennurbs_win_dwrite.h create mode 100644 opennurbs/Include/opennurbs_windows_targetver.h create mode 100644 opennurbs/Include/opennurbs_wip.h create mode 100644 opennurbs/Include/opennurbs_workspace.h create mode 100644 opennurbs/Include/opennurbs_xform.h create mode 100644 opennurbs/Include/opennurbs_zlib.h create mode 100644 opennurbs/Lib/opennurbs_publicD32.lib create mode 100644 opennurbs/Lib/opennurbs_publicD32.pdb create mode 100644 opennurbs/Lib/opennurbs_publicD64.lib create mode 100644 opennurbs/Lib/opennurbs_publicD64.pdb create mode 100644 opennurbs/Lib/opennurbs_publicR32.lib create mode 100644 opennurbs/Lib/opennurbs_publicR32.pdb create mode 100644 opennurbs/Lib/opennurbs_publicR64.lib create mode 100644 opennurbs/Lib/opennurbs_publicR64.pdb diff --git a/opennurbs/Include/dwrite_1_x32.h b/opennurbs/Include/dwrite_1_x32.h new file mode 100644 index 0000000..ba83072 --- /dev/null +++ b/opennurbs/Include/dwrite_1_x32.h @@ -0,0 +1,1926 @@ +//+-------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Abstract: +// DirectX Typography Services public API definitions. +// +//---------------------------------------------------------------------------- + +#ifndef DWRITE_1_H_INCLUDED +#define DWRITE_1_H_INCLUDED + +#pragma once + +#include + + + +/// +/// The overall kind of family. +/// +enum DWRITE_PANOSE_FAMILY +{ + DWRITE_PANOSE_FAMILY_ANY = 0, + DWRITE_PANOSE_FAMILY_NO_FIT = 1, + DWRITE_PANOSE_FAMILY_TEXT_DISPLAY = 2, + DWRITE_PANOSE_FAMILY_SCRIPT = 3, // or hand written + DWRITE_PANOSE_FAMILY_DECORATIVE = 4, + DWRITE_PANOSE_FAMILY_SYMBOL = 5, // or symbol + DWRITE_PANOSE_FAMILY_PICTORIAL = DWRITE_PANOSE_FAMILY_SYMBOL +}; + +/// +/// Appearance of the serifs. +/// Present for families: 2-text +/// +enum DWRITE_PANOSE_SERIF_STYLE +{ + DWRITE_PANOSE_SERIF_STYLE_ANY = 0, + DWRITE_PANOSE_SERIF_STYLE_NO_FIT = 1, + DWRITE_PANOSE_SERIF_STYLE_COVE = 2, + DWRITE_PANOSE_SERIF_STYLE_OBTUSE_COVE = 3, + DWRITE_PANOSE_SERIF_STYLE_SQUARE_COVE = 4, + DWRITE_PANOSE_SERIF_STYLE_OBTUSE_SQUARE_COVE = 5, + DWRITE_PANOSE_SERIF_STYLE_SQUARE = 6, + DWRITE_PANOSE_SERIF_STYLE_THIN = 7, + DWRITE_PANOSE_SERIF_STYLE_OVAL = 8, + DWRITE_PANOSE_SERIF_STYLE_EXAGGERATED = 9, + DWRITE_PANOSE_SERIF_STYLE_TRIANGLE = 10, + DWRITE_PANOSE_SERIF_STYLE_NORMAL_SANS = 11, + DWRITE_PANOSE_SERIF_STYLE_OBTUSE_SANS = 12, + DWRITE_PANOSE_SERIF_STYLE_PERPENDICULAR_SANS = 13, + DWRITE_PANOSE_SERIF_STYLE_FLARED = 14, + DWRITE_PANOSE_SERIF_STYLE_ROUNDED = 15, + DWRITE_PANOSE_SERIF_STYLE_SCRIPT = 16, + DWRITE_PANOSE_SERIF_STYLE_PERP_SANS = DWRITE_PANOSE_SERIF_STYLE_PERPENDICULAR_SANS, + DWRITE_PANOSE_SERIF_STYLE_BONE = DWRITE_PANOSE_SERIF_STYLE_OVAL +}; + +/// +/// PANOSE font weights. These roughly correspond to the DWRITE_FONT_WEIGHT's +/// using (panose_weight - 2) * 100. +/// Present for families: 2-text, 3-script, 4-decorative, 5-symbol +/// +enum DWRITE_PANOSE_WEIGHT +{ + DWRITE_PANOSE_WEIGHT_ANY = 0, + DWRITE_PANOSE_WEIGHT_NO_FIT = 1, + DWRITE_PANOSE_WEIGHT_VERY_LIGHT = 2, + DWRITE_PANOSE_WEIGHT_LIGHT = 3, + DWRITE_PANOSE_WEIGHT_THIN = 4, + DWRITE_PANOSE_WEIGHT_BOOK = 5, + DWRITE_PANOSE_WEIGHT_MEDIUM = 6, + DWRITE_PANOSE_WEIGHT_DEMI = 7, + DWRITE_PANOSE_WEIGHT_BOLD = 8, + DWRITE_PANOSE_WEIGHT_HEAVY = 9, + DWRITE_PANOSE_WEIGHT_BLACK = 10, + DWRITE_PANOSE_WEIGHT_EXTRA_BLACK = 11, + DWRITE_PANOSE_WEIGHT_NORD = DWRITE_PANOSE_WEIGHT_EXTRA_BLACK +}; + +/// +/// Proportion of the glyph shape considering additional detail to standard +/// characters. +/// Present for families: 2-text +/// +enum DWRITE_PANOSE_PROPORTION +{ + DWRITE_PANOSE_PROPORTION_ANY = 0, + DWRITE_PANOSE_PROPORTION_NO_FIT = 1, + DWRITE_PANOSE_PROPORTION_OLD_STYLE = 2, + DWRITE_PANOSE_PROPORTION_MODERN = 3, + DWRITE_PANOSE_PROPORTION_EVEN_WIDTH = 4, + DWRITE_PANOSE_PROPORTION_EXPANDED = 5, + DWRITE_PANOSE_PROPORTION_CONDENSED = 6, + DWRITE_PANOSE_PROPORTION_VERY_EXPANDED = 7, + DWRITE_PANOSE_PROPORTION_VERY_CONDENSED = 8, + DWRITE_PANOSE_PROPORTION_MONOSPACED = 9 +}; + +/// +/// Ratio between thickest and thinnest point of the stroke for a letter such +/// as uppercase 'O'. +/// Present for families: 2-text, 3-script, 4-decorative +/// +enum DWRITE_PANOSE_CONTRAST +{ + DWRITE_PANOSE_CONTRAST_ANY = 0, + DWRITE_PANOSE_CONTRAST_NO_FIT = 1, + DWRITE_PANOSE_CONTRAST_NONE = 2, + DWRITE_PANOSE_CONTRAST_VERY_LOW = 3, + DWRITE_PANOSE_CONTRAST_LOW = 4, + DWRITE_PANOSE_CONTRAST_MEDIUM_LOW = 5, + DWRITE_PANOSE_CONTRAST_MEDIUM = 6, + DWRITE_PANOSE_CONTRAST_MEDIUM_HIGH = 7, + DWRITE_PANOSE_CONTRAST_HIGH = 8, + DWRITE_PANOSE_CONTRAST_VERY_HIGH = 9, + DWRITE_PANOSE_CONTRAST_HORIZONTAL_LOW = 10, + DWRITE_PANOSE_CONTRAST_HORIZONTAL_MEDIUM = 11, + DWRITE_PANOSE_CONTRAST_HORIZONTAL_HIGH = 12, + DWRITE_PANOSE_CONTRAST_BROKEN = 13 +}; + +/// +/// Relationship between thin and thick stems. +/// Present for families: 2-text +/// +enum DWRITE_PANOSE_STROKE_VARIATION +{ + DWRITE_PANOSE_STROKE_VARIATION_ANY = 0, + DWRITE_PANOSE_STROKE_VARIATION_NO_FIT = 1, + DWRITE_PANOSE_STROKE_VARIATION_NO_VARIATION = 2, + DWRITE_PANOSE_STROKE_VARIATION_GRADUAL_DIAGONAL = 3, + DWRITE_PANOSE_STROKE_VARIATION_GRADUAL_TRANSITIONAL = 4, + DWRITE_PANOSE_STROKE_VARIATION_GRADUAL_VERTICAL = 5, + DWRITE_PANOSE_STROKE_VARIATION_GRADUAL_HORIZONTAL = 6, + DWRITE_PANOSE_STROKE_VARIATION_RAPID_VERTICAL = 7, + DWRITE_PANOSE_STROKE_VARIATION_RAPID_HORIZONTAL = 8, + DWRITE_PANOSE_STROKE_VARIATION_INSTANT_VERTICAL = 9, + DWRITE_PANOSE_STROKE_VARIATION_INSTANT_HORIZONTAL = 10 +}; + +/// +/// Style of termination of stems and rounded letterforms. +/// Present for families: 2-text +/// +enum DWRITE_PANOSE_ARM_STYLE +{ + DWRITE_PANOSE_ARM_STYLE_ANY = 0, + DWRITE_PANOSE_ARM_STYLE_NO_FIT = 1, + DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_HORIZONTAL = 2, + DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_WEDGE = 3, + DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_VERTICAL = 4, + DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_SINGLE_SERIF = 5, + DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_DOUBLE_SERIF = 6, + DWRITE_PANOSE_ARM_STYLE_NONSTRAIGHT_ARMS_HORIZONTAL = 7, + DWRITE_PANOSE_ARM_STYLE_NONSTRAIGHT_ARMS_WEDGE = 8, + DWRITE_PANOSE_ARM_STYLE_NONSTRAIGHT_ARMS_VERTICAL = 9, + DWRITE_PANOSE_ARM_STYLE_NONSTRAIGHT_ARMS_SINGLE_SERIF = 10, + DWRITE_PANOSE_ARM_STYLE_NONSTRAIGHT_ARMS_DOUBLE_SERIF = 11, + DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_HORZ = DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_HORIZONTAL, + DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_VERT = DWRITE_PANOSE_ARM_STYLE_STRAIGHT_ARMS_VERTICAL, + DWRITE_PANOSE_ARM_STYLE_BENT_ARMS_HORZ = DWRITE_PANOSE_ARM_STYLE_NONSTRAIGHT_ARMS_HORIZONTAL, + DWRITE_PANOSE_ARM_STYLE_BENT_ARMS_WEDGE = DWRITE_PANOSE_ARM_STYLE_NONSTRAIGHT_ARMS_WEDGE, + DWRITE_PANOSE_ARM_STYLE_BENT_ARMS_VERT = DWRITE_PANOSE_ARM_STYLE_NONSTRAIGHT_ARMS_VERTICAL, + DWRITE_PANOSE_ARM_STYLE_BENT_ARMS_SINGLE_SERIF = DWRITE_PANOSE_ARM_STYLE_NONSTRAIGHT_ARMS_SINGLE_SERIF, + DWRITE_PANOSE_ARM_STYLE_BENT_ARMS_DOUBLE_SERIF = DWRITE_PANOSE_ARM_STYLE_NONSTRAIGHT_ARMS_DOUBLE_SERIF +}; + +/// +/// Roundness of letterform. +/// Present for families: 2-text +/// +enum DWRITE_PANOSE_LETTERFORM +{ + DWRITE_PANOSE_LETTERFORM_ANY = 0, + DWRITE_PANOSE_LETTERFORM_NO_FIT = 1, + DWRITE_PANOSE_LETTERFORM_NORMAL_CONTACT = 2, + DWRITE_PANOSE_LETTERFORM_NORMAL_WEIGHTED = 3, + DWRITE_PANOSE_LETTERFORM_NORMAL_BOXED = 4, + DWRITE_PANOSE_LETTERFORM_NORMAL_FLATTENED = 5, + DWRITE_PANOSE_LETTERFORM_NORMAL_ROUNDED = 6, + DWRITE_PANOSE_LETTERFORM_NORMAL_OFF_CENTER = 7, + DWRITE_PANOSE_LETTERFORM_NORMAL_SQUARE = 8, + DWRITE_PANOSE_LETTERFORM_OBLIQUE_CONTACT = 9, + DWRITE_PANOSE_LETTERFORM_OBLIQUE_WEIGHTED = 10, + DWRITE_PANOSE_LETTERFORM_OBLIQUE_BOXED = 11, + DWRITE_PANOSE_LETTERFORM_OBLIQUE_FLATTENED = 12, + DWRITE_PANOSE_LETTERFORM_OBLIQUE_ROUNDED = 13, + DWRITE_PANOSE_LETTERFORM_OBLIQUE_OFF_CENTER = 14, + DWRITE_PANOSE_LETTERFORM_OBLIQUE_SQUARE = 15 +}; + +/// +/// Placement of midline across uppercase characters and treatment of diagonal +/// stem apexes. +/// Present for families: 2-text +/// +enum DWRITE_PANOSE_MIDLINE +{ + DWRITE_PANOSE_MIDLINE_ANY = 0, + DWRITE_PANOSE_MIDLINE_NO_FIT = 1, + DWRITE_PANOSE_MIDLINE_STANDARD_TRIMMED = 2, + DWRITE_PANOSE_MIDLINE_STANDARD_POINTED = 3, + DWRITE_PANOSE_MIDLINE_STANDARD_SERIFED = 4, + DWRITE_PANOSE_MIDLINE_HIGH_TRIMMED = 5, + DWRITE_PANOSE_MIDLINE_HIGH_POINTED = 6, + DWRITE_PANOSE_MIDLINE_HIGH_SERIFED = 7, + DWRITE_PANOSE_MIDLINE_CONSTANT_TRIMMED = 8, + DWRITE_PANOSE_MIDLINE_CONSTANT_POINTED = 9, + DWRITE_PANOSE_MIDLINE_CONSTANT_SERIFED = 10, + DWRITE_PANOSE_MIDLINE_LOW_TRIMMED = 11, + DWRITE_PANOSE_MIDLINE_LOW_POINTED = 12, + DWRITE_PANOSE_MIDLINE_LOW_SERIFED = 13 +}; + +/// +/// Relative size of lowercase letters and treament of diacritic marks +/// and uppercase glyphs. +/// Present for families: 2-text +/// +enum DWRITE_PANOSE_XHEIGHT +{ + DWRITE_PANOSE_XHEIGHT_ANY = 0, + DWRITE_PANOSE_XHEIGHT_NO_FIT = 1, + DWRITE_PANOSE_XHEIGHT_CONSTANT_SMALL = 2, + DWRITE_PANOSE_XHEIGHT_CONSTANT_STANDARD = 3, + DWRITE_PANOSE_XHEIGHT_CONSTANT_LARGE = 4, + DWRITE_PANOSE_XHEIGHT_DUCKING_SMALL = 5, + DWRITE_PANOSE_XHEIGHT_DUCKING_STANDARD = 6, + DWRITE_PANOSE_XHEIGHT_DUCKING_LARGE = 7, + DWRITE_PANOSE_XHEIGHT_CONSTANT_STD = DWRITE_PANOSE_XHEIGHT_CONSTANT_STANDARD, + DWRITE_PANOSE_XHEIGHT_DUCKING_STD = DWRITE_PANOSE_XHEIGHT_DUCKING_STANDARD +}; + +/// +/// Kind of tool used to create character forms. +/// Present for families: 3-script +/// +enum DWRITE_PANOSE_TOOL_KIND +{ + DWRITE_PANOSE_TOOL_KIND_ANY = 0, + DWRITE_PANOSE_TOOL_KIND_NO_FIT = 1, + DWRITE_PANOSE_TOOL_KIND_FLAT_NIB = 2, + DWRITE_PANOSE_TOOL_KIND_PRESSURE_POINT = 3, + DWRITE_PANOSE_TOOL_KIND_ENGRAVED = 4, + DWRITE_PANOSE_TOOL_KIND_BALL = 5, + DWRITE_PANOSE_TOOL_KIND_BRUSH = 6, + DWRITE_PANOSE_TOOL_KIND_ROUGH = 7, + DWRITE_PANOSE_TOOL_KIND_FELT_PEN_BRUSH_TIP = 8, + DWRITE_PANOSE_TOOL_KIND_WILD_BRUSH = 9 +}; + +/// +/// Monospace vs proportional. +/// Present for families: 3-script, 5-symbol +/// +enum DWRITE_PANOSE_SPACING +{ + DWRITE_PANOSE_SPACING_ANY = 0, + DWRITE_PANOSE_SPACING_NO_FIT = 1, + DWRITE_PANOSE_SPACING_PROPORTIONAL_SPACED = 2, + DWRITE_PANOSE_SPACING_MONOSPACED = 3, +}; + +/// +/// Ratio between width and height of the face. +/// Present for families: 3-script +/// +enum DWRITE_PANOSE_ASPECT_RATIO +{ + DWRITE_PANOSE_ASPECT_RATIO_ANY = 0, + DWRITE_PANOSE_ASPECT_RATIO_NO_FIT = 1, + DWRITE_PANOSE_ASPECT_RATIO_VERY_CONDENSED = 2, + DWRITE_PANOSE_ASPECT_RATIO_CONDENSED = 3, + DWRITE_PANOSE_ASPECT_RATIO_NORMAL = 4, + DWRITE_PANOSE_ASPECT_RATIO_EXPANDED = 5, + DWRITE_PANOSE_ASPECT_RATIO_VERY_EXPANDED = 6 +}; + +/// +/// Topology of letterforms. +/// Present for families: 3-script +/// +enum DWRITE_PANOSE_SCRIPT_TOPOLOGY +{ + DWRITE_PANOSE_SCRIPT_TOPOLOGY_ANY = 0, + DWRITE_PANOSE_SCRIPT_TOPOLOGY_NO_FIT = 1, + DWRITE_PANOSE_SCRIPT_TOPOLOGY_ROMAN_DISCONNECTED = 2, + DWRITE_PANOSE_SCRIPT_TOPOLOGY_ROMAN_TRAILING = 3, + DWRITE_PANOSE_SCRIPT_TOPOLOGY_ROMAN_CONNECTED = 4, + DWRITE_PANOSE_SCRIPT_TOPOLOGY_CURSIVE_DISCONNECTED = 5, + DWRITE_PANOSE_SCRIPT_TOPOLOGY_CURSIVE_TRAILING = 6, + DWRITE_PANOSE_SCRIPT_TOPOLOGY_CURSIVE_CONNECTED = 7, + DWRITE_PANOSE_SCRIPT_TOPOLOGY_BLACKLETTER_DISCONNECTED = 8, + DWRITE_PANOSE_SCRIPT_TOPOLOGY_BLACKLETTER_TRAILING = 9, + DWRITE_PANOSE_SCRIPT_TOPOLOGY_BLACKLETTER_CONNECTED = 10 +}; + +/// +/// General look of the face, considering slope and tails. +/// Present for families: 3-script +/// +enum DWRITE_PANOSE_SCRIPT_FORM +{ + DWRITE_PANOSE_SCRIPT_FORM_ANY = 0, + DWRITE_PANOSE_SCRIPT_FORM_NO_FIT = 1, + DWRITE_PANOSE_SCRIPT_FORM_UPRIGHT_NO_WRAPPING = 2, + DWRITE_PANOSE_SCRIPT_FORM_UPRIGHT_SOME_WRAPPING = 3, + DWRITE_PANOSE_SCRIPT_FORM_UPRIGHT_MORE_WRAPPING = 4, + DWRITE_PANOSE_SCRIPT_FORM_UPRIGHT_EXTREME_WRAPPING = 5, + DWRITE_PANOSE_SCRIPT_FORM_OBLIQUE_NO_WRAPPING = 6, + DWRITE_PANOSE_SCRIPT_FORM_OBLIQUE_SOME_WRAPPING = 7, + DWRITE_PANOSE_SCRIPT_FORM_OBLIQUE_MORE_WRAPPING = 8, + DWRITE_PANOSE_SCRIPT_FORM_OBLIQUE_EXTREME_WRAPPING = 9, + DWRITE_PANOSE_SCRIPT_FORM_EXAGGERATED_NO_WRAPPING = 10, + DWRITE_PANOSE_SCRIPT_FORM_EXAGGERATED_SOME_WRAPPING = 11, + DWRITE_PANOSE_SCRIPT_FORM_EXAGGERATED_MORE_WRAPPING = 12, + DWRITE_PANOSE_SCRIPT_FORM_EXAGGERATED_EXTREME_WRAPPING = 13 +}; + +/// +/// How character ends and miniscule ascenders are treated. +/// Present for families: 3-script +/// +enum DWRITE_PANOSE_FINIALS +{ + DWRITE_PANOSE_FINIALS_ANY = 0, + DWRITE_PANOSE_FINIALS_NO_FIT = 1, + DWRITE_PANOSE_FINIALS_NONE_NO_LOOPS = 2, + DWRITE_PANOSE_FINIALS_NONE_CLOSED_LOOPS = 3, + DWRITE_PANOSE_FINIALS_NONE_OPEN_LOOPS = 4, + DWRITE_PANOSE_FINIALS_SHARP_NO_LOOPS = 5, + DWRITE_PANOSE_FINIALS_SHARP_CLOSED_LOOPS = 6, + DWRITE_PANOSE_FINIALS_SHARP_OPEN_LOOPS = 7, + DWRITE_PANOSE_FINIALS_TAPERED_NO_LOOPS = 8, + DWRITE_PANOSE_FINIALS_TAPERED_CLOSED_LOOPS = 9, + DWRITE_PANOSE_FINIALS_TAPERED_OPEN_LOOPS = 10, + DWRITE_PANOSE_FINIALS_ROUND_NO_LOOPS = 11, + DWRITE_PANOSE_FINIALS_ROUND_CLOSED_LOOPS = 12, + DWRITE_PANOSE_FINIALS_ROUND_OPEN_LOOPS = 13 +}; + +/// +/// Relative size of the lowercase letters. +/// Present for families: 3-script +/// +enum DWRITE_PANOSE_XASCENT +{ + DWRITE_PANOSE_XASCENT_ANY = 0, + DWRITE_PANOSE_XASCENT_NO_FIT = 1, + DWRITE_PANOSE_XASCENT_VERY_LOW = 2, + DWRITE_PANOSE_XASCENT_LOW = 3, + DWRITE_PANOSE_XASCENT_MEDIUM = 4, + DWRITE_PANOSE_XASCENT_HIGH = 5, + DWRITE_PANOSE_XASCENT_VERY_HIGH = 6 +}; + +/// +/// General look of the face. +/// Present for families: 4-decorative +/// +enum DWRITE_PANOSE_DECORATIVE_CLASS +{ + DWRITE_PANOSE_DECORATIVE_CLASS_ANY = 0, + DWRITE_PANOSE_DECORATIVE_CLASS_NO_FIT = 1, + DWRITE_PANOSE_DECORATIVE_CLASS_DERIVATIVE = 2, + DWRITE_PANOSE_DECORATIVE_CLASS_NONSTANDARD_TOPOLOGY = 3, + DWRITE_PANOSE_DECORATIVE_CLASS_NONSTANDARD_ELEMENTS = 4, + DWRITE_PANOSE_DECORATIVE_CLASS_NONSTANDARD_ASPECT = 5, + DWRITE_PANOSE_DECORATIVE_CLASS_INITIALS = 6, + DWRITE_PANOSE_DECORATIVE_CLASS_CARTOON = 7, + DWRITE_PANOSE_DECORATIVE_CLASS_PICTURE_STEMS = 8, + DWRITE_PANOSE_DECORATIVE_CLASS_ORNAMENTED = 9, + DWRITE_PANOSE_DECORATIVE_CLASS_TEXT_AND_BACKGROUND = 10, + DWRITE_PANOSE_DECORATIVE_CLASS_COLLAGE = 11, + DWRITE_PANOSE_DECORATIVE_CLASS_MONTAGE = 12 +}; + +/// +/// Ratio between the width and height of the face. +/// Present for families: 4-decorative +/// +enum DWRITE_PANOSE_ASPECT +{ + DWRITE_PANOSE_ASPECT_ANY = 0, + DWRITE_PANOSE_ASPECT_NO_FIT = 1, + DWRITE_PANOSE_ASPECT_SUPER_CONDENSED = 2, + DWRITE_PANOSE_ASPECT_VERY_CONDENSED = 3, + DWRITE_PANOSE_ASPECT_CONDENSED = 4, + DWRITE_PANOSE_ASPECT_NORMAL = 5, + DWRITE_PANOSE_ASPECT_EXTENDED = 6, + DWRITE_PANOSE_ASPECT_VERY_EXTENDED = 7, + DWRITE_PANOSE_ASPECT_SUPER_EXTENDED = 8, + DWRITE_PANOSE_ASPECT_MONOSPACED = 9 +}; + +/// +/// Type of fill/line (treatment). +/// Present for families: 4-decorative +/// +enum DWRITE_PANOSE_FILL +{ + DWRITE_PANOSE_FILL_ANY = 0, + DWRITE_PANOSE_FILL_NO_FIT = 1, + DWRITE_PANOSE_FILL_STANDARD_SOLID_FILL = 2, + DWRITE_PANOSE_FILL_NO_FILL = 3, + DWRITE_PANOSE_FILL_PATTERNED_FILL = 4, + DWRITE_PANOSE_FILL_COMPLEX_FILL = 5, + DWRITE_PANOSE_FILL_SHAPED_FILL = 6, + DWRITE_PANOSE_FILL_DRAWN_DISTRESSED = 7, +}; + +/// +/// Outline handling. +/// Present for families: 4-decorative +/// +enum DWRITE_PANOSE_LINING +{ + DWRITE_PANOSE_LINING_ANY = 0, + DWRITE_PANOSE_LINING_NO_FIT = 1, + DWRITE_PANOSE_LINING_NONE = 2, + DWRITE_PANOSE_LINING_INLINE = 3, + DWRITE_PANOSE_LINING_OUTLINE = 4, + DWRITE_PANOSE_LINING_ENGRAVED = 5, + DWRITE_PANOSE_LINING_SHADOW = 6, + DWRITE_PANOSE_LINING_RELIEF = 7, + DWRITE_PANOSE_LINING_BACKDROP = 8 +}; + +/// +/// Overall shape characteristics of the font. +/// Present for families: 4-decorative +/// +enum DWRITE_PANOSE_DECORATIVE_TOPOLOGY +{ + DWRITE_PANOSE_DECORATIVE_TOPOLOGY_ANY = 0, + DWRITE_PANOSE_DECORATIVE_TOPOLOGY_NO_FIT = 1, + DWRITE_PANOSE_DECORATIVE_TOPOLOGY_STANDARD = 2, + DWRITE_PANOSE_DECORATIVE_TOPOLOGY_SQUARE = 3, + DWRITE_PANOSE_DECORATIVE_TOPOLOGY_MULTIPLE_SEGMENT = 4, + DWRITE_PANOSE_DECORATIVE_TOPOLOGY_ART_DECO = 5, + DWRITE_PANOSE_DECORATIVE_TOPOLOGY_UNEVEN_WEIGHTING = 6, + DWRITE_PANOSE_DECORATIVE_TOPOLOGY_DIVERSE_ARMS = 7, + DWRITE_PANOSE_DECORATIVE_TOPOLOGY_DIVERSE_FORMS = 8, + DWRITE_PANOSE_DECORATIVE_TOPOLOGY_LOMBARDIC_FORMS = 9, + DWRITE_PANOSE_DECORATIVE_TOPOLOGY_UPPER_CASE_IN_LOWER_CASE = 10, + DWRITE_PANOSE_DECORATIVE_TOPOLOGY_IMPLIED_TOPOLOGY = 11, + DWRITE_PANOSE_DECORATIVE_TOPOLOGY_HORSESHOE_E_AND_A = 12, + DWRITE_PANOSE_DECORATIVE_TOPOLOGY_CURSIVE = 13, + DWRITE_PANOSE_DECORATIVE_TOPOLOGY_BLACKLETTER = 14, + DWRITE_PANOSE_DECORATIVE_TOPOLOGY_SWASH_VARIANCE = 15 +}; + +/// +/// Type of characters available in the font. +/// Present for families: 4-decorative +/// +enum DWRITE_PANOSE_CHARACTER_RANGES +{ + DWRITE_PANOSE_CHARACTER_RANGES_ANY = 0, + DWRITE_PANOSE_CHARACTER_RANGES_NO_FIT = 1, + DWRITE_PANOSE_CHARACTER_RANGES_EXTENDED_COLLECTION = 2, + DWRITE_PANOSE_CHARACTER_RANGES_LITERALS = 3, + DWRITE_PANOSE_CHARACTER_RANGES_NO_LOWER_CASE = 4, + DWRITE_PANOSE_CHARACTER_RANGES_SMALL_CAPS = 5 +}; + +/// +/// Kind of symbol set. +/// Present for families: 5-symbol +/// +enum DWRITE_PANOSE_SYMBOL_KIND +{ + DWRITE_PANOSE_SYMBOL_KIND_ANY = 0, + DWRITE_PANOSE_SYMBOL_KIND_NO_FIT = 1, + DWRITE_PANOSE_SYMBOL_KIND_MONTAGES = 2, + DWRITE_PANOSE_SYMBOL_KIND_PICTURES = 3, + DWRITE_PANOSE_SYMBOL_KIND_SHAPES = 4, + DWRITE_PANOSE_SYMBOL_KIND_SCIENTIFIC = 5, + DWRITE_PANOSE_SYMBOL_KIND_MUSIC = 6, + DWRITE_PANOSE_SYMBOL_KIND_EXPERT = 7, + DWRITE_PANOSE_SYMBOL_KIND_PATTERNS = 8, + DWRITE_PANOSE_SYMBOL_KIND_BOARDERS = 9, + DWRITE_PANOSE_SYMBOL_KIND_ICONS = 10, + DWRITE_PANOSE_SYMBOL_KIND_LOGOS = 11, + DWRITE_PANOSE_SYMBOL_KIND_INDUSTRY_SPECIFIC = 12 +}; + +/// +/// Aspect ratio of symbolic characters. +/// Present for families: 5-symbol +/// +enum DWRITE_PANOSE_SYMBOL_ASPECT_RATIO +{ + DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_ANY = 0, + DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_NO_FIT = 1, + DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_NO_WIDTH = 2, + DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_EXCEPTIONALLY_WIDE = 3, + DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_SUPER_WIDE = 4, + DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_VERY_WIDE = 5, + DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_WIDE = 6, + DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_NORMAL = 7, + DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_NARROW = 8, + DWRITE_PANOSE_SYMBOL_ASPECT_RATIO_VERY_NARROW = 9 +}; + +/// +/// Specifies the policy used by GetRecommendedRenderingMode to determine whether to +/// render glyphs in outline mode. Glyphs are rendered in outline mode by default at +/// large sizes for performance reasons, but how large (i.e., the outline threshold) +/// depends on the quality of outline rendering. If the graphics system renders anti- +/// aliased outlines then a relatively low threshold is used, but if the graphics +/// system renders aliased outlines then a much higher threshold is used. +/// +enum DWRITE_OUTLINE_THRESHOLD +{ + DWRITE_OUTLINE_THRESHOLD_ANTIALIASED, + DWRITE_OUTLINE_THRESHOLD_ALIASED +}; + +/// +/// Baseline for text alignment. +/// +enum DWRITE_BASELINE +{ + /// + /// The Roman baseline for horizontal, Central baseline for vertical. + /// + DWRITE_BASELINE_DEFAULT, + + /// + /// The baseline used by alphabetic scripts such as Latin, Greek, Cyrillic. + /// + DWRITE_BASELINE_ROMAN, + + /// + /// Central baseline, generally used for vertical text. + /// + DWRITE_BASELINE_CENTRAL, + + /// + /// Mathematical baseline which math characters are centered on. + /// + DWRITE_BASELINE_MATH, + + /// + /// Hanging baseline, used in scripts like Devanagari. + /// + DWRITE_BASELINE_HANGING, + + /// + /// Ideographic bottom baseline for CJK, left in vertical. + /// + DWRITE_BASELINE_IDEOGRAPHIC_BOTTOM, + + /// + /// Ideographic top baseline for CJK, right in vertical. + /// + DWRITE_BASELINE_IDEOGRAPHIC_TOP, + + /// + /// The bottom-most extent in horizontal, left-most in vertical. + /// + DWRITE_BASELINE_MINIMUM, + + /// + /// The top-most extent in horizontal, right-most in vertical. + /// + DWRITE_BASELINE_MAXIMUM, +}; + +/// +/// The desired kind of glyph orientation for the text. The client specifies +/// this to the analyzer as the desired orientation, but note this is the +/// client preference, and the constraints of the script will determine the +/// final presentation. +/// +enum DWRITE_VERTICAL_GLYPH_ORIENTATION +{ + /// + /// In vertical layout, naturally horizontal scripts (Latin, Thai, Arabic, + /// Devanagari) rotate 90 degrees clockwise, while ideographic scripts + /// (Chinese, Japanese, Korean) remain upright, 0 degrees. + /// + DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT, + + /// + /// Ideographic scripts and scripts that permit stacking + /// (Latin, Hebrew) are stacked in vertical reading layout. + /// Connected scripts (Arabic, Syriac, 'Phags-pa, Ogham), + /// which would otherwise look broken if glyphs were kept + /// at 0 degrees, remain connected and rotate. + /// + DWRITE_VERTICAL_GLYPH_ORIENTATION_STACKED, +}; + +/// +/// How the glyph is oriented to the x-axis. This is an output from the text +/// analyzer, dependent on the desired orientation, bidi level, and character +/// properties. +/// +enum DWRITE_GLYPH_ORIENTATION_ANGLE +{ + /// + /// Glyph orientation is upright. + /// + DWRITE_GLYPH_ORIENTATION_ANGLE_0_DEGREES, + + /// + /// Glyph orientation is rotated 90 clockwise. + /// + DWRITE_GLYPH_ORIENTATION_ANGLE_90_DEGREES, + + /// + /// Glyph orientation is upside-down. + /// + DWRITE_GLYPH_ORIENTATION_ANGLE_180_DEGREES, + + /// + /// Glyph orientation is rotated 270 clockwise. + /// + DWRITE_GLYPH_ORIENTATION_ANGLE_270_DEGREES, +}; + + +struct DWRITE_FONT_METRICS1 : public DWRITE_FONT_METRICS +{ + /// + /// Left edge of accumulated bounding blackbox of all glyphs in the font. + /// + INT16 glyphBoxLeft; + + /// + /// Top edge of accumulated bounding blackbox of all glyphs in the font. + /// + INT16 glyphBoxTop; + + /// + /// Right edge of accumulated bounding blackbox of all glyphs in the font. + /// + INT16 glyphBoxRight; + + /// + /// Bottom edge of accumulated bounding blackbox of all glyphs in the font. + /// + INT16 glyphBoxBottom; + + /// + /// Horizontal position of the subscript relative to the baseline origin. + /// This is typically negative (to the left) in italic/oblique fonts, and + /// zero in regular fonts. + /// + INT16 subscriptPositionX; + + /// + /// Vertical position of the subscript relative to the baseline. + /// This is typically negative. + /// + INT16 subscriptPositionY; + + /// + /// Horizontal size of the subscript em box in design units, used to + /// scale the simulated subscript relative to the full em box size. + /// This the numerator of the scaling ratio where denominator is the + /// design units per em. If this member is zero, the font does not specify + /// a scale factor, and the client should use its own policy. + /// + INT16 subscriptSizeX; + + /// + /// Vertical size of the subscript em box in design units, used to + /// scale the simulated subscript relative to the full em box size. + /// This the numerator of the scaling ratio where denominator is the + /// design units per em. If this member is zero, the font does not specify + /// a scale factor, and the client should use its own policy. + /// + INT16 subscriptSizeY; + + /// + /// Horizontal position of the superscript relative to the baseline origin. + /// This is typically positive (to the right) in italic/oblique fonts, and + /// zero in regular fonts. + /// + INT16 superscriptPositionX; + + /// + /// Vertical position of the superscript relative to the baseline. + /// This is typically positive. + /// + INT16 superscriptPositionY; + + /// + /// Horizontal size of the superscript em box in design units, used to + /// scale the simulated superscript relative to the full em box size. + /// This the numerator of the scaling ratio where denominator is the + /// design units per em. If this member is zero, the font does not specify + /// a scale factor, and the client should use its own policy. + /// + INT16 superscriptSizeX; + + /// + /// Vertical size of the superscript em box in design units, used to + /// scale the simulated superscript relative to the full em box size. + /// This the numerator of the scaling ratio where denominator is the + /// design units per em. If this member is zero, the font does not specify + /// a scale factor, and the client should use its own policy. + /// + INT16 superscriptSizeY; + + /// + /// Indicates that the ascent, descent, and lineGap are based on newer + /// 'typographic' values in the font, rather than legacy values. + /// + BOOL hasTypographicMetrics; +}; + + +/// +/// Metrics for caret placement in a font. +/// +struct DWRITE_CARET_METRICS +{ + /// + /// Vertical rise of the caret. Rise / Run yields the caret angle. + /// Rise = 1 for perfectly upright fonts (non-italic). + /// + INT16 slopeRise; + + /// + /// Horizontal run of th caret. Rise / Run yields the caret angle. + /// Run = 0 for perfectly upright fonts (non-italic). + /// + INT16 slopeRun; + + /// + /// Horizontal offset of the caret along the baseline for good appearance. + /// Offset = 0 for perfectly upright fonts (non-italic). + /// + INT16 offset; +}; + + +/// +/// Typeface classification values, used for font selection and matching. +/// +/// +/// Note the family type (index 0) is the only stable entry in the 10-byte +/// array, as all the following entries can change dynamically depending on +/// context of the first field. +/// +union DWRITE_PANOSE +{ + UINT8 values[10]; + + UINT8 familyKind; // this is the only field that never changes meaning + + struct + { + UINT8 familyKind; // = 2 for text + UINT8 serifStyle; + UINT8 weight; + UINT8 proportion; + UINT8 contrast; + UINT8 strokeVariation; + UINT8 armStyle; + UINT8 letterform; + UINT8 midline; + UINT8 xHeight; + } text; + + struct + { + UINT8 familyKind; // = 3 for script + UINT8 toolKind; + UINT8 weight; + UINT8 spacing; + UINT8 aspectRatio; + UINT8 contrast; + UINT8 scriptTopology; + UINT8 scriptForm; + UINT8 finials; + UINT8 xAscent; + } script; + + struct + { + UINT8 familyKind; // = 4 for decorative + UINT8 decorativeClass; + UINT8 weight; + UINT8 aspect; + UINT8 contrast; + UINT8 serifVariant; + UINT8 fill; // treatment + UINT8 lining; + UINT8 decorativeTopology; + UINT8 characterRange; + } decorative; + + struct + { + UINT8 familyKind; // = 5 for symbol + UINT8 symbolKind; + UINT8 weight; + UINT8 spacing; + UINT8 aspectRatioAndContrast; // hard coded to no-fit (1) + UINT8 aspectRatio94; + UINT8 aspectRatio119; + UINT8 aspectRatio157; + UINT8 aspectRatio163; + UINT8 aspectRatio211; + } symbol; +}; + + +/// +/// Range of Unicode codepoints. +/// +struct DWRITE_UNICODE_RANGE +{ + /// + /// The first codepoint in the Unicode range. + /// + UINT32 first; + + /// + /// The last codepoint in the Unicode range. + /// + UINT32 last; +}; + + +/// +/// Script-specific properties for caret navigation and justification. +/// +struct DWRITE_SCRIPT_PROPERTIES +{ + /// + /// The standardized four character code for the given script. + /// Note these only include the general Unicode scripts, not any + /// additional ISO 15924 scripts for bibliographic distinction + /// (for example, Fraktur Latin vs Gaelic Latin). + /// http://unicode.org/iso15924/iso15924-codes.html + /// + UINT32 isoScriptCode; + + /// + /// The standardized numeric code, ranging 0-999. + /// http://unicode.org/iso15924/iso15924-codes.html + /// + UINT32 isoScriptNumber; + + /// + /// Number of characters to estimate look-ahead for complex scripts. + /// Latin and all Kana are generally 1. Indic scripts are up to 15, + /// and most others are 8. Note that combining marks and variation + /// selectors can produce clusters longer than these look-aheads, + /// so this estimate is considered typical language use. Diacritics + /// must be tested explicitly separately. + /// + UINT32 clusterLookahead; + + /// + /// Appropriate character to elongate the given script for justification. + /// + /// Examples: + /// Arabic - U+0640 Tatweel + /// Ogham - U+1680 Ogham Space Mark + /// + UINT32 justificationCharacter; + + /// + /// Restrict the caret to whole clusters, like Thai and Devanagari. Scripts + /// such as Arabic by default allow navigation between clusters. Others + /// like Thai always navigate across whole clusters. + /// + UINT32 restrictCaretToClusters : 1; + + /// + /// The language uses dividers between words, such as spaces between Latin + /// or the Ethiopic wordspace. + /// + /// Examples: Latin, Greek, Devanagari, Ethiopic + /// Excludes: Chinese, Korean, Thai. + /// + UINT32 usesWordDividers : 1; + + /// + /// The characters are discrete units from each other. This includes both + /// block scripts and clustered scripts. + /// + /// Examples: Latin, Greek, Cyrillic, Hebrew, Chinese, Thai + /// + UINT32 isDiscreteWriting : 1; + + /// + /// The language is a block script, expanding between characters. + /// + /// Examples: Chinese, Japanese, Korean, Bopomofo. + /// + UINT32 isBlockWriting : 1; + + /// + /// The language is justified within glyph clusters, not just between glyph + /// clusters. One such as the character sequence is Thai Lu and Sara Am + /// (U+E026, U+E033) which form a single cluster but still expand between + /// them. + /// + /// Examples: Thai, Lao, Khmer + /// + UINT32 isDistributedWithinCluster : 1; + + /// + /// The script's clusters are connected to each other (such as the + /// baseline-linked Devanagari), and no separation should be added + /// between characters. Note that cursively linked scripts like Arabic + /// are also connected (but not all connected scripts are + /// cursive). + /// + /// Examples: Devanagari, Arabic, Syriac, Bengali, Gurmukhi, Ogham + /// Excludes: Latin, Chinese, Thaana + /// + UINT32 isConnectedWriting : 1; + + /// + /// The script is naturally cursive (Arabic/Syriac), meaning it uses other + /// justification methods like kashida extension rather than intercharacter + /// spacing. Note that although other scripts like Latin and Japanese may + /// actually support handwritten cursive forms, they are not considered + /// cursive scripts. + /// + /// Examples: Arabic, Syriac, Mongolian + /// Excludes: Thaana, Devanagari, Latin, Chinese + /// + UINT32 isCursiveWriting : 1; + + UINT32 reserved : 25; +}; + + +/// +/// Justification information per glyph. +/// +struct DWRITE_JUSTIFICATION_OPPORTUNITY +{ + /// + /// Minimum amount of expansion to apply to the side of the glyph. + /// This may vary from 0 to infinity, typically being zero except + /// for kashida. + /// + FLOAT expansionMinimum; + + /// + /// Maximum amount of expansion to apply to the side of the glyph. + /// This may vary from 0 to infinity, being zero for fixed-size characters + /// and connected scripts, and non-zero for discrete scripts, and non-zero + /// for cursive scripts at expansion points. + /// + FLOAT expansionMaximum; + + /// + /// Maximum amount of compression to apply to the side of the glyph. + /// This may vary from 0 up to the glyph cluster size. + /// + FLOAT compressionMaximum; + + /// + /// Priority of this expansion point. Larger priorities are applied later, + /// while priority zero does nothing. + /// + UINT32 expansionPriority : 8; + + /// + /// Priority of this compression point. Larger priorities are applied later, + /// while priority zero does nothing. + /// + UINT32 compressionPriority : 8; + + /// + /// Allow this expansion point to use up any remaining slack space even + /// after all expansion priorities have been used up. + /// + UINT32 allowResidualExpansion : 1; + + /// + /// Allow this compression point to use up any remaining space even after + /// all compression priorities have been used up. + /// + UINT32 allowResidualCompression : 1; + + /// + /// Apply expansion/compression to the leading edge of the glyph. This will + /// be false for connected scripts, fixed-size characters, and diacritics. + /// It is generally false within a multi-glyph cluster, unless the script + /// allows expansion of glyphs within a cluster, like Thai. + /// + UINT32 applyToLeadingEdge : 1; + + /// + /// Apply expansion/compression to the trailing edge of the glyph. This will + /// be false for connected scripts, fixed-size characters, and diacritics. + /// It is generally false within a multi-glyph cluster, unless the script + /// allows expansion of glyphs within a cluster, like Thai. + /// + UINT32 applyToTrailingEdge : 1; + + UINT32 reserved : 12; +}; + + +interface IDWriteTextAnalysisSource1; +interface IDWriteTextAnalysisSink1; +interface IDWriteRenderingParams1; + +/// +/// The root factory interface for all DWrite objects. +/// +interface DWRITE_DECLARE_INTERFACE("30572f99-dac6-41db-a16e-0486307e606a") IDWriteFactory1 : public IDWriteFactory +{ + /// + /// Gets a font collection representing the set of end-user defined + /// custom fonts. + /// + /// Receives a pointer to the EUDC font + /// collection object, or NULL in case of failure. + /// If this parameter is nonzero, the + /// function performs an immediate check for changes to the set of + /// EUDC fonts. If this parameter is FALSE, the function will still + /// detect changes, but there may be some latency. For example, an + /// application might specify TRUE if it has itself just modified a + /// font and wants to be sure the font collection contains that font. + /// + /// + /// Standard HRESULT error code. Note that if no EUDC is set on the system, + /// the returned collection will be empty, meaning it will return success + /// but GetFontFamilyCount will be zero. + /// + /// + /// Querying via IDWriteFontCollection::FindFamilyName for a specific + /// family (like MS Gothic) will return the matching family-specific EUDC + /// font if one exists. Querying for "" will return the global EUDC font. + /// For example, if you were matching an EUDC character within a run of + /// the base font PMingLiu, you would retrieve the corresponding EUDC font + /// face using GetEudcFontCollection, then FindFamilyName with "PMingLiu", + /// followed by GetFontFamily and CreateFontFace. + /// + /// Be aware that eudcedit.exe can create placeholder empty glyphs that + /// have zero advance width and no glyph outline. Although they are present + /// in the font (HasCharacter returns true), you are best to ignore + /// these and continue on with font fallback in your layout if the metrics + /// for the glyph are zero. + /// + STDMETHOD(GetEudcFontCollection)( + _COM_Outptr_ IDWriteFontCollection** fontCollection, + BOOL checkForUpdates = FALSE + ) PURE; + + /// + /// Creates a rendering parameters object with the specified properties. + /// + /// The gamma value used for gamma correction, which must be greater than zero and cannot exceed 256. + /// The amount of contrast enhancement, zero or greater. + /// The amount of contrast enhancement to use for grayscale antialiasing, zero or greater. + /// The degree of ClearType level, from 0.0f (no ClearType) to 1.0f (full ClearType). + /// The geometry of a device pixel. + /// Method of rendering glyphs. In most cases, this should be DWRITE_RENDERING_MODE_DEFAULT to automatically use an appropriate mode. + /// Holds the newly created rendering parameters object, or NULL in case of failure. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateCustomRenderingParams)( + FLOAT gamma, + FLOAT enhancedContrast, + FLOAT enhancedContrastGrayscale, + FLOAT clearTypeLevel, + DWRITE_PIXEL_GEOMETRY pixelGeometry, + DWRITE_RENDERING_MODE renderingMode, + _COM_Outptr_ IDWriteRenderingParams1** renderingParams + ) PURE; + + using IDWriteFactory::CreateCustomRenderingParams; +}; + + +/// +/// The interface that represents an absolute reference to a font face. +/// It contains font face type, appropriate file references and face identification data. +/// Various font data such as metrics, names and glyph outlines is obtained from IDWriteFontFace. +/// +interface DWRITE_DECLARE_INTERFACE("a71efdb4-9fdb-4838-ad90-cfc3be8c3daf") IDWriteFontFace1 : public IDWriteFontFace +{ + /// + /// Gets common metrics for the font in design units. + /// These metrics are applicable to all the glyphs within a font, + /// and are used by applications for layout calculations. + /// + /// Metrics structure to fill in. + STDMETHOD_(void, GetMetrics)( + _Out_ DWRITE_FONT_METRICS1* fontMetrics + ) PURE; + + /// + /// Gets common metrics for the font in design units. + /// These metrics are applicable to all the glyphs within a font, + /// and are used by applications for layout calculations. + /// + /// Logical size of the font in DIP units. A DIP + /// ("device-independent pixel") equals 1/96 inch. + /// Number of physical pixels per DIP. For + /// example, if the DPI of the rendering surface is 96 this value is + /// 1.0f. If the DPI is 120, this value is 120.0f/96. + /// Optional transform applied to the glyphs and + /// their positions. This transform is applied after the scaling + /// specified by the font size and pixelsPerDip. + /// Font metrics structure to fill in. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetGdiCompatibleMetrics)( + FLOAT emSize, + FLOAT pixelsPerDip, + _In_opt_ DWRITE_MATRIX const* transform, + _Out_ DWRITE_FONT_METRICS1* fontMetrics + ) PURE; + + /// + /// Gets caret metrics for the font in design units. These are used by + /// text editors for drawing the correct caret placement/slant. + /// + /// Metrics structure to fill in. + STDMETHOD_(void, GetCaretMetrics)( + _Out_ DWRITE_CARET_METRICS* caretMetrics + ) PURE; + + /// + /// Returns the list of character ranges supported by the font, which is + /// useful for scenarios like character picking, glyph display, and + /// efficient font selection lookup. This is similar to GDI's + /// GetFontUnicodeRanges, except that it returns the full Unicode range, + /// not just 16-bit UCS-2. + /// + /// Maximum number of character ranges passed + /// in from the client. + /// Array of character ranges. + /// Actual number of character ranges, + /// regardless of the maximum count. + /// + /// These ranges are from the cmap, not the OS/2::ulCodePageRange1. + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetUnicodeRanges)( + UINT32 maxRangeCount, + _Out_writes_to_opt_(maxRangeCount, *actualRangeCount) DWRITE_UNICODE_RANGE* unicodeRanges, + _Out_ UINT32* actualRangeCount + ) PURE; + + /// + /// Returns true if the font is monospaced, meaning its characters are the + /// same fixed-pitch width (non-proportional). + /// + STDMETHOD_(BOOL, IsMonospacedFont)() PURE; + + /// + /// Returns the advances in design units for a sequences of glyphs. + /// + /// Number of glyphs to retrieve advances for. + /// Array of glyph id's to retrieve advances for. + /// Returned advances in font design units for + /// each glyph. + /// Retrieve the glyph's vertical advance height + /// rather than horizontal advance widths. + /// + /// This is equivalent to calling GetGlyphMetrics and using only the + /// advance width/height. + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetDesignGlyphAdvances)( + UINT32 glyphCount, + _In_reads_(glyphCount) UINT16 const* glyphIndices, + _Out_writes_(glyphCount) INT32* glyphAdvances, + BOOL isSideways = FALSE + ) PURE; + + /// + /// Returns the pixel-aligned advances for a sequences of glyphs, the same + /// as GetGdiCompatibleGlyphMetrics would return. + /// + /// Logical size of the font in DIP units. A DIP + /// ("device-independent pixel") equals 1/96 inch. + /// Number of physical pixels per DIP. For + /// example, if the DPI of the rendering surface is 96 this value is + /// 1.0f. If the DPI is 120, this value is 120.0f/96. + /// Optional transform applied to the glyphs and + /// their positions. This transform is applied after the scaling + /// specified by the font size and pixelsPerDip. + /// When FALSE, the metrics are the same as + /// GDI aliased text (DWRITE_MEASURING_MODE_GDI_CLASSIC). When TRUE, + /// the metrics are the same as those measured by GDI using a font + /// using CLEARTYPE_NATURAL_QUALITY (DWRITE_MEASURING_MODE_GDI_NATURAL). + /// Retrieve the glyph's vertical advances rather + /// than horizontal advances. + /// Total glyphs to retrieve adjustments for. + /// Array of glyph id's to retrieve advances. + /// Returned advances in font design units for + /// each glyph. + /// + /// This is equivalent to calling GetGdiCompatibleGlyphMetrics and using only + /// the advance width/height. Like GetGdiCompatibleGlyphMetrics, these are in + /// design units, meaning they must be scaled down by + /// DWRITE_FONT_METRICS::designUnitsPerEm. + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetGdiCompatibleGlyphAdvances)( + FLOAT emSize, + FLOAT pixelsPerDip, + _In_opt_ DWRITE_MATRIX const* transform, + BOOL useGdiNatural, + BOOL isSideways, + UINT32 glyphCount, + _In_reads_(glyphCount) UINT16 const* glyphIndices, + _Out_writes_(glyphCount) INT32* glyphAdvances + ) PURE; + + /// + /// Retrieves the kerning pair adjustments from the font's kern table. + /// + /// Number of glyphs to retrieve adjustments for. + /// Array of glyph id's to retrieve adjustments + /// for. + /// Returned advances in font design units for + /// each glyph. The last glyph adjustment is zero. + /// + /// This is not a direct replacement for GDI's character based + /// GetKerningPairs, but it serves the same role, without the client + /// needing to cache them locally. It also uses glyph id's directly + /// rather than UCS-2 characters (how the kern table actually stores + /// them) which avoids glyph collapse and ambiguity, such as the dash + /// and hyphen, or space and non-breaking space. + /// + /// + /// Newer fonts may have only GPOS kerning instead of the legacy pair + /// table kerning. Such fonts, like Gabriola, will only return 0's for + /// adjustments. This function does not virtualize and flatten these + /// GPOS entries into kerning pairs. + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetKerningPairAdjustments)( + UINT32 glyphCount, + _In_reads_(glyphCount) UINT16 const* glyphIndices, + _Out_writes_(glyphCount) INT32* glyphAdvanceAdjustments + ) PURE; + + /// + /// Returns whether or not the font supports pair-kerning. + /// + /// + /// If the font does not support pair table kerning, there is no need to + /// call GetKerningPairAdjustments (it would be all zeroes). + /// + /// + /// Whether the font supports kerning pairs. + /// + STDMETHOD_(BOOL, HasKerningPairs)() PURE; + + /// + /// Determines the recommended text rendering mode to be used based on the + /// font, size, world transform, and measuring mode. + /// + /// Logical font size in DIPs. + /// Number of pixels per logical inch in the horizontal direction. + /// Number of pixels per logical inch in the vertical direction. + /// Specifies the world transform. + /// Specifies the quality of the graphics system's outline rendering, + /// affects the size threshold above which outline rendering is used. + /// Specifies the method used to measure during text layout. For proper + /// glyph spacing, the function returns a rendering mode that is compatible with the specified + /// measuring mode. + /// Receives the recommended rendering mode. + /// + /// This method should be used to determine the actual rendering mode in cases where the rendering + /// mode of the rendering params object is DWRITE_RENDERING_MODE_DEFAULT. + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetRecommendedRenderingMode)( + FLOAT fontEmSize, + FLOAT dpiX, + FLOAT dpiY, + _In_opt_ DWRITE_MATRIX const* transform, + BOOL isSideways, + DWRITE_OUTLINE_THRESHOLD outlineThreshold, + DWRITE_MEASURING_MODE measuringMode, + _Out_ DWRITE_RENDERING_MODE* renderingMode + ) PURE; + + /// + /// Retrieves the vertical forms of the nominal glyphs retrieved from + /// GetGlyphIndices, using the font's 'vert' table. This is used in + /// CJK vertical layout so the correct characters are shown. + /// + /// Number of glyphs to retrieve. + /// Original glyph indices from cmap. + /// The vertical form of glyph indices. + /// + /// Call GetGlyphIndices to get the nominal glyph indices, followed by + /// calling this to remap the to the substituted forms, when the run + /// is sideways, and the font has vertical glyph variants. + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetVerticalGlyphVariants)( + UINT32 glyphCount, + _In_reads_(glyphCount) UINT16 const* nominalGlyphIndices, + _Out_writes_(glyphCount) UINT16* verticalGlyphIndices + ) PURE; + + /// + /// Returns whether or not the font has any vertical glyph variants. + /// + /// + /// For OpenType fonts, this will return true if the font contains a 'vert' + /// feature. + /// + /// + /// True if the font contains vertical glyph variants. + /// + STDMETHOD_(BOOL, HasVerticalGlyphVariants)() PURE; + + using IDWriteFontFace::GetMetrics; + using IDWriteFontFace::GetGdiCompatibleMetrics; + using IDWriteFontFace::GetRecommendedRenderingMode; +}; + + +/// +/// The IDWriteFont interface represents a physical font in a font collection. +/// +interface DWRITE_DECLARE_INTERFACE("acd16696-8c14-4f5d-877e-fe3fc1d32738") IDWriteFont1 : public IDWriteFont +{ + /// + /// Gets common metrics for the font in design units. + /// These metrics are applicable to all the glyphs within a font, + /// and are used by applications for layout calculations. + /// + /// Metrics structure to fill in. + STDMETHOD_(void, GetMetrics)( + _Out_ DWRITE_FONT_METRICS1* fontMetrics + ) PURE; + + using IDWriteFont::GetMetrics; + + /// + /// Gets the PANOSE values from the font, used for font selection and + /// matching. + /// + /// PANOSE structure to fill in. + /// + /// The function does not simulate these, such as substituting a weight or + /// proportion inferred on other values. If the font does not specify them, + /// they are all set to 'any' (0). + /// + STDMETHOD_(void, GetPanose)( + _Out_ DWRITE_PANOSE* panose + ) PURE; + + /// + /// Returns the list of character ranges supported by the font, which is + /// useful for scenarios like character picking, glyph display, and + /// efficient font selection lookup. This is similar to GDI's + /// GetFontUnicodeRanges, except that it returns the full Unicode range, + /// not just 16-bit UCS-2. + /// + /// Maximum number of character ranges passed + /// in from the client. + /// Array of character ranges. + /// Actual number of character ranges, + /// regardless of the maximum count. + /// + /// These ranges are from the cmap, not the OS/2::ulCodePageRange1. + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetUnicodeRanges)( + UINT32 maxRangeCount, + _Out_writes_to_opt_(maxRangeCount, *actualRangeCount) DWRITE_UNICODE_RANGE* unicodeRanges, + _Out_ UINT32* actualRangeCount + ) PURE; + + /// + /// Returns true if the font is monospaced, meaning its characters are the + /// same fixed-pitch width (non-proportional). + /// + STDMETHOD_(BOOL, IsMonospacedFont)() PURE; +}; + +/// +/// The interface that represents text rendering settings for glyph rasterization and filtering. +/// +interface DWRITE_DECLARE_INTERFACE("94413cf4-a6fc-4248-8b50-6674348fcad3") IDWriteRenderingParams1 : public IDWriteRenderingParams +{ + /// + /// Gets the amount of contrast enhancement to use for grayscale antialiasing. + /// Valid values are greater than or equal to zero. + /// + STDMETHOD_(FLOAT, GetGrayscaleEnhancedContrast)() PURE; +}; + +/// +/// Analyzes various text properties for complex script processing. +/// +interface DWRITE_DECLARE_INTERFACE("80DAD800-E21F-4E83-96CE-BFCCE500DB7C") IDWriteTextAnalyzer1 : public IDWriteTextAnalyzer +{ + /// + /// Applies spacing between characters, properly adjusting glyph clusters + /// and diacritics. + /// + /// The spacing before each character, in reading order. + /// The spacing after each character, in reading order. + /// The minimum advance of each character, + /// to prevent characters from becoming too thin or zero-width. This + /// must be zero or greater. + /// The length of the clustermap and original text. + /// The number of glyphs. + /// Mapping from character ranges to glyph ranges. + /// The advance width of each glyph. + /// The offset of the origin of each glyph. + /// Properties of each glyph, from GetGlyphs. + /// The new advance width of each glyph. + /// The new offset of the origin of each glyph. + /// + /// The input and output advances/offsets are allowed to alias the same array. + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(ApplyCharacterSpacing)( + FLOAT leadingSpacing, + FLOAT trailingSpacing, + FLOAT minimumAdvanceWidth, + UINT32 textLength, + UINT32 glyphCount, + _In_reads_(textLength) UINT16 const* clusterMap, + _In_reads_(glyphCount) FLOAT const* glyphAdvances, + _In_reads_(glyphCount) DWRITE_GLYPH_OFFSET const* glyphOffsets, + _In_reads_(glyphCount) DWRITE_SHAPING_GLYPH_PROPERTIES const* glyphProperties, + _Out_writes_(glyphCount) FLOAT* modifiedGlyphAdvances, + _Out_writes_(glyphCount) DWRITE_GLYPH_OFFSET* modifiedGlyphOffsets + ) PURE; + + /// + /// Retrieves the given baseline from the font. + /// + /// The font face to read. + /// The baseline of interest. + /// Whether the baseline is vertical or horizontal. + /// Simulate the baseline if it is missing in the font. + /// Script analysis result from AnalyzeScript. + /// The language of the run. + /// The baseline coordinate value in design units. + /// Whether the returned baseline exists in the font. + /// + /// If the baseline does not exist in the font, it is not considered an + /// error, but the function will return exists = false. You may then use + /// heuristics to calculate the missing base, or, if the flag + /// simulationAllowed is true, the function will compute a reasonable + /// approximation for you. + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetBaseline)( + _In_ IDWriteFontFace* fontFace, + DWRITE_BASELINE baseline, + BOOL isVertical, + BOOL isSimulationAllowed, + DWRITE_SCRIPT_ANALYSIS scriptAnalysis, + _In_opt_z_ WCHAR const* localeName, + _Out_ INT32* baselineCoordinate, + _Out_ BOOL* exists + ) PURE; + + /// + /// Analyzes a text range for script orientation, reading text and + /// attributes from the source and reporting results to the sink. + /// + /// Source object to analyze. + /// Starting position within the source object. + /// Length to analyze. + /// Callback object. + /// + /// Standard HRESULT error code. + /// + /// + /// All bidi analysis should be resolved before calling this. + /// + STDMETHOD(AnalyzeVerticalGlyphOrientation)( + _In_ IDWriteTextAnalysisSource1* analysisSource, + UINT32 textPosition, + UINT32 textLength, + _In_ IDWriteTextAnalysisSink1* analysisSink + ) PURE; + + /// + /// Returns 2x3 transform matrix for the respective angle to draw the + /// glyph run. + /// + /// The angle reported into + /// SetGlyphOrientation. + /// Whether the run's glyphs are sideways or not. + /// Returned transform. + /// + /// + /// Standard HRESULT error code. + /// + /// + /// The returned displacement is zero. + /// + STDMETHOD(GetGlyphOrientationTransform)( + DWRITE_GLYPH_ORIENTATION_ANGLE glyphOrientationAngle, + BOOL isSideways, + _Out_ DWRITE_MATRIX* transform + ) PURE; + + /// + /// Returns the properties for a given script. + /// + /// The script for a run of text returned + /// from IDWriteTextAnalyzer::AnalyzeScript. + /// Information for the script. + /// + /// Returns properties for the given script. If the script is invalid, + /// it returns generic properties for the unknown script and E_INVALIDARG. + /// + STDMETHOD(GetScriptProperties)( + DWRITE_SCRIPT_ANALYSIS scriptAnalysis, + _Out_ DWRITE_SCRIPT_PROPERTIES* scriptProperties + ) PURE; + + /// + /// Determines the complexity of text, and whether or not full script + /// shaping needs to be called (GetGlyphs). + /// + /// The font face to read. + /// Length of the text to check. + /// The text to check for complexity. This string + /// may be UTF-16, but any supplementary characters will be considered + /// complex. + /// If true, the text is simple, and the + /// glyphIndices array will already have the nominal glyphs for you. + /// Otherwise you need to call GetGlyphs to properly shape complex + /// scripts and OpenType features. + /// + /// The length read of the text run with the + /// same complexity, simple or complex. You may call again from that + /// point onward. + /// Optional glyph indices for the text. If the + /// function returned that the text was simple, you already have the + /// glyphs you need. Otherwise the glyph indices are not meaningful, + /// and you should call shaping instead. + /// + /// Text is not simple if the characters are part of a script that has + /// complex shaping requirements, require bidi analysis, combine with + /// other characters, reside in the supplementary planes, or have glyphs + /// which participate in standard OpenType features. The length returned + /// will not split combining marks from their base characters. + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetTextComplexity)( + _In_reads_(textLength) WCHAR const* textString, + UINT32 textLength, + _In_ IDWriteFontFace* fontFace, + _Out_ BOOL* isTextSimple, + _Out_range_(0, textLength) UINT32* textLengthRead, + _Out_writes_to_opt_(textLength, *textLengthRead) UINT16* glyphIndices + ) PURE; + + /// + /// Retrieves justification opportunity information for each of the glyphs + /// given the text and shaping glyph properties. + /// + /// Font face that was used for shaping. This is + /// mainly important for returning correct results of the kashida + /// width. + /// Font em size used for the glyph run. + /// Script of the text from the itemizer. + /// Length of the text. + /// Number of glyphs. + /// Characters used to produce the glyphs. + /// Clustermap produced from shaping. + /// Glyph properties produced from shaping. + /// Receives information for the + /// allowed justification expansion/compression for each glyph. + /// + /// This function is called per-run, after shaping is done via GetGlyphs(). + /// Note this function only supports natural metrics (DWRITE_MEASURING_MODE_NATURAL). + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetJustificationOpportunities)( + _In_opt_ IDWriteFontFace* fontFace, + FLOAT fontEmSize, + DWRITE_SCRIPT_ANALYSIS scriptAnalysis, + UINT32 textLength, + UINT32 glyphCount, + _In_reads_(textLength) WCHAR const* textString, + _In_reads_(textLength) UINT16 const* clusterMap, + _In_reads_(glyphCount) DWRITE_SHAPING_GLYPH_PROPERTIES const* glyphProperties, + _Out_writes_(glyphCount) DWRITE_JUSTIFICATION_OPPORTUNITY* justificationOpportunities + ) PURE; + + /// + /// Justifies an array of glyph advances to fit the line width. + /// + /// Width of the line. + /// Number of glyphs. + /// Opportunities per glyph. Call + /// GetJustificationOpportunities() to get suitable opportunities + /// according to script. + /// Original glyph advances from shaping. + /// Original glyph offsets from shaping. + /// Justified glyph advances. + /// Justified glyph offsets. + /// + /// This is called after all the opportunities have been collected, and it + /// spans across the entire line. The input and output arrays are allowed + /// to alias each other, permitting in-place update. + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(JustifyGlyphAdvances)( + FLOAT lineWidth, + UINT32 glyphCount, + _In_reads_(glyphCount) DWRITE_JUSTIFICATION_OPPORTUNITY const* justificationOpportunities, + _In_reads_(glyphCount) FLOAT const* glyphAdvances, + _In_reads_(glyphCount) DWRITE_GLYPH_OFFSET const* glyphOffsets, + _Out_writes_(glyphCount) FLOAT* justifiedGlyphAdvances, + _Out_writes_opt_(glyphCount) DWRITE_GLYPH_OFFSET* justifiedGlyphOffsets + ) PURE; + + /// + /// Fills in new glyphs for complex scripts where justification increased + /// the advances of glyphs, such as Arabic with kashida. + /// + /// Font face used for shaping. + /// Font em size used for the glyph run. + /// Script of the text from the itemizer. + /// Length of the text. + /// Number of glyphs. + /// Maximum number of output glyphs allocated + /// by caller. + /// Clustermap produced from shaping. + /// Original glyphs produced from shaping. + /// Original glyph advances produced from shaping. + /// Justified glyph advances from + /// JustifyGlyphAdvances(). + /// Justified glyph offsets from + /// JustifyGlyphAdvances(). + /// Properties of each glyph, from GetGlyphs. + /// The new glyph count written to the + /// modified arrays, or the needed glyph count if the size is not + /// large enough. + /// Updated clustermap. + /// Updated glyphs with new glyphs + /// inserted where needed. + /// Updated glyph advances. + /// Updated glyph offsets. + /// + /// This is called after the line has been justified, and it is per-run. + /// It only needs to be called if the script has a specific justification + /// character via GetScriptProperties, and it is mainly for cursive scripts + /// like Arabic. If maxGlyphCount is not large enough, the error + /// E_NOT_SUFFICIENT_BUFFER will be returned, with actualGlyphCount holding + /// the final/needed glyph count. + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetJustifiedGlyphs)( + _In_opt_ IDWriteFontFace* fontFace, + FLOAT fontEmSize, + DWRITE_SCRIPT_ANALYSIS scriptAnalysis, + UINT32 textLength, + UINT32 glyphCount, + UINT32 maxGlyphCount, + _In_reads_opt_(textLength) UINT16 const* clusterMap, + _In_reads_(glyphCount) UINT16 const* glyphIndices, + _In_reads_(glyphCount) FLOAT const* glyphAdvances, + _In_reads_(glyphCount) FLOAT const* justifiedGlyphAdvances, + _In_reads_(glyphCount) DWRITE_GLYPH_OFFSET const* justifiedGlyphOffsets, + _In_reads_(glyphCount) DWRITE_SHAPING_GLYPH_PROPERTIES const* glyphProperties, + _Out_range_(glyphCount, maxGlyphCount) UINT32* actualGlyphCount, + _Out_writes_opt_(textLength) UINT16* modifiedClusterMap, + _Out_writes_to_(maxGlyphCount, *actualGlyphCount) UINT16* modifiedGlyphIndices, + _Out_writes_to_(maxGlyphCount, *actualGlyphCount) FLOAT* modifiedGlyphAdvances, + _Out_writes_to_(maxGlyphCount, *actualGlyphCount) DWRITE_GLYPH_OFFSET* modifiedGlyphOffsets + ) PURE; +}; + + +/// +/// The interface implemented by the client to provide needed information to +/// the text analyzer, such as the text and associated text properties. +/// If any of these callbacks returns an error, the analysis functions will +/// stop prematurely and return a callback error. +/// +interface DWRITE_DECLARE_INTERFACE("639CFAD8-0FB4-4B21-A58A-067920120009") IDWriteTextAnalysisSource1 : public IDWriteTextAnalysisSource +{ + /// + /// The text analyzer calls back to this to get the desired glyph + /// orientation and resolved bidi level, which it uses along with the + /// script properties of the text to determine the actual orientation of + /// each character, which it reports back to the client via the sink + /// SetGlyphOrientation method. + /// + /// First position of the piece to obtain. All + /// positions are in UTF-16 code-units, not whole characters, which + /// matters when supplementary characters are used. + /// Number of UTF-16 units of the retrieved chunk. + /// The returned length is not the length of the block, but the length + /// remaining in the block, from the given position until its end. + /// So querying for a position that is 75 positions into a 100 + /// postition block would return 25. + /// The type of glyph orientation the + /// client wants for this range, up to the returned text length. + /// The bidi level for this range up to + /// the returned text length, which comes from an earlier + /// bidirectional analysis. + /// + /// Standard HRESULT error code. Returning an error will abort the + /// analysis. + /// + STDMETHOD(GetVerticalGlyphOrientation)( + UINT32 textPosition, + _Out_ UINT32* textLength, + _Out_ DWRITE_VERTICAL_GLYPH_ORIENTATION* glyphOrientation, + _Out_ UINT8* bidiLevel + ) PURE; +}; + + +/// +/// The interface implemented by the client to receive the +/// output of the text analyzers. +/// +interface DWRITE_DECLARE_INTERFACE("B0D941A0-85E7-4D8B-9FD3-5CED9934482A") IDWriteTextAnalysisSink1 : public IDWriteTextAnalysisSink +{ + /// + /// The text analyzer calls back to this to report the actual orientation + /// of each character for shaping and drawing. + /// + /// Starting position to report from. + /// Number of UTF-16 units of the reported range. + /// Angle of the glyphs within the text + /// range (pass to GetGlyphOrientationTransform to get the world + /// relative transform). + /// The adjusted bidi level to be used by + /// the client layout for reordering runs. This will differ from the + /// resolved bidi level retrieved from the source for cases such as + /// Arabic stacked top-to-bottom, where the glyphs are still shaped + /// as RTL, but the runs are TTB along with any CJK or Latin. + /// Whether the glyphs are rotated on their side, + /// which is the default case for CJK and the case stacked Latin + /// Whether the script should be shaped as + /// right-to-left. For Arabic stacked top-to-bottom, even when the + /// adjusted bidi level is coerced to an even level, this will still + /// be true. + /// + /// A successful code or error code to abort analysis. + /// + STDMETHOD(SetGlyphOrientation)( + UINT32 textPosition, + UINT32 textLength, + DWRITE_GLYPH_ORIENTATION_ANGLE glyphOrientationAngle, + UINT8 adjustedBidiLevel, + BOOL isSideways, + BOOL isRightToLeft + ) PURE; +}; + + +/// +/// The IDWriteTextLayout1 interface represents a block of text after it has +/// been fully analyzed and formatted. +/// +/// All coordinates are in device independent pixels (DIPs). +/// +interface DWRITE_DECLARE_INTERFACE("9064D822-80A7-465C-A986-DF65F78B8FEB") IDWriteTextLayout1 : public IDWriteTextLayout +{ + /// + /// Enables/disables pair-kerning on the given range. + /// + /// The Boolean flag indicates whether text is pair-kerned. + /// Text range to which this change applies. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetPairKerning)( + BOOL isPairKerningEnabled, + DWRITE_TEXT_RANGE textRange + ) PURE; + + /// + /// Get whether or not pair-kerning is enabled at given position. + /// + /// The current text position. + /// The Boolean flag indicates whether text is pair-kerned. + /// The position range of the current format. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetPairKerning)( + UINT32 currentPosition, + _Out_ BOOL* isPairKerningEnabled, + _Out_opt_ DWRITE_TEXT_RANGE* textRange = NULL + ) PURE; + + /// + /// Sets the spacing between characters. + /// + /// The spacing before each character, in reading order. + /// The spacing after each character, in reading order. + /// The minimum advance of each character, + /// to prevent characters from becoming too thin or zero-width. This + /// must be zero or greater. + /// Text range to which this change applies. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetCharacterSpacing)( + FLOAT leadingSpacing, + FLOAT trailingSpacing, + FLOAT minimumAdvanceWidth, + DWRITE_TEXT_RANGE textRange + ) PURE; + + /// + /// Gets the spacing between characters. + /// + /// The current text position. + /// The spacing before each character, in reading order. + /// The spacing after each character, in reading order. + /// The minimum advance of each character, + /// to prevent characters from becoming too thin or zero-width. This + /// must be zero or greater. + /// The position range of the current format. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetCharacterSpacing)( + UINT32 currentPosition, + _Out_ FLOAT* leadingSpacing, + _Out_ FLOAT* trailingSpacing, + _Out_ FLOAT* minimumAdvanceWidth, + _Out_opt_ DWRITE_TEXT_RANGE* textRange = NULL + ) PURE; +}; + +/// +/// Represents the type of antialiasing to use for text when the rendering mode calls for +/// antialiasing. +/// +enum DWRITE_TEXT_ANTIALIAS_MODE +{ + /// + /// ClearType antialiasing computes coverage independently for the red, green, and blue + /// color elements of each pixel. This allows for more detail than conventional antialiasing. + /// However, because there is no one alpha value for each pixel, ClearType is not suitable + /// rendering text onto a transparent intermediate bitmap. + /// + DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE, + + /// + /// Grayscale antialiasing computes one coverage value for each pixel. Because the alpha + /// value of each pixel is well-defined, text can be rendered onto a transparent bitmap, + /// which can then be composited with other content. Note that grayscale rendering with + /// IDWriteBitmapRenderTarget1 uses premultiplied alpha. + /// + DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE +}; + +/// +/// Encapsulates a 32-bit device independent bitmap and device context, which can be used for rendering glyphs. +/// +interface DWRITE_DECLARE_INTERFACE("791e8298-3ef3-4230-9880-c9bdecc42064") IDWriteBitmapRenderTarget1 : public IDWriteBitmapRenderTarget +{ + /// + /// Gets the current text antialiasing mode of the bitmap render target. + /// + /// + /// Returns the antialiasing mode. + /// + STDMETHOD_(DWRITE_TEXT_ANTIALIAS_MODE, GetTextAntialiasMode)() PURE; + + /// + /// Sets the current text antialiasing mode of the bitmap render target. + /// + /// + /// Returns S_OK if successful, or E_INVALIDARG if the argument is not valid. + /// + /// + /// The antialiasing mode of a newly-created bitmap render target defaults to + /// DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE. An application can change the antialiasing + /// mode by calling SetTextAntialiasMode. For example, an application might specify + /// grayscale antialiasing when rendering text onto a transparent bitmap. + /// + STDMETHOD(SetTextAntialiasMode)( + DWRITE_TEXT_ANTIALIAS_MODE antialiasMode + ) PURE; +}; + +#endif /* DWRITE_1_H_INCLUDED */ diff --git a/opennurbs/Include/dwrite_2_x32.h b/opennurbs/Include/dwrite_2_x32.h new file mode 100644 index 0000000..a04e67e --- /dev/null +++ b/opennurbs/Include/dwrite_2_x32.h @@ -0,0 +1,976 @@ +//+-------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Abstract: +// DirectX Typography Services public API definitions. +// +//---------------------------------------------------------------------------- + +#ifndef DWRITE_2_H_INCLUDED +#define DWRITE_2_H_INCLUDED + +#pragma once + +//#include +#include "C:\EgtDev\Extern\dwrite_1.h" + + +interface IDWriteFontFallback; + + +/// +/// How to align glyphs to the margin. +/// +enum DWRITE_OPTICAL_ALIGNMENT +{ + /// + /// Align to the default metrics of the glyph. + /// + DWRITE_OPTICAL_ALIGNMENT_NONE, + + /// + /// Align glyphs to the margins. Without this, some small whitespace + /// may be present between the text and the margin from the glyph's side + /// bearing values. Note that glyphs may still overhang outside the + /// margin, such as flourishes or italic slants. + /// + DWRITE_OPTICAL_ALIGNMENT_NO_SIDE_BEARINGS, +}; + + +/// +/// Whether to enable grid-fitting of glyph outlines (a.k.a. hinting). +/// +enum DWRITE_GRID_FIT_MODE +{ + /// + /// Choose grid fitting base on the font's gasp table information. + /// + DWRITE_GRID_FIT_MODE_DEFAULT, + + /// + /// Always disable grid fitting, using the ideal glyph outlines. + /// + DWRITE_GRID_FIT_MODE_DISABLED, + + /// + /// Enable grid fitting, adjusting glyph outlines for device pixel display. + /// + DWRITE_GRID_FIT_MODE_ENABLED +}; + + +/// +/// Overall metrics associated with text after layout. +/// All coordinates are in device independent pixels (DIPs). +/// +struct DWRITE_TEXT_METRICS1 : DWRITE_TEXT_METRICS +{ + /// + /// The height of the formatted text taking into account the + /// trailing whitespace at the end of each line, which will + /// matter for vertical reading directions. + /// + FLOAT heightIncludingTrailingWhitespace; +}; + + +/// +/// The text renderer interface represents a set of application-defined +/// callbacks that perform rendering of text, inline objects, and decorations +/// such as underlines. +/// +interface DWRITE_DECLARE_INTERFACE("D3E0E934-22A0-427E-AAE4-7D9574B59DB1") IDWriteTextRenderer1 : public IDWriteTextRenderer +{ + /// + /// IDWriteTextLayout::Draw calls this function to instruct the client to + /// render a run of glyphs. + /// + /// The context passed to + /// IDWriteTextLayout::Draw. + /// X-coordinate of the baseline. + /// Y-coordinate of the baseline. + /// Orientation of the glyph run. + /// Specifies measuring method for glyphs in + /// the run. Renderer implementations may choose different rendering + /// modes for given measuring methods, but best results are seen when + /// the rendering mode matches the corresponding measuring mode: + /// DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL for DWRITE_MEASURING_MODE_NATURAL + /// DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC for DWRITE_MEASURING_MODE_GDI_CLASSIC + /// DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL for DWRITE_MEASURING_MODE_GDI_NATURAL + /// + /// The glyph run to draw. + /// Properties of the characters + /// associated with this run. + /// The drawing effect set in + /// IDWriteTextLayout::SetDrawingEffect. + /// + /// Standard HRESULT error code. + /// + /// + /// If a non-identity orientation is passed, the glyph run should be + /// rotated around the given baseline x and y coordinates. The function + /// IDWriteAnalyzer2::GetGlyphOrientationTransform will return the + /// necessary transform for you, which can be combined with any existing + /// world transform on the drawing context. + /// + STDMETHOD(DrawGlyphRun)( + _In_opt_ void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + DWRITE_GLYPH_ORIENTATION_ANGLE orientationAngle, + DWRITE_MEASURING_MODE measuringMode, + _In_ DWRITE_GLYPH_RUN const* glyphRun, + _In_ DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, + _In_opt_ IUnknown* clientDrawingEffect + ) PURE; + + /// + /// IDWriteTextLayout::Draw calls this function to instruct the client to draw + /// an underline. + /// + /// The context passed to + /// IDWriteTextLayout::Draw. + /// X-coordinate of the baseline. + /// Y-coordinate of the baseline. + /// Orientation of the underline. + /// Underline logical information. + /// The drawing effect set in + /// IDWriteTextLayout::SetDrawingEffect. + /// + /// Standard HRESULT error code. + /// + /// + /// A single underline can be broken into multiple calls, depending on + /// how the formatting changes attributes. If font sizes/styles change + /// within an underline, the thickness and offset will be averaged + /// weighted according to characters. + /// + /// To get the correct top coordinate of the underline rect, add + /// underline::offset to the baseline's Y. Otherwise the underline will + /// be immediately under the text. The x coordinate will always be passed + /// as the left side, regardless of text directionality. This simplifies + /// drawing and reduces the problem of round-off that could potentially + /// cause gaps or a double stamped alpha blend. To avoid alpha overlap, + /// round the end points to the nearest device pixel. + /// + STDMETHOD(DrawUnderline)( + _In_opt_ void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + DWRITE_GLYPH_ORIENTATION_ANGLE orientationAngle, + _In_ DWRITE_UNDERLINE const* underline, + _In_opt_ IUnknown* clientDrawingEffect + ) PURE; + + /// + /// IDWriteTextLayout::Draw calls this function to instruct the client to draw + /// a strikethrough. + /// + /// The context passed to + /// IDWriteTextLayout::Draw. + /// X-coordinate of the baseline. + /// Y-coordinate of the baseline. + /// Orientation of the strikethrough. + /// Strikethrough logical information. + /// The drawing effect set in + /// IDWriteTextLayout::SetDrawingEffect. + /// + /// Standard HRESULT error code. + /// + /// + /// A single strikethrough can be broken into multiple calls, depending on + /// how the formatting changes attributes. Strikethrough is not averaged + /// across font sizes/styles changes. + /// To get the correct top coordinate of the strikethrough rect, + /// add strikethrough::offset to the baseline's Y. + /// Like underlines, the x coordinate will always be passed as the left side, + /// regardless of text directionality. + /// + STDMETHOD(DrawStrikethrough)( + _In_opt_ void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + DWRITE_GLYPH_ORIENTATION_ANGLE orientationAngle, + _In_ DWRITE_STRIKETHROUGH const* strikethrough, + _In_opt_ IUnknown* clientDrawingEffect + ) PURE; + + /// + /// IDWriteTextLayout::Draw calls this application callback when it needs to + /// draw an inline object. + /// + /// The context passed to + /// IDWriteTextLayout::Draw. + /// X-coordinate at the top-left corner of the + /// inline object. + /// Y-coordinate at the top-left corner of the + /// inline object. + /// Orientation of the inline object. + /// The object set using IDWriteTextLayout::SetInlineObject. + /// The object should be drawn on its side. + /// The object is in an right-to-left context + /// and should be drawn flipped. + /// The drawing effect set in + /// IDWriteTextLayout::SetDrawingEffect. + /// + /// Standard HRESULT error code. + /// + /// + /// The right-to-left flag is a hint to draw the appropriate visual for + /// that reading direction. For example, it would look strange to draw an + /// arrow pointing to the right to indicate a submenu. The sideways flag + /// similarly hints that the object is drawn in a different orientation. + /// If a non-identity orientation is passed, the top left of the inline + /// object should be rotated around the given x and y coordinates. + /// IDWriteAnalyzer2::GetGlyphOrientationTransform returns the necessary + /// transform for this. + /// + STDMETHOD(DrawInlineObject)( + _In_opt_ void* clientDrawingContext, + FLOAT originX, + FLOAT originY, + DWRITE_GLYPH_ORIENTATION_ANGLE orientationAngle, + _In_ IDWriteInlineObject* inlineObject, + BOOL isSideways, + BOOL isRightToLeft, + _In_opt_ IUnknown* clientDrawingEffect + ) PURE; + + using IDWriteTextRenderer::DrawGlyphRun; + using IDWriteTextRenderer::DrawUnderline; + using IDWriteTextRenderer::DrawStrikethrough; + using IDWriteTextRenderer::DrawInlineObject; +}; + + +/// +/// The format of text used for text layout. +/// +/// +/// This object may not be thread-safe and it may carry the state of text format change. +/// +interface DWRITE_DECLARE_INTERFACE("5F174B49-0D8B-4CFB-8BCA-F1CCE9D06C67") IDWriteTextFormat1 : public IDWriteTextFormat +{ + /// + /// Set the preferred orientation of glyphs when using a vertical reading direction. + /// + /// Preferred glyph orientation. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetVerticalGlyphOrientation)( + DWRITE_VERTICAL_GLYPH_ORIENTATION glyphOrientation + ) PURE; + + /// + /// Get the preferred orientation of glyphs when using a vertical reading + /// direction. + /// + STDMETHOD_(DWRITE_VERTICAL_GLYPH_ORIENTATION, GetVerticalGlyphOrientation)() PURE; + + /// + /// Set whether or not the last word on the last line is wrapped. + /// + /// Line wrapping option. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetLastLineWrapping)( + BOOL isLastLineWrappingEnabled + ) PURE; + + /// + /// Get whether or not the last word on the last line is wrapped. + /// + STDMETHOD_(BOOL, GetLastLineWrapping)() PURE; + + /// + /// Set how the glyphs align to the edges the margin. Default behavior is + /// to align glyphs using their default glyphs metrics which include side + /// bearings. + /// + /// Optical alignment option. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetOpticalAlignment)( + DWRITE_OPTICAL_ALIGNMENT opticalAlignment + ) PURE; + + /// + /// Get how the glyphs align to the edges the margin. + /// + STDMETHOD_(DWRITE_OPTICAL_ALIGNMENT, GetOpticalAlignment)() PURE; + + /// + /// Apply a custom font fallback onto layout. If none is specified, + /// layout uses the system fallback list. + /// + /// Custom font fallback created from + /// IDWriteFontFallbackBuilder::CreateFontFallback or from + /// IDWriteFactory2::GetSystemFontFallback. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetFontFallback)( + IDWriteFontFallback* fontFallback + ) PURE; + + /// + /// Get the current font fallback object. + /// + STDMETHOD(GetFontFallback)( + __out IDWriteFontFallback** fontFallback + ) PURE; +}; + + +/// +/// The text layout interface represents a block of text after it has +/// been fully analyzed and formatted. +/// +/// All coordinates are in device independent pixels (DIPs). +/// +interface DWRITE_DECLARE_INTERFACE("1093C18F-8D5E-43F0-B064-0917311B525E") IDWriteTextLayout2 : public IDWriteTextLayout1 +{ + /// + /// GetMetrics retrieves overall metrics for the formatted string. + /// + /// The returned metrics. + /// + /// Standard HRESULT error code. + /// + /// + /// Drawing effects like underline and strikethrough do not contribute + /// to the text size, which is essentially the sum of advance widths and + /// line heights. Additionally, visible swashes and other graphic + /// adornments may extend outside the returned width and height. + /// + STDMETHOD(GetMetrics)( + _Out_ DWRITE_TEXT_METRICS1* textMetrics + ) PURE; + + using IDWriteTextLayout::GetMetrics; + + /// + /// Set the preferred orientation of glyphs when using a vertical reading direction. + /// + /// Preferred glyph orientation. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetVerticalGlyphOrientation)( + DWRITE_VERTICAL_GLYPH_ORIENTATION glyphOrientation + ) PURE; + + /// + /// Get the preferred orientation of glyphs when using a vertical reading + /// direction. + /// + STDMETHOD_(DWRITE_VERTICAL_GLYPH_ORIENTATION, GetVerticalGlyphOrientation)() PURE; + + /// + /// Set whether or not the last word on the last line is wrapped. + /// + /// Line wrapping option. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetLastLineWrapping)( + BOOL isLastLineWrappingEnabled + ) PURE; + + /// + /// Get whether or not the last word on the last line is wrapped. + /// + STDMETHOD_(BOOL, GetLastLineWrapping)() PURE; + + /// + /// Set how the glyphs align to the edges the margin. Default behavior is + /// to align glyphs using their default glyphs metrics which include side + /// bearings. + /// + /// Optical alignment option. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetOpticalAlignment)( + DWRITE_OPTICAL_ALIGNMENT opticalAlignment + ) PURE; + + /// + /// Get how the glyphs align to the edges the margin. + /// + STDMETHOD_(DWRITE_OPTICAL_ALIGNMENT, GetOpticalAlignment)() PURE; + + /// + /// Apply a custom font fallback onto layout. If none is specified, + /// layout uses the system fallback list. + /// + /// Custom font fallback created from + /// IDWriteFontFallbackBuilder::CreateFontFallback or + /// IDWriteFactory2::GetSystemFontFallback. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetFontFallback)( + IDWriteFontFallback* fontFallback + ) PURE; + + /// + /// Get the current font fallback object. + /// + STDMETHOD(GetFontFallback)( + __out IDWriteFontFallback** fontFallback + ) PURE; +}; + + +/// +/// The text analyzer interface represents a set of application-defined +/// callbacks that perform rendering of text, inline objects, and decorations +/// such as underlines. +/// +interface DWRITE_DECLARE_INTERFACE("553A9FF3-5693-4DF7-B52B-74806F7F2EB9") IDWriteTextAnalyzer2 : public IDWriteTextAnalyzer1 +{ + /// + /// Returns 2x3 transform matrix for the respective angle to draw the + /// glyph run or other object. + /// + /// The angle reported to one of the application callbacks, + /// including IDWriteTextAnalysisSink1::SetGlyphOrientation and IDWriteTextRenderer1::Draw*. + /// Whether the run's glyphs are sideways or not. + /// X origin of the element, be it a glyph run or underline or other. + /// Y origin of the element, be it a glyph run or underline or other. + /// Returned transform. + /// + /// Standard HRESULT error code. + /// + /// + /// This rotates around the given origin x and y, returning a translation component + /// such that the glyph run, text decoration, or inline object is drawn with the + /// right orientation at the expected coordinate. + /// + STDMETHOD(GetGlyphOrientationTransform)( + DWRITE_GLYPH_ORIENTATION_ANGLE glyphOrientationAngle, + BOOL isSideways, + FLOAT originX, + FLOAT originY, + _Out_ DWRITE_MATRIX* transform + ) PURE; + + /// + /// Returns a list of typographic feature tags for the given script and language. + /// + /// The font face to get features from. + /// Script analysis result from AnalyzeScript. + /// The locale to use when selecting the feature, + /// such en-us or ja-jp. + /// Maximum tag count. + /// Actual tag count. If greater than + /// maxTagCount, E_NOT_SUFFICIENT_BUFFER is returned, and the call + /// should be retried with a larger buffer. + /// Feature tag list. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetTypographicFeatures)( + IDWriteFontFace* fontFace, + DWRITE_SCRIPT_ANALYSIS scriptAnalysis, + _In_opt_z_ WCHAR const* localeName, + UINT32 maxTagCount, + _Out_ UINT32* actualTagCount, + _Out_writes_(maxTagCount) DWRITE_FONT_FEATURE_TAG* tags + ) PURE; + + /// + /// Returns an array of which glyphs are affected by a given feature. + /// + /// The font face to read glyph information from. + /// Script analysis result from AnalyzeScript. + /// The locale to use when selecting the feature, + /// such en-us or ja-jp. + /// OpenType feature name to use, which may be one + /// of the DWRITE_FONT_FEATURE_TAG values or a custom feature using + /// DWRITE_MAKE_OPENTYPE_TAG. + /// Number of glyph indices to check. + /// Glyph indices to check for feature application. + /// Output of which glyphs are affected by the + /// feature, where for each glyph affected, the respective array index + /// will be 1. The result is returned per-glyph without regard to + /// neighboring context of adjacent glyphs. + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CheckTypographicFeature)( + IDWriteFontFace* fontFace, + DWRITE_SCRIPT_ANALYSIS scriptAnalysis, + _In_opt_z_ WCHAR const* localeName, + DWRITE_FONT_FEATURE_TAG featureTag, + UINT32 glyphCount, + _In_reads_(glyphCount) UINT16 const* glyphIndices, + _Out_writes_(glyphCount) UINT8* featureApplies + ) PURE; + + using IDWriteTextAnalyzer1::GetGlyphOrientationTransform; +}; + + +/// +/// A font fallback definition used for mapping characters to fonts capable of +/// supporting them. +/// +interface DWRITE_DECLARE_INTERFACE("EFA008F9-F7A1-48BF-B05C-F224713CC0FF") IDWriteFontFallback : public IUnknown +{ + /// + /// Determines an appropriate font to use to render the range of text. + /// + /// The text source implementation holds the text and + /// locale. + /// Length of the text to analyze. + /// Default font collection to use. + /// Family name of the base font. If you pass + /// null, no matching will be done against the family. + /// Desired weight. + /// Desired style. + /// Desired stretch. + /// Length of text mapped to the mapped font. + /// This will always be less or equal to the input text length and + /// greater than zero (if the text length is non-zero) so that the + /// caller advances at least one character each call. + /// The font that should be used to render the + /// first mappedLength characters of the text. If it returns NULL, + /// then no known font can render the text, and mappedLength is the + /// number of unsupported characters to skip. + /// Scale factor to multiply the em size of the + /// returned font by. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(MapCharacters)( + IDWriteTextAnalysisSource* analysisSource, + UINT32 textPosition, + UINT32 textLength, + _In_opt_ IDWriteFontCollection* baseFontCollection, + _In_opt_z_ wchar_t const* baseFamilyName, + DWRITE_FONT_WEIGHT baseWeight, + DWRITE_FONT_STYLE baseStyle, + DWRITE_FONT_STRETCH baseStretch, + _Out_range_(0, textLength) UINT32* mappedLength, + _COM_Outptr_result_maybenull_ IDWriteFont** mappedFont, + _Out_ FLOAT* scale + ) PURE; +}; + + +/// +/// Builder used to create a font fallback definition by appending a series of +/// fallback mappings, followed by a creation call. +/// +/// +/// This object may not be thread-safe. +/// +interface DWRITE_DECLARE_INTERFACE("FD882D06-8ABA-4FB8-B849-8BE8B73E14DE") IDWriteFontFallbackBuilder : public IUnknown +{ + /// + /// Appends a single mapping to the list. Call this once for each additional mapping. + /// + /// Unicode ranges that apply to this mapping. + /// Number of Unicode ranges. + /// Locale of the context (e.g. document locale). + /// Base family name to match against, if applicable. + /// Explicit font collection for this mapping (optional). + /// List of target family name strings. + /// Number of target family names. + /// Scale factor to multiply the result target font by. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(AddMapping)( + _In_reads_(rangesCount) DWRITE_UNICODE_RANGE const* ranges, + UINT32 rangesCount, + _In_reads_(targetFamilyNamesCount) WCHAR const** targetFamilyNames, + UINT32 targetFamilyNamesCount, + _In_opt_ IDWriteFontCollection* fontCollection = NULL, + _In_opt_z_ WCHAR const* localeName = NULL, + _In_opt_z_ WCHAR const* baseFamilyName = NULL, + FLOAT scale = 1.0f + ) PURE; + + /// + /// Appends all the mappings from an existing font fallback object. + /// + /// Font fallback to read mappings from. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(AddMappings)( + IDWriteFontFallback* fontFallback + ) PURE; + + /// + /// Creates the finalized fallback object from the mappings added. + /// + /// Created fallback list. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateFontFallback)( + _COM_Outptr_ IDWriteFontFallback** fontFallback + ) PURE; +}; + +/// +/// DWRITE_COLOR_F +/// +#ifndef D3DCOLORVALUE_DEFINED + +typedef struct _D3DCOLORVALUE { + union { + FLOAT r; + FLOAT dvR; + }; + union { + FLOAT g; + FLOAT dvG; + }; + union { + FLOAT b; + FLOAT dvB; + }; + union { + FLOAT a; + FLOAT dvA; + }; +} D3DCOLORVALUE; + +#define D3DCOLORVALUE_DEFINED +#endif // D3DCOLORVALUE_DEFINED + +typedef D3DCOLORVALUE DWRITE_COLOR_F; + +/// +/// The IDWriteFont interface represents a physical font in a font collection. +/// +interface DWRITE_DECLARE_INTERFACE("29748ed6-8c9c-4a6a-be0b-d912e8538944") IDWriteFont2 : public IDWriteFont1 +{ + /// + /// Returns TRUE if the font contains tables that can provide color information + /// (including COLR, CPAL, SVG, CBDT, sbix tables), or FALSE if not. Note that + /// TRUE is returned even in the case when the font tables contain only grayscale + /// images. + /// + STDMETHOD_(BOOL, IsColorFont)() PURE; +}; + +/// +/// The interface that represents an absolute reference to a font face. +/// It contains font face type, appropriate file references and face identification data. +/// Various font data such as metrics, names and glyph outlines is obtained from IDWriteFontFace. +/// +interface DWRITE_DECLARE_INTERFACE("d8b768ff-64bc-4e66-982b-ec8e87f693f7") IDWriteFontFace2 : public IDWriteFontFace1 +{ + /// + /// Returns TRUE if the font contains tables that can provide color information + /// (including COLR, CPAL, SVG, CBDT, sbix tables), or FALSE if not. Note that + /// TRUE is returned even in the case when the font tables contain only grayscale + /// images. + /// + STDMETHOD_(BOOL, IsColorFont)() PURE; + + /// + /// Returns the number of color palettes defined by the font. The return + /// value is zero if the font has no color information. Color fonts must + /// have at least one palette, with palette index zero being the default. + /// + STDMETHOD_(UINT32, GetColorPaletteCount)() PURE; + + /// + /// Returns the number of entries in each color palette. All color palettes + /// in a font have the same number of palette entries. The return value is + /// zero if the font has no color information. + /// + STDMETHOD_(UINT32, GetPaletteEntryCount)() PURE; + + /// + /// Reads color values from the font's color palette. + /// + /// Zero-based index of the color palette. If the + /// font does not have a palette with the specified index, the method returns + /// DWRITE_E_NOCOLOR. + /// Zero-based index of the first palette entry + /// to read. + /// Number of palette entries to read. + /// Array that receives the color values. + /// + /// Standard HRESULT error code. + /// The return value is E_INVALIDARG if firstEntryIndex + entryCount is greater + /// than the actual number of palette entries as returned by GetPaletteEntryCount. + /// The return value is DWRITE_E_NOCOLOR if the font does not have a palette + /// with the specified palette index. + /// + STDMETHOD(GetPaletteEntries)( + UINT32 colorPaletteIndex, + UINT32 firstEntryIndex, + UINT32 entryCount, + _Out_writes_(entryCount) DWRITE_COLOR_F* paletteEntries + ) PURE; + + /// + /// Determines the recommended text rendering and grid-fit mode to be used based on the + /// font, size, world transform, and measuring mode. + /// + /// Logical font size in DIPs. + /// Number of pixels per logical inch in the horizontal direction. + /// Number of pixels per logical inch in the vertical direction. + /// Specifies the world transform. + /// Specifies the quality of the graphics system's outline rendering, + /// affects the size threshold above which outline rendering is used. + /// Specifies the method used to measure during text layout. For proper + /// glyph spacing, the function returns a rendering mode that is compatible with the specified + /// measuring mode. + /// Rendering parameters object. This parameter is necessary in case the rendering parameters + /// object overrides the rendering mode. + /// Receives the recommended rendering mode. + /// Receives the recommended grid-fit mode. + /// + /// This method should be used to determine the actual rendering mode in cases where the rendering + /// mode of the rendering params object is DWRITE_RENDERING_MODE_DEFAULT, and the actual grid-fit + /// mode when the rendering params object is DWRITE_GRID_FIT_MODE_DEFAULT. + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetRecommendedRenderingMode)( + FLOAT fontEmSize, + FLOAT dpiX, + FLOAT dpiY, + _In_opt_ DWRITE_MATRIX const* transform, + BOOL isSideways, + DWRITE_OUTLINE_THRESHOLD outlineThreshold, + DWRITE_MEASURING_MODE measuringMode, + _In_opt_ IDWriteRenderingParams* renderingParams, + _Out_ DWRITE_RENDERING_MODE* renderingMode, + _Out_ DWRITE_GRID_FIT_MODE* gridFitMode + ) PURE; + + using IDWriteFontFace1::GetRecommendedRenderingMode; +}; + +/// +/// Represents a color glyph run. The IDWriteFactory2::TranslateColorGlyphRun +/// method returns an ordered collection of color glyph runs, which can be +/// layered on top of each other to produce a color representation of the +/// given base glyph run. +/// +struct DWRITE_COLOR_GLYPH_RUN +{ + /// + /// Glyph run to render. + /// + DWRITE_GLYPH_RUN glyphRun; + + /// + /// Optional glyph run description. + /// + _Maybenull_ DWRITE_GLYPH_RUN_DESCRIPTION* glyphRunDescription; + + /// + /// Location at which to draw this glyph run. + /// + FLOAT baselineOriginX; + FLOAT baselineOriginY; + + /// + /// Color to use for this layer, if any. This is the same color that + /// IDWriteFontFace2::GetPaletteEntries would return for the current + /// palette index if the paletteIndex member is less than 0xFFFF. If + /// the paletteIndex member is 0xFFFF then there is no associated + /// palette entry, this member is set to { 0, 0, 0, 0 }, and the client + /// should use the current foreground brush. + /// + DWRITE_COLOR_F runColor; + + /// + /// Zero-based index of this layer's color entry in the current color + /// palette, or 0xFFFF if this layer is to be rendered using + /// the current foreground brush. + /// + UINT16 paletteIndex; +}; + +/// +/// Enumerator for an ordered collection of color glyph runs. +/// +interface DWRITE_DECLARE_INTERFACE("d31fbe17-f157-41a2-8d24-cb779e0560e8") IDWriteColorGlyphRunEnumerator : public IUnknown +{ + /// + /// Advances to the first or next color run. The runs are enumerated + /// in order from back to front. + /// + /// Receives TRUE if there is a current run or + /// FALSE if the end of the sequence has been reached. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(MoveNext)( + _Out_ BOOL* hasRun + ) PURE; + + /// + /// Gets the current color glyph run. + /// + /// Receives a pointer to the color + /// glyph run. The pointer remains valid until the next call to + /// MoveNext or until the interface is released. + /// + /// Standard HRESULT error code. An error is returned if there is + /// no current glyph run, i.e., if MoveNext has not yet been called + /// or if the end of the sequence has been reached. + /// + STDMETHOD(GetCurrentRun)( + _Outptr_ DWRITE_COLOR_GLYPH_RUN const** colorGlyphRun + ) PURE; +}; + +/// +/// The interface that represents text rendering settings for glyph rasterization and filtering. +/// +interface DWRITE_DECLARE_INTERFACE("F9D711C3-9777-40AE-87E8-3E5AF9BF0948") IDWriteRenderingParams2 : public IDWriteRenderingParams1 +{ + /// + /// Gets the grid fitting mode. + /// + STDMETHOD_(DWRITE_GRID_FIT_MODE, GetGridFitMode)() PURE; +}; + +/// +/// The root factory interface for all DWrite objects. +/// +interface DWRITE_DECLARE_INTERFACE("0439fc60-ca44-4994-8dee-3a9af7b732ec") IDWriteFactory2 : public IDWriteFactory1 +{ + /// + /// Get the system-appropriate font fallback mapping list. + /// + /// The system fallback list. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetSystemFontFallback)( + _COM_Outptr_ IDWriteFontFallback** fontFallback + ) PURE; + + /// + /// Create a custom font fallback builder. + /// + /// Empty font fallback builder. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateFontFallbackBuilder)( + _COM_Outptr_ IDWriteFontFallbackBuilder** fontFallbackBuilder + ) PURE; + + /// + /// Translates a glyph run to a sequence of color glyph runs, which can be + /// rendered to produce a color representation of the original "base" run. + /// + /// Horizontal origin of the base glyph run in + /// pre-transform coordinates. + /// Vertical origin of the base glyph run in + /// pre-transform coordinates. + /// Pointer to the original "base" glyph run. + /// Optional glyph run description. + /// Measuring mode, needed to compute the origins + /// of each glyph. + /// Matrix converting from the client's + /// coordinate space to device coordinates (pixels), i.e., the world transform + /// multiplied by any DPI scaling. + /// Zero-based index of the color palette to use. + /// Valid indices are less than the number of palettes in the font, as returned + /// by IDWriteFontFace2::GetColorPaletteCount. + /// If the function succeeds, receives a pointer + /// to an enumerator object that can be used to obtain the color glyph runs. + /// If the base run has no color glyphs, then the output pointer is NULL + /// and the method returns DWRITE_E_NOCOLOR. + /// + /// Returns DWRITE_E_NOCOLOR if the font has no color information, the base + /// glyph run does not contain any color glyphs, or the specified color palette + /// index is out of range. In this case, the client should render the base glyph + /// run. Otherwise, returns a standard HRESULT error code. + /// + STDMETHOD(TranslateColorGlyphRun)( + FLOAT baselineOriginX, + FLOAT baselineOriginY, + _In_ DWRITE_GLYPH_RUN const* glyphRun, + _In_opt_ DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, + DWRITE_MEASURING_MODE measuringMode, + _In_opt_ DWRITE_MATRIX const* worldToDeviceTransform, + UINT32 colorPaletteIndex, + _COM_Outptr_ IDWriteColorGlyphRunEnumerator** colorLayers + ) PURE; + + /// + /// Creates a rendering parameters object with the specified properties. + /// + /// The gamma value used for gamma correction, which must be greater than zero and cannot exceed 256. + /// The amount of contrast enhancement, zero or greater. + /// The degree of ClearType level, from 0.0f (no ClearType) to 1.0f (full ClearType). + /// The geometry of a device pixel. + /// Method of rendering glyphs. In most cases, this should be DWRITE_RENDERING_MODE_DEFAULT to automatically use an appropriate mode. + /// How to grid fit glyph outlines. In most cases, this should be DWRITE_GRID_FIT_DEFAULT to automatically choose an appropriate mode. + /// Holds the newly created rendering parameters object, or NULL in case of failure. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateCustomRenderingParams)( + FLOAT gamma, + FLOAT enhancedContrast, + FLOAT grayscaleEnhancedContrast, + FLOAT clearTypeLevel, + DWRITE_PIXEL_GEOMETRY pixelGeometry, + DWRITE_RENDERING_MODE renderingMode, + DWRITE_GRID_FIT_MODE gridFitMode, + _COM_Outptr_ IDWriteRenderingParams2** renderingParams + ) PURE; + + using IDWriteFactory::CreateCustomRenderingParams; + using IDWriteFactory1::CreateCustomRenderingParams; + + /// + /// Creates a glyph run analysis object, which encapsulates information + /// used to render a glyph run. + /// + /// Structure specifying the properties of the glyph run. + /// Optional transform applied to the glyphs and their positions. This transform is applied after the + /// scaling specified by the emSize and pixelsPerDip. + /// Specifies the rendering mode, which must be one of the raster rendering modes (i.e., not default + /// and not outline). + /// Specifies the method to measure glyphs. + /// How to grid-fit glyph outlines. This must be non-default. + /// Horizontal position of the baseline origin, in DIPs. + /// Vertical position of the baseline origin, in DIPs. + /// Receives a pointer to the newly created object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateGlyphRunAnalysis)( + _In_ DWRITE_GLYPH_RUN const* glyphRun, + _In_opt_ DWRITE_MATRIX const* transform, + DWRITE_RENDERING_MODE renderingMode, + DWRITE_MEASURING_MODE measuringMode, + DWRITE_GRID_FIT_MODE gridFitMode, + DWRITE_TEXT_ANTIALIAS_MODE antialiasMode, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + _COM_Outptr_ IDWriteGlyphRunAnalysis** glyphRunAnalysis + ) PURE; + + using IDWriteFactory::CreateGlyphRunAnalysis; +}; + + +#endif /* DWRITE_2_H_INCLUDED */ diff --git a/opennurbs/Include/dwrite_x32.h b/opennurbs/Include/dwrite_x32.h new file mode 100644 index 0000000..ccd0bf8 --- /dev/null +++ b/opennurbs/Include/dwrite_x32.h @@ -0,0 +1,5141 @@ +//+-------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Abstract: +// DirectX Typography Services public API definitions. +// +//---------------------------------------------------------------------------- + +#ifndef DWRITE_H_INCLUDED +#define DWRITE_H_INCLUDED + +#pragma once + +#ifndef DWRITE_NO_WINDOWS_H + +#include +#include + +#endif // DWRITE_NO_WINDOWS_H + +#include + +#ifndef DWRITE_DECLARE_INTERFACE +#define DWRITE_DECLARE_INTERFACE(iid) DECLSPEC_UUID(iid) DECLSPEC_NOVTABLE +#endif + +#ifndef DWRITE_EXPORT +#define DWRITE_EXPORT __declspec(dllimport) WINAPI +#endif + +/// +/// The type of a font represented by a single font file. +/// Font formats that consist of multiple files, e.g. Type 1 .PFM and .PFB, have +/// separate enum values for each of the file type. +/// +enum DWRITE_FONT_FILE_TYPE +{ + /// + /// Font type is not recognized by the DirectWrite font system. + /// + DWRITE_FONT_FILE_TYPE_UNKNOWN, + + /// + /// OpenType font with CFF outlines. + /// + DWRITE_FONT_FILE_TYPE_CFF, + + /// + /// OpenType font with TrueType outlines. + /// + DWRITE_FONT_FILE_TYPE_TRUETYPE, + + /// + /// OpenType font that contains a TrueType collection. + /// + DWRITE_FONT_FILE_TYPE_OPENTYPE_COLLECTION, + + /// + /// Type 1 PFM font. + /// + DWRITE_FONT_FILE_TYPE_TYPE1_PFM, + + /// + /// Type 1 PFB font. + /// + DWRITE_FONT_FILE_TYPE_TYPE1_PFB, + + /// + /// Vector .FON font. + /// + DWRITE_FONT_FILE_TYPE_VECTOR, + + /// + /// Bitmap .FON font. + /// + DWRITE_FONT_FILE_TYPE_BITMAP, + + // The following name is obsolete, but kept as an alias to avoid breaking existing code. + DWRITE_FONT_FILE_TYPE_TRUETYPE_COLLECTION = DWRITE_FONT_FILE_TYPE_OPENTYPE_COLLECTION, +}; + +/// +/// The file format of a complete font face. +/// Font formats that consist of multiple files, e.g. Type 1 .PFM and .PFB, have +/// a single enum entry. +/// +enum DWRITE_FONT_FACE_TYPE +{ + /// + /// OpenType font face with CFF outlines. + /// + DWRITE_FONT_FACE_TYPE_CFF, + + /// + /// OpenType font face with TrueType outlines. + /// + DWRITE_FONT_FACE_TYPE_TRUETYPE, + + /// + /// OpenType font face that is a part of a TrueType or CFF collection. + /// + DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION, + + /// + /// A Type 1 font face. + /// + DWRITE_FONT_FACE_TYPE_TYPE1, + + /// + /// A vector .FON format font face. + /// + DWRITE_FONT_FACE_TYPE_VECTOR, + + /// + /// A bitmap .FON format font face. + /// + DWRITE_FONT_FACE_TYPE_BITMAP, + + /// + /// Font face type is not recognized by the DirectWrite font system. + /// + DWRITE_FONT_FACE_TYPE_UNKNOWN, + + /// + /// The font data includes only the CFF table from an OpenType CFF font. + /// This font face type can be used only for embedded fonts (i.e., custom + /// font file loaders) and the resulting font face object supports only the + /// minimum functionality necessary to render glyphs. + /// + DWRITE_FONT_FACE_TYPE_RAW_CFF, + + // The following name is obsolete, but kept as an alias to avoid breaking existing code. + DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION = DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION, +}; + +/// +/// Specifies algorithmic style simulations to be applied to the font face. +/// Bold and oblique simulations can be combined via bitwise OR operation. +/// +enum DWRITE_FONT_SIMULATIONS +{ + /// + /// No simulations are performed. + /// + DWRITE_FONT_SIMULATIONS_NONE = 0x0000, + + /// + /// Algorithmic emboldening is performed. + /// + DWRITE_FONT_SIMULATIONS_BOLD = 0x0001, + + /// + /// Algorithmic italicization is performed. + /// + DWRITE_FONT_SIMULATIONS_OBLIQUE = 0x0002 +}; + +#ifdef DEFINE_ENUM_FLAG_OPERATORS +DEFINE_ENUM_FLAG_OPERATORS(DWRITE_FONT_SIMULATIONS); +#endif + +/// +/// The font weight enumeration describes common values for degree of blackness or thickness of strokes of characters in a font. +/// Font weight values less than 1 or greater than 999 are considered to be invalid, and they are rejected by font API functions. +/// +enum DWRITE_FONT_WEIGHT +{ + /// + /// Predefined font weight : Thin (100). + /// + DWRITE_FONT_WEIGHT_THIN = 100, + + /// + /// Predefined font weight : Extra-light (200). + /// + DWRITE_FONT_WEIGHT_EXTRA_LIGHT = 200, + + /// + /// Predefined font weight : Ultra-light (200). + /// + DWRITE_FONT_WEIGHT_ULTRA_LIGHT = 200, + + /// + /// Predefined font weight : Light (300). + /// + DWRITE_FONT_WEIGHT_LIGHT = 300, + + /// + /// Predefined font weight : Semi-light (350). + /// + DWRITE_FONT_WEIGHT_SEMI_LIGHT = 350, + + /// + /// Predefined font weight : Normal (400). + /// + DWRITE_FONT_WEIGHT_NORMAL = 400, + + /// + /// Predefined font weight : Regular (400). + /// + DWRITE_FONT_WEIGHT_REGULAR = 400, + + /// + /// Predefined font weight : Medium (500). + /// + DWRITE_FONT_WEIGHT_MEDIUM = 500, + + /// + /// Predefined font weight : Demi-bold (600). + /// + DWRITE_FONT_WEIGHT_DEMI_BOLD = 600, + + /// + /// Predefined font weight : Semi-bold (600). + /// + DWRITE_FONT_WEIGHT_SEMI_BOLD = 600, + + /// + /// Predefined font weight : Bold (700). + /// + DWRITE_FONT_WEIGHT_BOLD = 700, + + /// + /// Predefined font weight : Extra-bold (800). + /// + DWRITE_FONT_WEIGHT_EXTRA_BOLD = 800, + + /// + /// Predefined font weight : Ultra-bold (800). + /// + DWRITE_FONT_WEIGHT_ULTRA_BOLD = 800, + + /// + /// Predefined font weight : Black (900). + /// + DWRITE_FONT_WEIGHT_BLACK = 900, + + /// + /// Predefined font weight : Heavy (900). + /// + DWRITE_FONT_WEIGHT_HEAVY = 900, + + /// + /// Predefined font weight : Extra-black (950). + /// + DWRITE_FONT_WEIGHT_EXTRA_BLACK = 950, + + /// + /// Predefined font weight : Ultra-black (950). + /// + DWRITE_FONT_WEIGHT_ULTRA_BLACK = 950 +}; + +/// +/// The font stretch enumeration describes relative change from the normal aspect ratio +/// as specified by a font designer for the glyphs in a font. +/// Values less than 1 or greater than 9 are considered to be invalid, and they are rejected by font API functions. +/// +enum DWRITE_FONT_STRETCH +{ + /// + /// Predefined font stretch : Not known (0). + /// + DWRITE_FONT_STRETCH_UNDEFINED = 0, + + /// + /// Predefined font stretch : Ultra-condensed (1). + /// + DWRITE_FONT_STRETCH_ULTRA_CONDENSED = 1, + + /// + /// Predefined font stretch : Extra-condensed (2). + /// + DWRITE_FONT_STRETCH_EXTRA_CONDENSED = 2, + + /// + /// Predefined font stretch : Condensed (3). + /// + DWRITE_FONT_STRETCH_CONDENSED = 3, + + /// + /// Predefined font stretch : Semi-condensed (4). + /// + DWRITE_FONT_STRETCH_SEMI_CONDENSED = 4, + + /// + /// Predefined font stretch : Normal (5). + /// + DWRITE_FONT_STRETCH_NORMAL = 5, + + /// + /// Predefined font stretch : Medium (5). + /// + DWRITE_FONT_STRETCH_MEDIUM = 5, + + /// + /// Predefined font stretch : Semi-expanded (6). + /// + DWRITE_FONT_STRETCH_SEMI_EXPANDED = 6, + + /// + /// Predefined font stretch : Expanded (7). + /// + DWRITE_FONT_STRETCH_EXPANDED = 7, + + /// + /// Predefined font stretch : Extra-expanded (8). + /// + DWRITE_FONT_STRETCH_EXTRA_EXPANDED = 8, + + /// + /// Predefined font stretch : Ultra-expanded (9). + /// + DWRITE_FONT_STRETCH_ULTRA_EXPANDED = 9 +}; + +/// +/// The font style enumeration describes the slope style of a font face, such as Normal, Italic or Oblique. +/// Values other than the ones defined in the enumeration are considered to be invalid, and they are rejected by font API functions. +/// +enum DWRITE_FONT_STYLE +{ + /// + /// Font slope style : Normal. + /// + DWRITE_FONT_STYLE_NORMAL, + + /// + /// Font slope style : Oblique. + /// + DWRITE_FONT_STYLE_OBLIQUE, + + /// + /// Font slope style : Italic. + /// + DWRITE_FONT_STYLE_ITALIC + +}; + +/// +/// The informational string enumeration identifies a string in a font. +/// +enum DWRITE_INFORMATIONAL_STRING_ID +{ + /// + /// Unspecified name ID. + /// + DWRITE_INFORMATIONAL_STRING_NONE, + + /// + /// Copyright notice provided by the font. + /// + DWRITE_INFORMATIONAL_STRING_COPYRIGHT_NOTICE, + + /// + /// String containing a version number. + /// + DWRITE_INFORMATIONAL_STRING_VERSION_STRINGS, + + /// + /// Trademark information provided by the font. + /// + DWRITE_INFORMATIONAL_STRING_TRADEMARK, + + /// + /// Name of the font manufacturer. + /// + DWRITE_INFORMATIONAL_STRING_MANUFACTURER, + + /// + /// Name of the font designer. + /// + DWRITE_INFORMATIONAL_STRING_DESIGNER, + + /// + /// URL of font designer (with protocol, e.g., http://, ftp://). + /// + DWRITE_INFORMATIONAL_STRING_DESIGNER_URL, + + /// + /// Description of the font. Can contain revision information, usage recommendations, history, features, etc. + /// + DWRITE_INFORMATIONAL_STRING_DESCRIPTION, + + /// + /// URL of font vendor (with protocol, e.g., http://, ftp://). If a unique serial number is embedded in the URL, it can be used to register the font. + /// + DWRITE_INFORMATIONAL_STRING_FONT_VENDOR_URL, + + /// + /// Description of how the font may be legally used, or different example scenarios for licensed use. This field should be written in plain language, not legalese. + /// + DWRITE_INFORMATIONAL_STRING_LICENSE_DESCRIPTION, + + /// + /// URL where additional licensing information can be found. + /// + DWRITE_INFORMATIONAL_STRING_LICENSE_INFO_URL, + + /// + /// GDI-compatible family name. Because GDI allows a maximum of four fonts per family, fonts in the same family may have different GDI-compatible family names + /// (e.g., "Arial", "Arial Narrow", "Arial Black"). + /// + DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, + + /// + /// GDI-compatible subfamily name. + /// + DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES, + + /// + /// Typographic family name preferred by the designer. This enables font designers to group more than four fonts in a single family without losing compatibility with + /// GDI. This name is typically only present if it differs from the GDI-compatible family name. + /// + DWRITE_INFORMATIONAL_STRING_TYPOGRAPHIC_FAMILY_NAMES, + + /// + /// Typographic subfamily name preferred by the designer. This name is typically only present if it differs from the GDI-compatible subfamily name. + /// + DWRITE_INFORMATIONAL_STRING_TYPOGRAPHIC_SUBFAMILY_NAMES, + + /// + /// Sample text. This can be the font name or any other text that the designer thinks is the best example to display the font in. + /// + DWRITE_INFORMATIONAL_STRING_SAMPLE_TEXT, + + /// + /// The full name of the font, e.g. "Arial Bold", from name id 4 in the name table. + /// + DWRITE_INFORMATIONAL_STRING_FULL_NAME, + + /// + /// The postscript name of the font, e.g. "GillSans-Bold" from name id 6 in the name table. + /// + DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, + + /// + /// The postscript CID findfont name, from name id 20 in the name table. + /// + DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME, + + /// + /// Family name for the weight-stretch-style model. + /// + DWRITE_INFORMATIONAL_STRING_WEIGHT_STRETCH_STYLE_FAMILY_NAME, + + /// + /// Script/language tag to identify the scripts or languages that the font was + /// primarily designed to support. See DWRITE_FONT_PROPERTY_ID_DESIGN_SCRIPT_LANGUAGE_TAG + /// for a longer description. + /// + DWRITE_INFORMATIONAL_STRING_DESIGN_SCRIPT_LANGUAGE_TAG, + + /// + /// Script/language tag to identify the scripts or languages that the font declares + /// it is able to support. + /// + DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG, + + // Obsolete aliases kept to avoid breaking existing code. + DWRITE_INFORMATIONAL_STRING_PREFERRED_FAMILY_NAMES = DWRITE_INFORMATIONAL_STRING_TYPOGRAPHIC_FAMILY_NAMES, + DWRITE_INFORMATIONAL_STRING_PREFERRED_SUBFAMILY_NAMES = DWRITE_INFORMATIONAL_STRING_TYPOGRAPHIC_SUBFAMILY_NAMES, + DWRITE_INFORMATIONAL_STRING_WWS_FAMILY_NAME = DWRITE_INFORMATIONAL_STRING_WEIGHT_STRETCH_STYLE_FAMILY_NAME, +}; + + +/// +/// The DWRITE_FONT_METRICS structure specifies the metrics of a font face that +/// are applicable to all glyphs within the font face. +/// +struct DWRITE_FONT_METRICS +{ + /// + /// The number of font design units per em unit. + /// Font files use their own coordinate system of font design units. + /// A font design unit is the smallest measurable unit in the em square, + /// an imaginary square that is used to size and align glyphs. + /// The concept of em square is used as a reference scale factor when defining font size and device transformation semantics. + /// The size of one em square is also commonly used to compute the paragraph indentation value. + /// + UINT16 designUnitsPerEm; + + /// + /// Ascent value of the font face in font design units. + /// Ascent is the distance from the top of font character alignment box to English baseline. + /// + UINT16 ascent; + + /// + /// Descent value of the font face in font design units. + /// Descent is the distance from the bottom of font character alignment box to English baseline. + /// + UINT16 descent; + + /// + /// Line gap in font design units. + /// Recommended additional white space to add between lines to improve legibility. The recommended line spacing + /// (baseline-to-baseline distance) is thus the sum of ascent, descent, and lineGap. The line gap is usually + /// positive or zero but can be negative, in which case the recommended line spacing is less than the height + /// of the character alignment box. + /// + INT16 lineGap; + + /// + /// Cap height value of the font face in font design units. + /// Cap height is the distance from English baseline to the top of a typical English capital. + /// Capital "H" is often used as a reference character for the purpose of calculating the cap height value. + /// + UINT16 capHeight; + + /// + /// x-height value of the font face in font design units. + /// x-height is the distance from English baseline to the top of lowercase letter "x", or a similar lowercase character. + /// + UINT16 xHeight; + + /// + /// The underline position value of the font face in font design units. + /// Underline position is the position of underline relative to the English baseline. + /// The value is usually made negative in order to place the underline below the baseline. + /// + INT16 underlinePosition; + + /// + /// The suggested underline thickness value of the font face in font design units. + /// + UINT16 underlineThickness; + + /// + /// The strikethrough position value of the font face in font design units. + /// Strikethrough position is the position of strikethrough relative to the English baseline. + /// The value is usually made positive in order to place the strikethrough above the baseline. + /// + INT16 strikethroughPosition; + + /// + /// The suggested strikethrough thickness value of the font face in font design units. + /// + UINT16 strikethroughThickness; +}; + +/// +/// The DWRITE_GLYPH_METRICS structure specifies the metrics of an individual glyph. +/// The units depend on how the metrics are obtained. +/// +struct DWRITE_GLYPH_METRICS +{ + /// + /// Specifies the X offset from the glyph origin to the left edge of the black box. + /// The glyph origin is the current horizontal writing position. + /// A negative value means the black box extends to the left of the origin (often true for lowercase italic 'f'). + /// + INT32 leftSideBearing; + + /// + /// Specifies the X offset from the origin of the current glyph to the origin of the next glyph when writing horizontally. + /// + UINT32 advanceWidth; + + /// + /// Specifies the X offset from the right edge of the black box to the origin of the next glyph when writing horizontally. + /// The value is negative when the right edge of the black box overhangs the layout box. + /// + INT32 rightSideBearing; + + /// + /// Specifies the vertical offset from the vertical origin to the top of the black box. + /// Thus, a positive value adds whitespace whereas a negative value means the glyph overhangs the top of the layout box. + /// + INT32 topSideBearing; + + /// + /// Specifies the Y offset from the vertical origin of the current glyph to the vertical origin of the next glyph when writing vertically. + /// (Note that the term "origin" by itself denotes the horizontal origin. The vertical origin is different. + /// Its Y coordinate is specified by verticalOriginY value, + /// and its X coordinate is half the advanceWidth to the right of the horizontal origin). + /// + UINT32 advanceHeight; + + /// + /// Specifies the vertical distance from the black box's bottom edge to the advance height. + /// Positive when the bottom edge of the black box is within the layout box. + /// Negative when the bottom edge of black box overhangs the layout box. + /// + INT32 bottomSideBearing; + + /// + /// Specifies the Y coordinate of a glyph's vertical origin, in the font's design coordinate system. + /// The y coordinate of a glyph's vertical origin is the sum of the glyph's top side bearing + /// and the top (i.e. yMax) of the glyph's bounding box. + /// + INT32 verticalOriginY; +}; + +/// +/// Optional adjustment to a glyph's position. A glyph offset changes the position of a glyph without affecting +/// the pen position. Offsets are in logical, pre-transform units. +/// +struct DWRITE_GLYPH_OFFSET +{ + /// + /// Offset in the advance direction of the run. A positive advance offset moves the glyph to the right + /// (in pre-transform coordinates) if the run is left-to-right or to the left if the run is right-to-left. + /// + FLOAT advanceOffset; + + /// + /// Offset in the ascent direction, i.e., the direction ascenders point. A positive ascender offset moves + /// the glyph up (in pre-transform coordinates). + /// + FLOAT ascenderOffset; +}; + +/// +/// Specifies the type of DirectWrite factory object. +/// DirectWrite factory contains internal state such as font loader registration and cached font data. +/// In most cases it is recommended to use the shared factory object, because it allows multiple components +/// that use DirectWrite to share internal DirectWrite state and reduce memory usage. +/// However, there are cases when it is desirable to reduce the impact of a component, +/// such as a plug-in from an untrusted source, on the rest of the process by sandboxing and isolating it +/// from the rest of the process components. In such cases, it is recommended to use an isolated factory for the sandboxed +/// component. +/// +enum DWRITE_FACTORY_TYPE +{ + /// + /// Shared factory allow for re-use of cached font data across multiple in process components. + /// Such factories also take advantage of cross process font caching components for better performance. + /// + DWRITE_FACTORY_TYPE_SHARED, + + /// + /// Objects created from the isolated factory do not interact with internal DirectWrite state from other components. + /// + DWRITE_FACTORY_TYPE_ISOLATED +}; + +/// +/// Creates an OpenType tag as a 32bit integer such that +/// the first character in the tag is the lowest byte, +/// (least significant on little endian architectures) +/// which can be used to compare with tags in the font file. +/// This macro is compatible with DWRITE_FONT_FEATURE_TAG. +/// +/// Example: DWRITE_MAKE_OPENTYPE_TAG('c','c','m','p') +/// Dword: 0x706D6363 +/// +#define DWRITE_MAKE_OPENTYPE_TAG(a,b,c,d) ( \ + (static_cast(static_cast(d)) << 24) | \ + (static_cast(static_cast(c)) << 16) | \ + (static_cast(static_cast(b)) << 8) | \ + static_cast(static_cast(a))) + +/// +/// Creates an OpenType tag for glyph positioning and substitution font features. +/// +#define DWRITE_MAKE_FONT_FEATURE_TAG(a,b,c,d) (static_cast(DWRITE_MAKE_OPENTYPE_TAG(a,b,c,d))) + +interface IDWriteFontFileStream; + +/// +/// Font file loader interface handles loading font file resources of a particular type from a key. +/// The font file loader interface is recommended to be implemented by a singleton object. +/// IMPORTANT: font file loader implementations must not register themselves with DirectWrite factory +/// inside their constructors and must not unregister themselves in their destructors, because +/// registration and unregistration operations increment and decrement the object reference count respectively. +/// Instead, registration and unregistration of font file loaders with DirectWrite factory should be performed +/// outside of the font file loader implementation as a separate step. +/// +interface DWRITE_DECLARE_INTERFACE("727cad4e-d6af-4c9e-8a08-d695b11caa49") IDWriteFontFileLoader : public IUnknown +{ + /// + /// Creates a font file stream object that encapsulates an open file resource. + /// The resource is closed when the last reference to fontFileStream is released. + /// + /// Font file reference key that uniquely identifies the font file resource + /// within the scope of the font loader being used. + /// Size of font file reference key in bytes. + /// Pointer to the newly created font file stream. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateStreamFromKey)( + _In_reads_bytes_(fontFileReferenceKeySize) void const* fontFileReferenceKey, + UINT32 fontFileReferenceKeySize, + _COM_Outptr_ IDWriteFontFileStream** fontFileStream + ) PURE; +}; + +/// +/// A built-in implementation of IDWriteFontFileLoader interface that operates on local font files +/// and exposes local font file information from the font file reference key. +/// Font file references created using CreateFontFileReference use this font file loader. +/// +interface DWRITE_DECLARE_INTERFACE("b2d9f3ec-c9fe-4a11-a2ec-d86208f7c0a2") IDWriteLocalFontFileLoader : public IDWriteFontFileLoader +{ + /// + /// Obtains the length of the absolute file path from the font file reference key. + /// + /// Font file reference key that uniquely identifies the local font file + /// within the scope of the font loader being used. + /// Size of font file reference key in bytes. + /// Length of the file path string not including the terminated NULL character. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFilePathLengthFromKey)( + _In_reads_bytes_(fontFileReferenceKeySize) void const* fontFileReferenceKey, + UINT32 fontFileReferenceKeySize, + _Out_ UINT32* filePathLength + ) PURE; + + /// + /// Obtains the absolute font file path from the font file reference key. + /// + /// Font file reference key that uniquely identifies the local font file + /// within the scope of the font loader being used. + /// Size of font file reference key in bytes. + /// Character array that receives the local file path. + /// Size of the filePath array in character count including the terminated NULL character. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFilePathFromKey)( + _In_reads_bytes_(fontFileReferenceKeySize) void const* fontFileReferenceKey, + UINT32 fontFileReferenceKeySize, + _Out_writes_z_(filePathSize) WCHAR* filePath, + UINT32 filePathSize + ) PURE; + + /// + /// Obtains the last write time of the file from the font file reference key. + /// + /// Font file reference key that uniquely identifies the local font file + /// within the scope of the font loader being used. + /// Size of font file reference key in bytes. + /// Last modified time of the font file. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetLastWriteTimeFromKey)( + _In_reads_bytes_(fontFileReferenceKeySize) void const* fontFileReferenceKey, + UINT32 fontFileReferenceKeySize, + _Out_ FILETIME* lastWriteTime + ) PURE; +}; + +/// +/// The interface for loading font file data. +/// +interface DWRITE_DECLARE_INTERFACE("6d4865fe-0ab8-4d91-8f62-5dd6be34a3e0") IDWriteFontFileStream : public IUnknown +{ + /// + /// Reads a fragment from a file. + /// + /// Receives the pointer to the start of the font file fragment. + /// Offset of the fragment from the beginning of the font file. + /// Size of the fragment in bytes. + /// The client defined context to be passed to the ReleaseFileFragment. + /// + /// Standard HRESULT error code. + /// + /// + /// IMPORTANT: ReadFileFragment() implementations must check whether the requested file fragment + /// is within the file bounds. Otherwise, an error should be returned from ReadFileFragment. + /// + STDMETHOD(ReadFileFragment)( + _Outptr_result_bytebuffer_(fragmentSize) void const** fragmentStart, + UINT64 fileOffset, + UINT64 fragmentSize, + _Out_ void** fragmentContext + ) PURE; + + /// + /// Releases a fragment from a file. + /// + /// The client defined context of a font fragment returned from ReadFileFragment. + STDMETHOD_(void, ReleaseFileFragment)( + void* fragmentContext + ) PURE; + + /// + /// Obtains the total size of a file. + /// + /// Receives the total size of the file. + /// + /// Standard HRESULT error code. + /// + /// + /// Implementing GetFileSize() for asynchronously loaded font files may require + /// downloading the complete file contents, therefore this method should only be used for operations that + /// either require complete font file to be loaded (e.g., copying a font file) or need to make + /// decisions based on the value of the file size (e.g., validation against a persisted file size). + /// + STDMETHOD(GetFileSize)( + _Out_ UINT64* fileSize + ) PURE; + + /// + /// Obtains the last modified time of the file. The last modified time is used by DirectWrite font selection algorithms + /// to determine whether one font resource is more up to date than another one. + /// + /// Receives the last modified time of the file in the format that represents + /// the number of 100-nanosecond intervals since January 1, 1601 (UTC). + /// + /// Standard HRESULT error code. For resources that don't have a concept of the last modified time, the implementation of + /// GetLastWriteTime should return E_NOTIMPL. + /// + STDMETHOD(GetLastWriteTime)( + _Out_ UINT64* lastWriteTime + ) PURE; +}; + +/// +/// The interface that represents a reference to a font file. +/// +interface DWRITE_DECLARE_INTERFACE("739d886a-cef5-47dc-8769-1a8b41bebbb0") IDWriteFontFile : public IUnknown +{ + /// + /// This method obtains the pointer to the reference key of a font file. The pointer is only valid until the object that refers to it is released. + /// + /// Pointer to the font file reference key. + /// IMPORTANT: The pointer value is valid until the font file reference object it is obtained from is released. + /// Size of font file reference key in bytes. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetReferenceKey)( + _Outptr_result_bytebuffer_(*fontFileReferenceKeySize) void const** fontFileReferenceKey, + _Out_ UINT32* fontFileReferenceKeySize + ) PURE; + + /// + /// Obtains the file loader associated with a font file object. + /// + /// The font file loader associated with the font file object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetLoader)( + _COM_Outptr_ IDWriteFontFileLoader** fontFileLoader + ) PURE; + + /// + /// Analyzes a file and returns whether it represents a font, and whether the font type is supported by the font system. + /// + /// TRUE if the font type is supported by the font system, FALSE otherwise. + /// The type of the font file. Note that even if isSupportedFontType is FALSE, + /// the fontFileType value may be different from DWRITE_FONT_FILE_TYPE_UNKNOWN. + /// The type of the font face that can be constructed from the font file. + /// Note that even if isSupportedFontType is FALSE, the fontFaceType value may be different from + /// DWRITE_FONT_FACE_TYPE_UNKNOWN. + /// Number of font faces contained in the font file. + /// + /// Standard HRESULT error code if there was a processing error during analysis. + /// + /// + /// IMPORTANT: certain font file types are recognized, but not supported by the font system. + /// For example, the font system will recognize a file as a Type 1 font file, + /// but will not be able to construct a font face object from it. In such situations, Analyze will set + /// isSupportedFontType output parameter to FALSE. + /// + STDMETHOD(Analyze)( + _Out_ BOOL* isSupportedFontType, + _Out_ DWRITE_FONT_FILE_TYPE* fontFileType, + _Out_opt_ DWRITE_FONT_FACE_TYPE* fontFaceType, + _Out_ UINT32* numberOfFaces + ) PURE; +}; + +/// +/// Represents the internal structure of a device pixel (i.e., the physical arrangement of red, +/// green, and blue color components) that is assumed for purposes of rendering text. +/// +#ifndef DWRITE_PIXEL_GEOMETRY_DEFINED +enum DWRITE_PIXEL_GEOMETRY +{ + /// + /// The red, green, and blue color components of each pixel are assumed to occupy the same point. + /// + DWRITE_PIXEL_GEOMETRY_FLAT, + + /// + /// Each pixel comprises three vertical stripes, with red on the left, green in the center, and + /// blue on the right. This is the most common pixel geometry for LCD monitors. + /// + DWRITE_PIXEL_GEOMETRY_RGB, + + /// + /// Each pixel comprises three vertical stripes, with blue on the left, green in the center, and + /// red on the right. + /// + DWRITE_PIXEL_GEOMETRY_BGR +}; +#define DWRITE_PIXEL_GEOMETRY_DEFINED +#endif + +/// +/// Represents a method of rendering glyphs. +/// +enum DWRITE_RENDERING_MODE +{ + /// + /// Specifies that the rendering mode is determined automatically based on the font and size. + /// + DWRITE_RENDERING_MODE_DEFAULT, + + /// + /// Specifies that no antialiasing is performed. Each pixel is either set to the foreground + /// color of the text or retains the color of the background. + /// + DWRITE_RENDERING_MODE_ALIASED, + + /// + /// Specifies that antialiasing is performed in the horizontal direction and the appearance + /// of glyphs is layout-compatible with GDI using CLEARTYPE_QUALITY. Use DWRITE_MEASURING_MODE_GDI_CLASSIC + /// to get glyph advances. The antialiasing may be either ClearType or grayscale depending on + /// the text antialiasing mode. + /// + DWRITE_RENDERING_MODE_GDI_CLASSIC, + + /// + /// Specifies that antialiasing is performed in the horizontal direction and the appearance + /// of glyphs is layout-compatible with GDI using CLEARTYPE_NATURAL_QUALITY. Glyph advances + /// are close to the font design advances, but are still rounded to whole pixels. Use + /// DWRITE_MEASURING_MODE_GDI_NATURAL to get glyph advances. The antialiasing may be either + /// ClearType or grayscale depending on the text antialiasing mode. + /// + DWRITE_RENDERING_MODE_GDI_NATURAL, + + /// + /// Specifies that antialiasing is performed in the horizontal direction. This rendering + /// mode allows glyphs to be positioned with subpixel precision and is therefore suitable + /// for natural (i.e., resolution-independent) layout. The antialiasing may be either + /// ClearType or grayscale depending on the text antialiasing mode. + /// + DWRITE_RENDERING_MODE_NATURAL, + + /// + /// Similar to natural mode except that antialiasing is performed in both the horizontal + /// and vertical directions. This is typically used at larger sizes to make curves and + /// diagonal lines look smoother. The antialiasing may be either ClearType or grayscale + /// depending on the text antialiasing mode. + /// + DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC, + + /// + /// Specifies that rendering should bypass the rasterizer and use the outlines directly. + /// This is typically used at very large sizes. + /// + DWRITE_RENDERING_MODE_OUTLINE, + + // The following names are obsolete, but are kept as aliases to avoid breaking existing code. + // Each of these rendering modes may result in either ClearType or grayscale antialiasing + // depending on the DWRITE_TEXT_ANTIALIASING_MODE. + DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC = DWRITE_RENDERING_MODE_GDI_CLASSIC, + DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL = DWRITE_RENDERING_MODE_GDI_NATURAL, + DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL = DWRITE_RENDERING_MODE_NATURAL, + DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC = DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC +}; + +/// +/// The DWRITE_MATRIX structure specifies the graphics transform to be applied +/// to rendered glyphs. +/// +struct DWRITE_MATRIX +{ + /// + /// Horizontal scaling / cosine of rotation + /// + FLOAT m11; + + /// + /// Vertical shear / sine of rotation + /// + FLOAT m12; + + /// + /// Horizontal shear / negative sine of rotation + /// + FLOAT m21; + + /// + /// Vertical scaling / cosine of rotation + /// + FLOAT m22; + + /// + /// Horizontal shift (always orthogonal regardless of rotation) + /// + FLOAT dx; + + /// + /// Vertical shift (always orthogonal regardless of rotation) + /// + FLOAT dy; +}; + +/// +/// The interface that represents text rendering settings for glyph rasterization and filtering. +/// +interface DWRITE_DECLARE_INTERFACE("2f0da53a-2add-47cd-82ee-d9ec34688e75") IDWriteRenderingParams : public IUnknown +{ + /// + /// Gets the gamma value used for gamma correction. Valid values must be + /// greater than zero and cannot exceed 256. + /// + STDMETHOD_(FLOAT, GetGamma)() PURE; + + /// + /// Gets the amount of contrast enhancement. Valid values are greater than + /// or equal to zero. + /// + STDMETHOD_(FLOAT, GetEnhancedContrast)() PURE; + + /// + /// Gets the ClearType level. Valid values range from 0.0f (no ClearType) + /// to 1.0f (full ClearType). + /// + STDMETHOD_(FLOAT, GetClearTypeLevel)() PURE; + + /// + /// Gets the pixel geometry. + /// + STDMETHOD_(DWRITE_PIXEL_GEOMETRY, GetPixelGeometry)() PURE; + + /// + /// Gets the rendering mode. + /// + STDMETHOD_(DWRITE_RENDERING_MODE, GetRenderingMode)() PURE; +}; + +// Forward declarations of D2D types +interface ID2D1SimplifiedGeometrySink; + +typedef ID2D1SimplifiedGeometrySink IDWriteGeometrySink; + +/// +/// This interface exposes various font data such as metrics, names, and glyph outlines. +/// It contains font face type, appropriate file references and face identification data. +/// +interface DWRITE_DECLARE_INTERFACE("5f49804d-7024-4d43-bfa9-d25984f53849") IDWriteFontFace : public IUnknown +{ + /// + /// Obtains the file format type of a font face. + /// + STDMETHOD_(DWRITE_FONT_FACE_TYPE, GetType)() PURE; + + /// + /// Obtains the font files representing a font face. + /// + /// The number of files representing the font face. + /// User provided array that stores pointers to font files representing the font face. + /// This parameter can be NULL if the user is only interested in the number of files representing the font face. + /// This API increments reference count of the font file pointers returned according to COM conventions, and the client + /// should release them when finished. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFiles)( + _Inout_ UINT32* numberOfFiles, + _Out_writes_opt_(*numberOfFiles) IDWriteFontFile** fontFiles + ) PURE; + + /// + /// Obtains the zero-based index of the font face in its font file or files. If the font files contain a single face, + /// the return value is zero. + /// + STDMETHOD_(UINT32, GetIndex)() PURE; + + /// + /// Obtains the algorithmic style simulation flags of a font face. + /// + STDMETHOD_(DWRITE_FONT_SIMULATIONS, GetSimulations)() PURE; + + /// + /// Determines whether the font is a symbol font. + /// + STDMETHOD_(BOOL, IsSymbolFont)() PURE; + + /// + /// Obtains design units and common metrics for the font face. + /// These metrics are applicable to all the glyphs within a fontface and are used by applications for layout calculations. + /// + /// Points to a DWRITE_FONT_METRICS structure to fill in. + /// The metrics returned by this function are in font design units. + STDMETHOD_(void, GetMetrics)( + _Out_ DWRITE_FONT_METRICS* fontFaceMetrics + ) PURE; + + /// + /// Obtains the number of glyphs in the font face. + /// + STDMETHOD_(UINT16, GetGlyphCount)() PURE; + + /// + /// Obtains ideal glyph metrics in font design units. Design glyphs metrics are used for glyph positioning. + /// + /// An array of glyph indices to compute the metrics for. + /// The number of elements in the glyphIndices array. + /// Array of DWRITE_GLYPH_METRICS structures filled by this function. + /// The metrics returned by this function are in font design units. + /// Indicates whether the font is being used in a sideways run. + /// This can affect the glyph metrics if the font has oblique simulation + /// because sideways oblique simulation differs from non-sideways oblique simulation. + /// + /// Standard HRESULT error code. If any of the input glyph indices are outside of the valid glyph index range + /// for the current font face, E_INVALIDARG will be returned. + /// + STDMETHOD(GetDesignGlyphMetrics)( + _In_reads_(glyphCount) UINT16 const* glyphIndices, + UINT32 glyphCount, + _Out_writes_(glyphCount) DWRITE_GLYPH_METRICS* glyphMetrics, + BOOL isSideways = FALSE + ) PURE; + + /// + /// Returns the nominal mapping of UTF-32 Unicode code points to glyph indices as defined by the font 'cmap' table. + /// Note that this mapping is primarily provided for line layout engines built on top of the physical font API. + /// Because of OpenType glyph substitution and line layout character substitution, the nominal conversion does not always correspond + /// to how a Unicode string will map to glyph indices when rendering using a particular font face. + /// Also, note that Unicode Variation Selectors provide for alternate mappings for character to glyph. + /// This call will always return the default variant. + /// + /// An array of UTF-32 code points to obtain nominal glyph indices from. + /// The number of elements in the codePoints array. + /// Array of nominal glyph indices filled by this function. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetGlyphIndices)( + _In_reads_(codePointCount) UINT32 const* codePoints, + UINT32 codePointCount, + _Out_writes_(codePointCount) UINT16* glyphIndices + ) PURE; + + /// + /// Finds the specified OpenType font table if it exists and returns a pointer to it. + /// The function accesses the underlying font data via the IDWriteFontFileStream interface + /// implemented by the font file loader. + /// + /// Four character tag of table to find. + /// Use the DWRITE_MAKE_OPENTYPE_TAG() macro to create it. + /// Unlike GDI, it does not support the special TTCF and null tags to access the whole font. + /// + /// Pointer to base of table in memory. + /// The pointer is only valid so long as the FontFace used to get the font table still exists + /// (not any other FontFace, even if it actually refers to the same physical font). + /// + /// Byte size of table. + /// + /// Opaque context which must be freed by calling ReleaseFontTable. + /// The context actually comes from the lower level IDWriteFontFileStream, + /// which may be implemented by the application or DWrite itself. + /// It is possible for a NULL tableContext to be returned, especially if + /// the implementation directly memory maps the whole file. + /// Nevertheless, always release it later, and do not use it as a test for function success. + /// The same table can be queried multiple times, + /// but each returned context can be different, so release each separately. + /// + /// True if table exists. + /// + /// Standard HRESULT error code. + /// If a table can not be found, the function will not return an error, but the size will be 0, table NULL, and exists = FALSE. + /// The context does not need to be freed if the table was not found. + /// + /// + /// The context for the same tag may be different for each call, + /// so each one must be held and released separately. + /// + STDMETHOD(TryGetFontTable)( + _In_ UINT32 openTypeTableTag, + _Outptr_result_bytebuffer_(*tableSize) const void** tableData, + _Out_ UINT32* tableSize, + _Out_ void** tableContext, + _Out_ BOOL* exists + ) PURE; + + /// + /// Releases the table obtained earlier from TryGetFontTable. + /// + /// Opaque context from TryGetFontTable. + STDMETHOD_(void, ReleaseFontTable)( + _In_ void* tableContext + ) PURE; + + /// + /// Computes the outline of a run of glyphs by calling back to the outline sink interface. + /// + /// Logical size of the font in DIP units. A DIP ("device-independent pixel") equals 1/96 inch. + /// Array of glyph indices. + /// Optional array of glyph advances in DIPs. + /// Optional array of glyph offsets. + /// Number of glyphs. + /// If true, specifies that glyphs are rotated 90 degrees to the left and vertical metrics are used. + /// A client can render a vertical run by specifying isSideways = true and rotating the resulting geometry 90 degrees to the + /// right using a transform. + /// If true, specifies that the advance direction is right to left. By default, the advance direction + /// is left to right. + /// Interface the function calls back to draw each element of the geometry. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetGlyphRunOutline)( + FLOAT emSize, + _In_reads_(glyphCount) UINT16 const* glyphIndices, + _In_reads_opt_(glyphCount) FLOAT const* glyphAdvances, + _In_reads_opt_(glyphCount) DWRITE_GLYPH_OFFSET const* glyphOffsets, + UINT32 glyphCount, + BOOL isSideways, + BOOL isRightToLeft, + _In_ IDWriteGeometrySink* geometrySink + ) PURE; + + /// + /// Determines the recommended rendering mode for the font given the specified size and rendering parameters. + /// + /// Logical size of the font in DIP units. A DIP ("device-independent pixel") equals 1/96 inch. + /// Number of physical pixels per DIP. For example, if the DPI of the rendering surface is 96 this + /// value is 1.0f. If the DPI is 120, this value is 120.0f/96. + /// Specifies measuring mode that will be used for glyphs in the font. + /// Renderer implementations may choose different rendering modes for given measuring modes, but + /// best results are seen when the corresponding modes match: + /// DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL for DWRITE_MEASURING_MODE_NATURAL + /// DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC for DWRITE_MEASURING_MODE_GDI_CLASSIC + /// DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL for DWRITE_MEASURING_MODE_GDI_NATURAL + /// + /// Rendering parameters object. This parameter is necessary in case the rendering parameters + /// object overrides the rendering mode. + /// Receives the recommended rendering mode to use. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetRecommendedRenderingMode)( + FLOAT emSize, + FLOAT pixelsPerDip, + DWRITE_MEASURING_MODE measuringMode, + IDWriteRenderingParams* renderingParams, + _Out_ DWRITE_RENDERING_MODE* renderingMode + ) PURE; + + /// + /// Obtains design units and common metrics for the font face. + /// These metrics are applicable to all the glyphs within a fontface and are used by applications for layout calculations. + /// + /// Logical size of the font in DIP units. A DIP ("device-independent pixel") equals 1/96 inch. + /// Number of physical pixels per DIP. For example, if the DPI of the rendering surface is 96 this + /// value is 1.0f. If the DPI is 120, this value is 120.0f/96. + /// Optional transform applied to the glyphs and their positions. This transform is applied after the + /// scaling specified by the font size and pixelsPerDip. + /// Points to a DWRITE_FONT_METRICS structure to fill in. + /// The metrics returned by this function are in font design units. + STDMETHOD(GetGdiCompatibleMetrics)( + FLOAT emSize, + FLOAT pixelsPerDip, + _In_opt_ DWRITE_MATRIX const* transform, + _Out_ DWRITE_FONT_METRICS* fontFaceMetrics + ) PURE; + + /// + /// Obtains glyph metrics in font design units with the return values compatible with what GDI would produce. + /// Glyphs metrics are used for positioning of individual glyphs. + /// + /// Logical size of the font in DIP units. A DIP ("device-independent pixel") equals 1/96 inch. + /// Number of physical pixels per DIP. For example, if the DPI of the rendering surface is 96 this + /// value is 1.0f. If the DPI is 120, this value is 120.0f/96. + /// Optional transform applied to the glyphs and their positions. This transform is applied after the + /// scaling specified by the font size and pixelsPerDip. + /// + /// When set to FALSE, the metrics are the same as the metrics of GDI aliased text. + /// When set to TRUE, the metrics are the same as the metrics of text measured by GDI using a font + /// created with CLEARTYPE_NATURAL_QUALITY. + /// + /// An array of glyph indices to compute the metrics for. + /// The number of elements in the glyphIndices array. + /// Array of DWRITE_GLYPH_METRICS structures filled by this function. + /// The metrics returned by this function are in font design units. + /// Indicates whether the font is being used in a sideways run. + /// This can affect the glyph metrics if the font has oblique simulation + /// because sideways oblique simulation differs from non-sideways oblique simulation. + /// + /// Standard HRESULT error code. If any of the input glyph indices are outside of the valid glyph index range + /// for the current font face, E_INVALIDARG will be returned. + /// + STDMETHOD(GetGdiCompatibleGlyphMetrics)( + FLOAT emSize, + FLOAT pixelsPerDip, + _In_opt_ DWRITE_MATRIX const* transform, + BOOL useGdiNatural, + _In_reads_(glyphCount) UINT16 const* glyphIndices, + UINT32 glyphCount, + _Out_writes_(glyphCount) DWRITE_GLYPH_METRICS* glyphMetrics, + BOOL isSideways = FALSE + ) PURE; +}; + + +interface IDWriteFactory; +interface IDWriteFontFileEnumerator; + +/// +/// The font collection loader interface is used to construct a collection of fonts given a particular type of key. +/// The font collection loader interface is recommended to be implemented by a singleton object. +/// IMPORTANT: font collection loader implementations must not register themselves with a DirectWrite factory +/// inside their constructors and must not unregister themselves in their destructors, because +/// registration and unregistration operations increment and decrement the object reference count respectively. +/// Instead, registration and unregistration of font file loaders with DirectWrite factory should be performed +/// outside of the font file loader implementation as a separate step. +/// +interface DWRITE_DECLARE_INTERFACE("cca920e4-52f0-492b-bfa8-29c72ee0a468") IDWriteFontCollectionLoader : public IUnknown +{ + /// + /// Creates a font file enumerator object that encapsulates a collection of font files. + /// The font system calls back to this interface to create a font collection. + /// + /// Factory associated with the loader. + /// Font collection key that uniquely identifies the collection of font files within + /// the scope of the font collection loader being used. + /// Size of the font collection key in bytes. + /// Pointer to the newly created font file enumerator. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateEnumeratorFromKey)( + _In_ IDWriteFactory* factory, + _In_reads_bytes_(collectionKeySize) void const* collectionKey, + UINT32 collectionKeySize, + _COM_Outptr_ IDWriteFontFileEnumerator** fontFileEnumerator + ) PURE; +}; + +/// +/// The font file enumerator interface encapsulates a collection of font files. The font system uses this interface +/// to enumerate font files when building a font collection. +/// +interface DWRITE_DECLARE_INTERFACE("72755049-5ff7-435d-8348-4be97cfa6c7c") IDWriteFontFileEnumerator : public IUnknown +{ + /// + /// Advances to the next font file in the collection. When it is first created, the enumerator is positioned + /// before the first element of the collection and the first call to MoveNext advances to the first file. + /// + /// Receives the value TRUE if the enumerator advances to a file, or FALSE if + /// the enumerator advanced past the last file in the collection. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(MoveNext)( + _Out_ BOOL* hasCurrentFile + ) PURE; + + /// + /// Gets a reference to the current font file. + /// + /// Pointer to the newly created font file object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetCurrentFontFile)( + _COM_Outptr_ IDWriteFontFile** fontFile + ) PURE; +}; + +/// +/// Represents a collection of strings indexed by locale name. +/// +interface DWRITE_DECLARE_INTERFACE("08256209-099a-4b34-b86d-c22b110e7771") IDWriteLocalizedStrings : public IUnknown +{ + /// + /// Gets the number of language/string pairs. + /// + STDMETHOD_(UINT32, GetCount)() PURE; + + /// + /// Gets the index of the item with the specified locale name. + /// + /// Locale name to look for. + /// Receives the zero-based index of the locale name/string pair. + /// Receives TRUE if the locale name exists or FALSE if not. + /// + /// Standard HRESULT error code. If the specified locale name does not exist, the return value is S_OK, + /// but *index is UINT_MAX and *exists is FALSE. + /// + STDMETHOD(FindLocaleName)( + _In_z_ WCHAR const* localeName, + _Out_ UINT32* index, + _Out_ BOOL* exists + ) PURE; + + /// + /// Gets the length in characters (not including the null terminator) of the locale name with the specified index. + /// + /// Zero-based index of the locale name. + /// Receives the length in characters, not including the null terminator. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetLocaleNameLength)( + UINT32 index, + _Out_ UINT32* length + ) PURE; + + /// + /// Copies the locale name with the specified index to the specified array. + /// + /// Zero-based index of the locale name. + /// Character array that receives the locale name. + /// Size of the array in characters. The size must include space for the terminating + /// null character. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetLocaleName)( + UINT32 index, + _Out_writes_z_(size) WCHAR* localeName, + UINT32 size + ) PURE; + + /// + /// Gets the length in characters (not including the null terminator) of the string with the specified index. + /// + /// Zero-based index of the string. + /// Receives the length in characters, not including the null terminator. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetStringLength)( + UINT32 index, + _Out_ UINT32* length + ) PURE; + + /// + /// Copies the string with the specified index to the specified array. + /// + /// Zero-based index of the string. + /// Character array that receives the string. + /// Size of the array in characters. The size must include space for the terminating + /// null character. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetString)( + UINT32 index, + _Out_writes_z_(size) WCHAR* stringBuffer, + UINT32 size + ) PURE; +}; + +interface IDWriteFontFamily; +interface IDWriteFont; + +/// +/// The IDWriteFontCollection encapsulates a collection of font families. +/// +interface DWRITE_DECLARE_INTERFACE("a84cee02-3eea-4eee-a827-87c1a02a0fcc") IDWriteFontCollection : public IUnknown +{ + /// + /// Gets the number of font families in the collection. + /// + STDMETHOD_(UINT32, GetFontFamilyCount)() PURE; + + /// + /// Creates a font family object given a zero-based font family index. + /// + /// Zero-based index of the font family. + /// Receives a pointer the newly created font family object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFontFamily)( + UINT32 index, + _COM_Outptr_ IDWriteFontFamily** fontFamily + ) PURE; + + /// + /// Finds the font family with the specified family name. + /// + /// Name of the font family. The name is not case-sensitive but must otherwise exactly match a family name in the collection. + /// Receives the zero-based index of the matching font family if the family name was found or UINT_MAX otherwise. + /// Receives TRUE if the family name exists or FALSE otherwise. + /// + /// Standard HRESULT error code. If the specified family name does not exist, the return value is S_OK, but *index is UINT_MAX and *exists is FALSE. + /// + STDMETHOD(FindFamilyName)( + _In_z_ WCHAR const* familyName, + _Out_ UINT32* index, + _Out_ BOOL* exists + ) PURE; + + /// + /// Gets the font object that corresponds to the same physical font as the specified font face object. The specified physical font must belong + /// to the font collection. + /// + /// Font face object that specifies the physical font. + /// Receives a pointer to the newly created font object if successful or NULL otherwise. + /// + /// Standard HRESULT error code. If the specified physical font is not part of the font collection the return value is DWRITE_E_NOFONT. + /// + STDMETHOD(GetFontFromFontFace)( + _In_ IDWriteFontFace* fontFace, + _COM_Outptr_ IDWriteFont** font + ) PURE; +}; + +/// +/// The IDWriteFontList interface represents an ordered set of fonts that are part of an IDWriteFontCollection. +/// +interface DWRITE_DECLARE_INTERFACE("1a0d8438-1d97-4ec1-aef9-a2fb86ed6acb") IDWriteFontList : public IUnknown +{ + /// + /// Gets the font collection that contains the fonts. + /// + /// Receives a pointer to the font collection object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFontCollection)( + _COM_Outptr_ IDWriteFontCollection** fontCollection + ) PURE; + + /// + /// Gets the number of fonts in the font list. + /// + STDMETHOD_(UINT32, GetFontCount)() PURE; + + /// + /// Gets a font given its zero-based index. + /// + /// Zero-based index of the font in the font list. + /// Receives a pointer to the newly created font object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFont)( + UINT32 index, + _COM_Outptr_ IDWriteFont** font + ) PURE; +}; + +/// +/// The IDWriteFontFamily interface represents a set of fonts that share the same design but are differentiated +/// by weight, stretch, and style. +/// +interface DWRITE_DECLARE_INTERFACE("da20d8ef-812a-4c43-9802-62ec4abd7add") IDWriteFontFamily : public IDWriteFontList +{ + /// + /// Creates a localized strings object that contains the family names for the font family, indexed by locale name. + /// + /// Receives a pointer to the newly created localized strings object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFamilyNames)( + _COM_Outptr_ IDWriteLocalizedStrings** names + ) PURE; + + /// + /// Gets the font that best matches the specified properties. + /// + /// Requested font weight. + /// Requested font stretch. + /// Requested font style. + /// Receives a pointer to the newly created font object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFirstMatchingFont)( + DWRITE_FONT_WEIGHT weight, + DWRITE_FONT_STRETCH stretch, + DWRITE_FONT_STYLE style, + _COM_Outptr_ IDWriteFont** matchingFont + ) PURE; + + /// + /// Gets a list of fonts in the font family ranked in order of how well they match the specified properties. + /// + /// Requested font weight. + /// Requested font stretch. + /// Requested font style. + /// Receives a pointer to the newly created font list object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetMatchingFonts)( + DWRITE_FONT_WEIGHT weight, + DWRITE_FONT_STRETCH stretch, + DWRITE_FONT_STYLE style, + _COM_Outptr_ IDWriteFontList** matchingFonts + ) PURE; +}; + +/// +/// The IDWriteFont interface represents a physical font in a font collection. +/// +interface DWRITE_DECLARE_INTERFACE("acd16696-8c14-4f5d-877e-fe3fc1d32737") IDWriteFont : public IUnknown +{ + /// + /// Gets the font family to which the specified font belongs. + /// + /// Receives a pointer to the font family object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFontFamily)( + _COM_Outptr_ IDWriteFontFamily** fontFamily + ) PURE; + + /// + /// Gets the weight of the specified font. + /// + STDMETHOD_(DWRITE_FONT_WEIGHT, GetWeight)() PURE; + + /// + /// Gets the stretch (aka. width) of the specified font. + /// + STDMETHOD_(DWRITE_FONT_STRETCH, GetStretch)() PURE; + + /// + /// Gets the style (aka. slope) of the specified font. + /// + STDMETHOD_(DWRITE_FONT_STYLE, GetStyle)() PURE; + + /// + /// Returns TRUE if the font is a symbol font or FALSE if not. + /// + STDMETHOD_(BOOL, IsSymbolFont)() PURE; + + /// + /// Gets a localized strings collection containing the face names for the font (e.g., Regular or Bold), indexed by locale name. + /// + /// Receives a pointer to the newly created localized strings object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFaceNames)( + _COM_Outptr_ IDWriteLocalizedStrings** names + ) PURE; + + /// + /// Gets a localized strings collection containing the specified informational strings, indexed by locale name. + /// + /// Identifies the string to get. + /// Receives a pointer to the newly created localized strings object. + /// Receives the value TRUE if the font contains the specified string ID or FALSE if not. + /// + /// Standard HRESULT error code. If the font does not contain the specified string, the return value is S_OK but + /// informationalStrings receives a NULL pointer and exists receives the value FALSE. + /// + STDMETHOD(GetInformationalStrings)( + DWRITE_INFORMATIONAL_STRING_ID informationalStringID, + _COM_Outptr_result_maybenull_ IDWriteLocalizedStrings** informationalStrings, + _Out_ BOOL* exists + ) PURE; + + /// + /// Gets a value that indicates what simulation are applied to the specified font. + /// + STDMETHOD_(DWRITE_FONT_SIMULATIONS, GetSimulations)() PURE; + + /// + /// Gets the metrics for the font. + /// + /// Receives the font metrics. + STDMETHOD_(void, GetMetrics)( + _Out_ DWRITE_FONT_METRICS* fontMetrics + ) PURE; + + /// + /// Determines whether the font supports the specified character. + /// + /// Unicode (UCS-4) character value. + /// Receives the value TRUE if the font supports the specified character or FALSE if not. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(HasCharacter)( + UINT32 unicodeValue, + _Out_ BOOL* exists + ) PURE; + + /// + /// Creates a font face object for the font. + /// + /// Receives a pointer to the newly created font face object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateFontFace)( + _COM_Outptr_ IDWriteFontFace** fontFace + ) PURE; +}; + +/// +/// Direction for how reading progresses. +/// +enum DWRITE_READING_DIRECTION +{ + /// + /// Reading progresses from left to right. + /// + DWRITE_READING_DIRECTION_LEFT_TO_RIGHT = 0, + + /// + /// Reading progresses from right to left. + /// + DWRITE_READING_DIRECTION_RIGHT_TO_LEFT = 1, + + /// + /// Reading progresses from top to bottom. + /// + DWRITE_READING_DIRECTION_TOP_TO_BOTTOM = 2, + + /// + /// Reading progresses from bottom to top. + /// + DWRITE_READING_DIRECTION_BOTTOM_TO_TOP = 3, +}; + +/// +/// Direction for how lines of text are placed relative to one another. +/// +enum DWRITE_FLOW_DIRECTION +{ + /// + /// Text lines are placed from top to bottom. + /// + DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM = 0, + + /// + /// Text lines are placed from bottom to top. + /// + DWRITE_FLOW_DIRECTION_BOTTOM_TO_TOP = 1, + + /// + /// Text lines are placed from left to right. + /// + DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT = 2, + + /// + /// Text lines are placed from right to left. + /// + DWRITE_FLOW_DIRECTION_RIGHT_TO_LEFT = 3, +}; + +/// +/// Alignment of paragraph text along the reading direction axis relative to +/// the leading and trailing edge of the layout box. +/// +enum DWRITE_TEXT_ALIGNMENT +{ + /// + /// The leading edge of the paragraph text is aligned to the layout box's leading edge. + /// + DWRITE_TEXT_ALIGNMENT_LEADING, + + /// + /// The trailing edge of the paragraph text is aligned to the layout box's trailing edge. + /// + DWRITE_TEXT_ALIGNMENT_TRAILING, + + /// + /// The center of the paragraph text is aligned to the center of the layout box. + /// + DWRITE_TEXT_ALIGNMENT_CENTER, + + /// + /// Align text to the leading side, and also justify text to fill the lines. + /// + DWRITE_TEXT_ALIGNMENT_JUSTIFIED +}; + +/// +/// Alignment of paragraph text along the flow direction axis relative to the +/// flow's beginning and ending edge of the layout box. +/// +enum DWRITE_PARAGRAPH_ALIGNMENT +{ + /// + /// The first line of paragraph is aligned to the flow's beginning edge of the layout box. + /// + DWRITE_PARAGRAPH_ALIGNMENT_NEAR, + + /// + /// The last line of paragraph is aligned to the flow's ending edge of the layout box. + /// + DWRITE_PARAGRAPH_ALIGNMENT_FAR, + + /// + /// The center of the paragraph is aligned to the center of the flow of the layout box. + /// + DWRITE_PARAGRAPH_ALIGNMENT_CENTER +}; + +/// +/// Word wrapping in multiline paragraph. +/// +enum DWRITE_WORD_WRAPPING +{ + /// + /// Words are broken across lines to avoid text overflowing the layout box. + /// + DWRITE_WORD_WRAPPING_WRAP = 0, + + /// + /// Words are kept within the same line even when it overflows the layout box. + /// This option is often used with scrolling to reveal overflow text. + /// + DWRITE_WORD_WRAPPING_NO_WRAP = 1, + + /// + /// Words are broken across lines to avoid text overflowing the layout box. + /// Emergency wrapping occurs if the word is larger than the maximum width. + /// + DWRITE_WORD_WRAPPING_EMERGENCY_BREAK = 2, + + /// + /// Only wrap whole words, never breaking words (emergency wrapping) when the + /// layout width is too small for even a single word. + /// + DWRITE_WORD_WRAPPING_WHOLE_WORD = 3, + + /// + /// Wrap between any valid characters clusters. + /// + DWRITE_WORD_WRAPPING_CHARACTER = 4, +}; + +/// +/// The method used for line spacing in layout. +/// +enum DWRITE_LINE_SPACING_METHOD +{ + /// + /// Line spacing depends solely on the content, growing to accommodate the size of fonts and inline objects. + /// + DWRITE_LINE_SPACING_METHOD_DEFAULT, + + /// + /// Lines are explicitly set to uniform spacing, regardless of contained font sizes. + /// This can be useful to avoid the uneven appearance that can occur from font fallback. + /// + DWRITE_LINE_SPACING_METHOD_UNIFORM, + + /// + /// Line spacing and baseline distances are proportional to the computed values based on the content, the size of the fonts and inline objects. + /// + DWRITE_LINE_SPACING_METHOD_PROPORTIONAL +}; + +/// +/// Text granularity used to trim text overflowing the layout box. +/// +enum DWRITE_TRIMMING_GRANULARITY +{ + /// + /// No trimming occurs. Text flows beyond the layout width. + /// + DWRITE_TRIMMING_GRANULARITY_NONE, + + /// + /// Trimming occurs at character cluster boundary. + /// + DWRITE_TRIMMING_GRANULARITY_CHARACTER, + + /// + /// Trimming occurs at word boundary. + /// + DWRITE_TRIMMING_GRANULARITY_WORD +}; + +/// +/// Typographic feature of text supplied by the font. +/// +/// +/// Use DWRITE_MAKE_FONT_FEATURE_TAG() to create a custom one. +/// +enum DWRITE_FONT_FEATURE_TAG +{ + DWRITE_FONT_FEATURE_TAG_ALTERNATIVE_FRACTIONS = DWRITE_MAKE_OPENTYPE_TAG('a','f','r','c'), + DWRITE_FONT_FEATURE_TAG_PETITE_CAPITALS_FROM_CAPITALS = DWRITE_MAKE_OPENTYPE_TAG('c','2','p','c'), + DWRITE_FONT_FEATURE_TAG_SMALL_CAPITALS_FROM_CAPITALS = DWRITE_MAKE_OPENTYPE_TAG('c','2','s','c'), + DWRITE_FONT_FEATURE_TAG_CONTEXTUAL_ALTERNATES = DWRITE_MAKE_OPENTYPE_TAG('c','a','l','t'), + DWRITE_FONT_FEATURE_TAG_CASE_SENSITIVE_FORMS = DWRITE_MAKE_OPENTYPE_TAG('c','a','s','e'), + DWRITE_FONT_FEATURE_TAG_GLYPH_COMPOSITION_DECOMPOSITION = DWRITE_MAKE_OPENTYPE_TAG('c','c','m','p'), + DWRITE_FONT_FEATURE_TAG_CONTEXTUAL_LIGATURES = DWRITE_MAKE_OPENTYPE_TAG('c','l','i','g'), + DWRITE_FONT_FEATURE_TAG_CAPITAL_SPACING = DWRITE_MAKE_OPENTYPE_TAG('c','p','s','p'), + DWRITE_FONT_FEATURE_TAG_CONTEXTUAL_SWASH = DWRITE_MAKE_OPENTYPE_TAG('c','s','w','h'), + DWRITE_FONT_FEATURE_TAG_CURSIVE_POSITIONING = DWRITE_MAKE_OPENTYPE_TAG('c','u','r','s'), + DWRITE_FONT_FEATURE_TAG_DEFAULT = DWRITE_MAKE_OPENTYPE_TAG('d','f','l','t'), + DWRITE_FONT_FEATURE_TAG_DISCRETIONARY_LIGATURES = DWRITE_MAKE_OPENTYPE_TAG('d','l','i','g'), + DWRITE_FONT_FEATURE_TAG_EXPERT_FORMS = DWRITE_MAKE_OPENTYPE_TAG('e','x','p','t'), + DWRITE_FONT_FEATURE_TAG_FRACTIONS = DWRITE_MAKE_OPENTYPE_TAG('f','r','a','c'), + DWRITE_FONT_FEATURE_TAG_FULL_WIDTH = DWRITE_MAKE_OPENTYPE_TAG('f','w','i','d'), + DWRITE_FONT_FEATURE_TAG_HALF_FORMS = DWRITE_MAKE_OPENTYPE_TAG('h','a','l','f'), + DWRITE_FONT_FEATURE_TAG_HALANT_FORMS = DWRITE_MAKE_OPENTYPE_TAG('h','a','l','n'), + DWRITE_FONT_FEATURE_TAG_ALTERNATE_HALF_WIDTH = DWRITE_MAKE_OPENTYPE_TAG('h','a','l','t'), + DWRITE_FONT_FEATURE_TAG_HISTORICAL_FORMS = DWRITE_MAKE_OPENTYPE_TAG('h','i','s','t'), + DWRITE_FONT_FEATURE_TAG_HORIZONTAL_KANA_ALTERNATES = DWRITE_MAKE_OPENTYPE_TAG('h','k','n','a'), + DWRITE_FONT_FEATURE_TAG_HISTORICAL_LIGATURES = DWRITE_MAKE_OPENTYPE_TAG('h','l','i','g'), + DWRITE_FONT_FEATURE_TAG_HALF_WIDTH = DWRITE_MAKE_OPENTYPE_TAG('h','w','i','d'), + DWRITE_FONT_FEATURE_TAG_HOJO_KANJI_FORMS = DWRITE_MAKE_OPENTYPE_TAG('h','o','j','o'), + DWRITE_FONT_FEATURE_TAG_JIS04_FORMS = DWRITE_MAKE_OPENTYPE_TAG('j','p','0','4'), + DWRITE_FONT_FEATURE_TAG_JIS78_FORMS = DWRITE_MAKE_OPENTYPE_TAG('j','p','7','8'), + DWRITE_FONT_FEATURE_TAG_JIS83_FORMS = DWRITE_MAKE_OPENTYPE_TAG('j','p','8','3'), + DWRITE_FONT_FEATURE_TAG_JIS90_FORMS = DWRITE_MAKE_OPENTYPE_TAG('j','p','9','0'), + DWRITE_FONT_FEATURE_TAG_KERNING = DWRITE_MAKE_OPENTYPE_TAG('k','e','r','n'), + DWRITE_FONT_FEATURE_TAG_STANDARD_LIGATURES = DWRITE_MAKE_OPENTYPE_TAG('l','i','g','a'), + DWRITE_FONT_FEATURE_TAG_LINING_FIGURES = DWRITE_MAKE_OPENTYPE_TAG('l','n','u','m'), + DWRITE_FONT_FEATURE_TAG_LOCALIZED_FORMS = DWRITE_MAKE_OPENTYPE_TAG('l','o','c','l'), + DWRITE_FONT_FEATURE_TAG_MARK_POSITIONING = DWRITE_MAKE_OPENTYPE_TAG('m','a','r','k'), + DWRITE_FONT_FEATURE_TAG_MATHEMATICAL_GREEK = DWRITE_MAKE_OPENTYPE_TAG('m','g','r','k'), + DWRITE_FONT_FEATURE_TAG_MARK_TO_MARK_POSITIONING = DWRITE_MAKE_OPENTYPE_TAG('m','k','m','k'), + DWRITE_FONT_FEATURE_TAG_ALTERNATE_ANNOTATION_FORMS = DWRITE_MAKE_OPENTYPE_TAG('n','a','l','t'), + DWRITE_FONT_FEATURE_TAG_NLC_KANJI_FORMS = DWRITE_MAKE_OPENTYPE_TAG('n','l','c','k'), + DWRITE_FONT_FEATURE_TAG_OLD_STYLE_FIGURES = DWRITE_MAKE_OPENTYPE_TAG('o','n','u','m'), + DWRITE_FONT_FEATURE_TAG_ORDINALS = DWRITE_MAKE_OPENTYPE_TAG('o','r','d','n'), + DWRITE_FONT_FEATURE_TAG_PROPORTIONAL_ALTERNATE_WIDTH = DWRITE_MAKE_OPENTYPE_TAG('p','a','l','t'), + DWRITE_FONT_FEATURE_TAG_PETITE_CAPITALS = DWRITE_MAKE_OPENTYPE_TAG('p','c','a','p'), + DWRITE_FONT_FEATURE_TAG_PROPORTIONAL_FIGURES = DWRITE_MAKE_OPENTYPE_TAG('p','n','u','m'), + DWRITE_FONT_FEATURE_TAG_PROPORTIONAL_WIDTHS = DWRITE_MAKE_OPENTYPE_TAG('p','w','i','d'), + DWRITE_FONT_FEATURE_TAG_QUARTER_WIDTHS = DWRITE_MAKE_OPENTYPE_TAG('q','w','i','d'), + DWRITE_FONT_FEATURE_TAG_REQUIRED_LIGATURES = DWRITE_MAKE_OPENTYPE_TAG('r','l','i','g'), + DWRITE_FONT_FEATURE_TAG_RUBY_NOTATION_FORMS = DWRITE_MAKE_OPENTYPE_TAG('r','u','b','y'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_ALTERNATES = DWRITE_MAKE_OPENTYPE_TAG('s','a','l','t'), + DWRITE_FONT_FEATURE_TAG_SCIENTIFIC_INFERIORS = DWRITE_MAKE_OPENTYPE_TAG('s','i','n','f'), + DWRITE_FONT_FEATURE_TAG_SMALL_CAPITALS = DWRITE_MAKE_OPENTYPE_TAG('s','m','c','p'), + DWRITE_FONT_FEATURE_TAG_SIMPLIFIED_FORMS = DWRITE_MAKE_OPENTYPE_TAG('s','m','p','l'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_1 = DWRITE_MAKE_OPENTYPE_TAG('s','s','0','1'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_2 = DWRITE_MAKE_OPENTYPE_TAG('s','s','0','2'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_3 = DWRITE_MAKE_OPENTYPE_TAG('s','s','0','3'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_4 = DWRITE_MAKE_OPENTYPE_TAG('s','s','0','4'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_5 = DWRITE_MAKE_OPENTYPE_TAG('s','s','0','5'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_6 = DWRITE_MAKE_OPENTYPE_TAG('s','s','0','6'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_7 = DWRITE_MAKE_OPENTYPE_TAG('s','s','0','7'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_8 = DWRITE_MAKE_OPENTYPE_TAG('s','s','0','8'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_9 = DWRITE_MAKE_OPENTYPE_TAG('s','s','0','9'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_10 = DWRITE_MAKE_OPENTYPE_TAG('s','s','1','0'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_11 = DWRITE_MAKE_OPENTYPE_TAG('s','s','1','1'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_12 = DWRITE_MAKE_OPENTYPE_TAG('s','s','1','2'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_13 = DWRITE_MAKE_OPENTYPE_TAG('s','s','1','3'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_14 = DWRITE_MAKE_OPENTYPE_TAG('s','s','1','4'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_15 = DWRITE_MAKE_OPENTYPE_TAG('s','s','1','5'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_16 = DWRITE_MAKE_OPENTYPE_TAG('s','s','1','6'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_17 = DWRITE_MAKE_OPENTYPE_TAG('s','s','1','7'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_18 = DWRITE_MAKE_OPENTYPE_TAG('s','s','1','8'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_19 = DWRITE_MAKE_OPENTYPE_TAG('s','s','1','9'), + DWRITE_FONT_FEATURE_TAG_STYLISTIC_SET_20 = DWRITE_MAKE_OPENTYPE_TAG('s','s','2','0'), + DWRITE_FONT_FEATURE_TAG_SUBSCRIPT = DWRITE_MAKE_OPENTYPE_TAG('s','u','b','s'), + DWRITE_FONT_FEATURE_TAG_SUPERSCRIPT = DWRITE_MAKE_OPENTYPE_TAG('s','u','p','s'), + DWRITE_FONT_FEATURE_TAG_SWASH = DWRITE_MAKE_OPENTYPE_TAG('s','w','s','h'), + DWRITE_FONT_FEATURE_TAG_TITLING = DWRITE_MAKE_OPENTYPE_TAG('t','i','t','l'), + DWRITE_FONT_FEATURE_TAG_TRADITIONAL_NAME_FORMS = DWRITE_MAKE_OPENTYPE_TAG('t','n','a','m'), + DWRITE_FONT_FEATURE_TAG_TABULAR_FIGURES = DWRITE_MAKE_OPENTYPE_TAG('t','n','u','m'), + DWRITE_FONT_FEATURE_TAG_TRADITIONAL_FORMS = DWRITE_MAKE_OPENTYPE_TAG('t','r','a','d'), + DWRITE_FONT_FEATURE_TAG_THIRD_WIDTHS = DWRITE_MAKE_OPENTYPE_TAG('t','w','i','d'), + DWRITE_FONT_FEATURE_TAG_UNICASE = DWRITE_MAKE_OPENTYPE_TAG('u','n','i','c'), + DWRITE_FONT_FEATURE_TAG_VERTICAL_WRITING = DWRITE_MAKE_OPENTYPE_TAG('v','e','r','t'), + DWRITE_FONT_FEATURE_TAG_VERTICAL_ALTERNATES_AND_ROTATION = DWRITE_MAKE_OPENTYPE_TAG('v','r','t','2'), + DWRITE_FONT_FEATURE_TAG_SLASHED_ZERO = DWRITE_MAKE_OPENTYPE_TAG('z','e','r','o'), +}; + +/// +/// The DWRITE_TEXT_RANGE structure specifies a range of text positions where format is applied. +/// +struct DWRITE_TEXT_RANGE +{ + /// + /// The start text position of the range. + /// + UINT32 startPosition; + + /// + /// The number of text positions in the range. + /// + UINT32 length; +}; + +/// +/// The DWRITE_FONT_FEATURE structure specifies properties used to identify and execute typographic feature in the font. +/// +struct DWRITE_FONT_FEATURE +{ + /// + /// The feature OpenType name identifier. + /// + DWRITE_FONT_FEATURE_TAG nameTag; + + /// + /// Execution parameter of the feature. + /// + /// + /// The parameter should be non-zero to enable the feature. Once enabled, a feature can't be disabled again within + /// the same range. Features requiring a selector use this value to indicate the selector index. + /// + UINT32 parameter; +}; + +/// +/// Defines a set of typographic features to be applied during shaping. +/// Notice the character range which this feature list spans is specified +/// as a separate parameter to GetGlyphs. +/// +struct DWRITE_TYPOGRAPHIC_FEATURES +{ + /// + /// Array of font features. + /// + _Field_size_(featureCount) DWRITE_FONT_FEATURE* features; + + /// + /// The number of features. + /// + UINT32 featureCount; +}; + +/// +/// The DWRITE_TRIMMING structure specifies the trimming option for text overflowing the layout box. +/// +struct DWRITE_TRIMMING +{ + /// + /// Text granularity of which trimming applies. + /// + DWRITE_TRIMMING_GRANULARITY granularity; + + /// + /// Character code used as the delimiter signaling the beginning of the portion of text to be preserved, + /// most useful for path ellipsis, where the delimiter would be a slash. Leave this zero if there is no + /// delimiter. + /// + UINT32 delimiter; + + /// + /// How many occurrences of the delimiter to step back. Leave this zero if there is no delimiter. + /// + UINT32 delimiterCount; +}; + + +interface IDWriteTypography; +interface IDWriteInlineObject; + +/// +/// The format of text used for text layout. +/// +/// +/// This object may not be thread-safe and it may carry the state of text format change. +/// +interface DWRITE_DECLARE_INTERFACE("9c906818-31d7-4fd3-a151-7c5e225db55a") IDWriteTextFormat : public IUnknown +{ + /// + /// Set alignment option of text relative to layout box's leading and trailing edge. + /// + /// Text alignment option + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetTextAlignment)( + DWRITE_TEXT_ALIGNMENT textAlignment + ) PURE; + + /// + /// Set alignment option of paragraph relative to layout box's top and bottom edge. + /// + /// Paragraph alignment option + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetParagraphAlignment)( + DWRITE_PARAGRAPH_ALIGNMENT paragraphAlignment + ) PURE; + + /// + /// Set word wrapping option. + /// + /// Word wrapping option + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetWordWrapping)( + DWRITE_WORD_WRAPPING wordWrapping + ) PURE; + + /// + /// Set paragraph reading direction. + /// + /// Text reading direction + /// + /// Standard HRESULT error code. + /// + /// + /// The flow direction must be perpendicular to the reading direction. + /// Setting both to a vertical direction or both to horizontal yields + /// DWRITE_E_FLOWDIRECTIONCONFLICTS when calling GetMetrics or Draw. + /// + STDMETHOD(SetReadingDirection)( + DWRITE_READING_DIRECTION readingDirection + ) PURE; + + /// + /// Set paragraph flow direction. + /// + /// Paragraph flow direction + /// + /// Standard HRESULT error code. + /// + /// + /// The flow direction must be perpendicular to the reading direction. + /// Setting both to a vertical direction or both to horizontal yields + /// DWRITE_E_FLOWDIRECTIONCONFLICTS when calling GetMetrics or Draw. + /// + STDMETHOD(SetFlowDirection)( + DWRITE_FLOW_DIRECTION flowDirection + ) PURE; + + /// + /// Set incremental tab stop position. + /// + /// The incremental tab stop value + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetIncrementalTabStop)( + FLOAT incrementalTabStop + ) PURE; + + /// + /// Set trimming options for any trailing text exceeding the layout width + /// or for any far text exceeding the layout height. + /// + /// Text trimming options. + /// Application-defined omission sign. This parameter may be NULL if no trimming sign is desired. + /// + /// Any inline object can be used for the trimming sign, but CreateEllipsisTrimmingSign + /// provides a typical ellipsis symbol. Trimming is also useful vertically for hiding + /// partial lines. + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetTrimming)( + _In_ DWRITE_TRIMMING const* trimmingOptions, + _In_opt_ IDWriteInlineObject* trimmingSign + ) PURE; + + /// + /// Set line spacing. + /// + /// How to determine line height. + /// The line height, or rather distance between one baseline to another. + /// Distance from top of line to baseline. A reasonable ratio to lineSpacing is 80%. + /// + /// For the default method, spacing depends solely on the content. + /// For uniform spacing, the given line height will override the content. + /// + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetLineSpacing)( + DWRITE_LINE_SPACING_METHOD lineSpacingMethod, + FLOAT lineSpacing, + FLOAT baseline + ) PURE; + + /// + /// Get alignment option of text relative to layout box's leading and trailing edge. + /// + STDMETHOD_(DWRITE_TEXT_ALIGNMENT, GetTextAlignment)() PURE; + + /// + /// Get alignment option of paragraph relative to layout box's top and bottom edge. + /// + STDMETHOD_(DWRITE_PARAGRAPH_ALIGNMENT, GetParagraphAlignment)() PURE; + + /// + /// Get word wrapping option. + /// + STDMETHOD_(DWRITE_WORD_WRAPPING, GetWordWrapping)() PURE; + + /// + /// Get paragraph reading direction. + /// + STDMETHOD_(DWRITE_READING_DIRECTION, GetReadingDirection)() PURE; + + /// + /// Get paragraph flow direction. + /// + STDMETHOD_(DWRITE_FLOW_DIRECTION, GetFlowDirection)() PURE; + + /// + /// Get incremental tab stop position. + /// + STDMETHOD_(FLOAT, GetIncrementalTabStop)() PURE; + + /// + /// Get trimming options for text overflowing the layout width. + /// + /// Text trimming options. + /// Trimming omission sign. This parameter may be NULL. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetTrimming)( + _Out_ DWRITE_TRIMMING* trimmingOptions, + _COM_Outptr_ IDWriteInlineObject** trimmingSign + ) PURE; + + /// + /// Get line spacing. + /// + /// How line height is determined. + /// The line height, or rather distance between one baseline to another. + /// Distance from top of line to baseline. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetLineSpacing)( + _Out_ DWRITE_LINE_SPACING_METHOD* lineSpacingMethod, + _Out_ FLOAT* lineSpacing, + _Out_ FLOAT* baseline + ) PURE; + + /// + /// Get the font collection. + /// + /// The current font collection. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFontCollection)( + _COM_Outptr_ IDWriteFontCollection** fontCollection + ) PURE; + + /// + /// Get the length of the font family name, in characters, not including the terminating NULL character. + /// + STDMETHOD_(UINT32, GetFontFamilyNameLength)() PURE; + + /// + /// Get a copy of the font family name. + /// + /// Character array that receives the current font family name + /// Size of the character array in character count including the terminated NULL character. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFontFamilyName)( + _Out_writes_z_(nameSize) WCHAR* fontFamilyName, + UINT32 nameSize + ) PURE; + + /// + /// Get the font weight. + /// + STDMETHOD_(DWRITE_FONT_WEIGHT, GetFontWeight)() PURE; + + /// + /// Get the font style. + /// + STDMETHOD_(DWRITE_FONT_STYLE, GetFontStyle)() PURE; + + /// + /// Get the font stretch. + /// + STDMETHOD_(DWRITE_FONT_STRETCH, GetFontStretch)() PURE; + + /// + /// Get the font em height. + /// + STDMETHOD_(FLOAT, GetFontSize)() PURE; + + /// + /// Get the length of the locale name, in characters, not including the terminating NULL character. + /// + STDMETHOD_(UINT32, GetLocaleNameLength)() PURE; + + /// + /// Get a copy of the locale name. + /// + /// Character array that receives the current locale name + /// Size of the character array in character count including the terminated NULL character. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetLocaleName)( + _Out_writes_z_(nameSize) WCHAR* localeName, + UINT32 nameSize + ) PURE; +}; + + +/// +/// Font typography setting. +/// +interface DWRITE_DECLARE_INTERFACE("55f1112b-1dc2-4b3c-9541-f46894ed85b6") IDWriteTypography : public IUnknown +{ + /// + /// Add font feature. + /// + /// The font feature to add. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(AddFontFeature)( + DWRITE_FONT_FEATURE fontFeature + ) PURE; + + /// + /// Get the number of font features. + /// + STDMETHOD_(UINT32, GetFontFeatureCount)() PURE; + + /// + /// Get the font feature at the specified index. + /// + /// The zero-based index of the font feature to get. + /// The font feature. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFontFeature)( + UINT32 fontFeatureIndex, + _Out_ DWRITE_FONT_FEATURE* fontFeature + ) PURE; +}; + +enum DWRITE_SCRIPT_SHAPES +{ + /// + /// No additional shaping requirement. Text is shaped with the writing system default behavior. + /// + DWRITE_SCRIPT_SHAPES_DEFAULT = 0, + + /// + /// Text should leave no visual on display i.e. control or format control characters. + /// + DWRITE_SCRIPT_SHAPES_NO_VISUAL = 1 +}; + +#ifdef DEFINE_ENUM_FLAG_OPERATORS +DEFINE_ENUM_FLAG_OPERATORS(DWRITE_SCRIPT_SHAPES); +#endif + +/// +/// Association of text and its writing system script as well as some display attributes. +/// +struct DWRITE_SCRIPT_ANALYSIS +{ + /// + /// Zero-based index representation of writing system script. + /// + UINT16 script; + + /// + /// Additional shaping requirement of text. + /// + DWRITE_SCRIPT_SHAPES shapes; +}; + +/// +/// Condition at the edges of inline object or text used to determine +/// line-breaking behavior. +/// +enum DWRITE_BREAK_CONDITION +{ + /// + /// Whether a break is allowed is determined by the condition of the + /// neighboring text span or inline object. + /// + DWRITE_BREAK_CONDITION_NEUTRAL, + + /// + /// A break is allowed, unless overruled by the condition of the + /// neighboring text span or inline object, either prohibited by a + /// May Not or forced by a Must. + /// + DWRITE_BREAK_CONDITION_CAN_BREAK, + + /// + /// There should be no break, unless overruled by a Must condition from + /// the neighboring text span or inline object. + /// + DWRITE_BREAK_CONDITION_MAY_NOT_BREAK, + + /// + /// The break must happen, regardless of the condition of the adjacent + /// text span or inline object. + /// + DWRITE_BREAK_CONDITION_MUST_BREAK +}; + +/// +/// Line breakpoint characteristics of a character. +/// +struct DWRITE_LINE_BREAKPOINT +{ + /// + /// Breaking condition before the character. + /// + UINT8 breakConditionBefore : 2; + + /// + /// Breaking condition after the character. + /// + UINT8 breakConditionAfter : 2; + + /// + /// The character is some form of whitespace, which may be meaningful + /// for justification. + /// + UINT8 isWhitespace : 1; + + /// + /// The character is a soft hyphen, often used to indicate hyphenation + /// points inside words. + /// + UINT8 isSoftHyphen : 1; + + UINT8 padding : 2; +}; + +/// +/// How to apply number substitution on digits and related punctuation. +/// +enum DWRITE_NUMBER_SUBSTITUTION_METHOD +{ + /// + /// Specifies that the substitution method should be determined based + /// on LOCALE_IDIGITSUBSTITUTION value of the specified text culture. + /// + DWRITE_NUMBER_SUBSTITUTION_METHOD_FROM_CULTURE, + + /// + /// If the culture is Arabic or Farsi, specifies that the number shape + /// depend on the context. Either traditional or nominal number shape + /// are used depending on the nearest preceding strong character or (if + /// there is none) the reading direction of the paragraph. + /// + DWRITE_NUMBER_SUBSTITUTION_METHOD_CONTEXTUAL, + + /// + /// Specifies that code points 0x30-0x39 are always rendered as nominal numeral + /// shapes (ones of the European number), i.e., no substitution is performed. + /// + DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE, + + /// + /// Specifies that number are rendered using the national number shape + /// as specified by the LOCALE_SNATIVEDIGITS value of the specified text culture. + /// + DWRITE_NUMBER_SUBSTITUTION_METHOD_NATIONAL, + + /// + /// Specifies that number are rendered using the traditional shape + /// for the specified culture. For most cultures, this is the same as + /// NativeNational. However, NativeNational results in Latin number + /// for some Arabic cultures, whereas this value results in Arabic + /// number for all Arabic cultures. + /// + DWRITE_NUMBER_SUBSTITUTION_METHOD_TRADITIONAL +}; + +/// +/// Holds the appropriate digits and numeric punctuation for a given locale. +/// +interface DWRITE_DECLARE_INTERFACE("14885CC9-BAB0-4f90-B6ED-5C366A2CD03D") IDWriteNumberSubstitution : public IUnknown +{ +}; + +/// +/// Shaping output properties per input character. +/// +struct DWRITE_SHAPING_TEXT_PROPERTIES +{ + /// + /// This character can be shaped independently from the others + /// (usually set for the space character). + /// + UINT16 isShapedAlone : 1; + + /// + /// Reserved for use by shaping engine. + /// + UINT16 reserved1 : 1; + + /// + /// Glyph shaping can be cut after this point without affecting shaping + /// before or after it. Otherwise, splitting a call to GetGlyphs would + /// cause a reflow of glyph advances and shapes. + /// + UINT16 canBreakShapingAfter : 1; + + /// + /// Reserved for use by shaping engine. + /// + UINT16 reserved : 13; +}; + +/// +/// Shaping output properties per output glyph. +/// +struct DWRITE_SHAPING_GLYPH_PROPERTIES +{ + /// + /// Justification class, whether to use spacing, kashidas, or + /// another method. This exists for backwards compatibility + /// with Uniscribe's SCRIPT_JUSTIFY enum. + /// + UINT16 justification : 4; + + /// + /// Indicates glyph is the first of a cluster. + /// + UINT16 isClusterStart : 1; + + /// + /// Glyph is a diacritic. + /// + UINT16 isDiacritic : 1; + + /// + /// Glyph has no width, mark, ZWJ, ZWNJ, ZWSP, LRM etc. + /// This flag is not limited to just U+200B. + /// + UINT16 isZeroWidthSpace : 1; + + /// + /// Reserved for use by shaping engine. + /// + UINT16 reserved : 9; +}; + +/// +/// The interface implemented by the text analyzer's client to provide text to +/// the analyzer. It allows the separation between the logical view of text as +/// a continuous stream of characters identifiable by unique text positions, +/// and the actual memory layout of potentially discrete blocks of text in the +/// client's backing store. +/// +/// If any of these callbacks returns an error, the analysis functions will +/// stop prematurely and return a callback error. Rather than return E_NOTIMPL, +/// an application should stub the method and return a constant/null and S_OK. +/// +interface DWRITE_DECLARE_INTERFACE("688e1a58-5094-47c8-adc8-fbcea60ae92b") IDWriteTextAnalysisSource : public IUnknown +{ + /// + /// Get a block of text starting at the specified text position. + /// Returning NULL indicates the end of text - the position is after + /// the last character. This function is called iteratively for + /// each consecutive block, tying together several fragmented blocks + /// in the backing store into a virtual contiguous string. + /// + /// First position of the piece to obtain. All + /// positions are in UTF16 code-units, not whole characters, which + /// matters when supplementary characters are used. + /// Address that receives a pointer to the text block + /// at the specified position. + /// Number of UTF16 units of the retrieved chunk. + /// The returned length is not the length of the block, but the length + /// remaining in the block, from the given position until its end. + /// So querying for a position that is 75 positions into a 100 + /// position block would return 25. + /// Pointer to the first character at the given text position. + /// NULL indicates no chunk available at the specified position, either + /// because textPosition >= the entire text content length or because the + /// queried position is not mapped into the app's backing store. + /// + /// Although apps can implement sparse textual content that only maps part of + /// the backing store, the app must map any text that is in the range passed + /// to any analysis functions. + /// + STDMETHOD(GetTextAtPosition)( + UINT32 textPosition, + _Outptr_result_buffer_(*textLength) WCHAR const** textString, + _Out_ UINT32* textLength + ) PURE; + + /// + /// Get a block of text immediately preceding the specified position. + /// + /// Position immediately after the last position of the chunk to obtain. + /// Address that receives a pointer to the text block + /// at the specified position. + /// Number of UTF16 units of the retrieved block. + /// The length returned is from the given position to the front of + /// the block. + /// Pointer to the first character at (textPosition - textLength). + /// NULL indicates no chunk available at the specified position, either + /// because textPosition == 0,the textPosition > the entire text content + /// length, or the queried position is not mapped into the app's backing + /// store. + /// + /// Although apps can implement sparse textual content that only maps part of + /// the backing store, the app must map any text that is in the range passed + /// to any analysis functions. + /// + STDMETHOD(GetTextBeforePosition)( + UINT32 textPosition, + _Outptr_result_buffer_(*textLength) WCHAR const** textString, + _Out_ UINT32* textLength + ) PURE; + + /// + /// Get paragraph reading direction. + /// + STDMETHOD_(DWRITE_READING_DIRECTION, GetParagraphReadingDirection)() PURE; + + /// + /// Get locale name on the range affected by it. + /// + /// Position to get the locale name of. + /// Receives the length from the given position up to the + /// next differing locale. + /// Address that receives a pointer to the locale + /// at the specified position. + /// + /// The localeName pointer must remain valid until the next call or until + /// the analysis returns. + /// + STDMETHOD(GetLocaleName)( + UINT32 textPosition, + _Out_ UINT32* textLength, + _Outptr_result_z_ WCHAR const** localeName + ) PURE; + + /// + /// Get number substitution on the range affected by it. + /// + /// Position to get the number substitution of. + /// Receives the length from the given position up to the + /// next differing number substitution. + /// Address that receives a pointer to the number substitution + /// at the specified position. + /// + /// Any implementation should return the number substitution with an + /// incremented ref count, and the analysis will release when finished + /// with it (either before the next call or before it returns). However, + /// the sink callback may hold onto it after that. + /// + STDMETHOD(GetNumberSubstitution)( + UINT32 textPosition, + _Out_ UINT32* textLength, + _COM_Outptr_ IDWriteNumberSubstitution** numberSubstitution + ) PURE; +}; + +/// +/// The interface implemented by the text analyzer's client to receive the +/// output of a given text analysis. The Text analyzer disregards any current +/// state of the analysis sink, therefore a Set method call on a range +/// overwrites the previously set analysis result of the same range. +/// +interface DWRITE_DECLARE_INTERFACE("5810cd44-0ca0-4701-b3fa-bec5182ae4f6") IDWriteTextAnalysisSink : public IUnknown +{ + /// + /// Report script analysis for the text range. + /// + /// Starting position to report from. + /// Number of UTF16 units of the reported range. + /// Script analysis of characters in range. + /// + /// A successful code or error code to abort analysis. + /// + STDMETHOD(SetScriptAnalysis)( + UINT32 textPosition, + UINT32 textLength, + _In_ DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis + ) PURE; + + /// + /// Report line-break opportunities for each character, starting from + /// the specified position. + /// + /// Starting position to report from. + /// Number of UTF16 units of the reported range. + /// Breaking conditions for each character. + /// + /// A successful code or error code to abort analysis. + /// + STDMETHOD(SetLineBreakpoints)( + UINT32 textPosition, + UINT32 textLength, + _In_reads_(textLength) DWRITE_LINE_BREAKPOINT const* lineBreakpoints + ) PURE; + + /// + /// Set bidirectional level on the range, called once per each + /// level run change (either explicit or resolved implicit). + /// + /// Starting position to report from. + /// Number of UTF16 units of the reported range. + /// Explicit level from embedded control codes + /// RLE/RLO/LRE/LRO/PDF, determined before any additional rules. + /// Final implicit level considering the + /// explicit level and characters' natural directionality, after all + /// Bidi rules have been applied. + /// + /// A successful code or error code to abort analysis. + /// + STDMETHOD(SetBidiLevel)( + UINT32 textPosition, + UINT32 textLength, + UINT8 explicitLevel, + UINT8 resolvedLevel + ) PURE; + + /// + /// Set number substitution on the range. + /// + /// Starting position to report from. + /// Number of UTF16 units of the reported range. + /// The number substitution applicable to + /// the returned range of text. The sink callback may hold onto it by + /// incrementing its ref count. + /// + /// A successful code or error code to abort analysis. + /// + /// + /// Unlike script and bidi analysis, where every character passed to the + /// analyzer has a result, this will only be called for those ranges where + /// substitution is applicable. For any other range, you will simply not + /// be called. + /// + STDMETHOD(SetNumberSubstitution)( + UINT32 textPosition, + UINT32 textLength, + _In_ IDWriteNumberSubstitution* numberSubstitution + ) PURE; +}; + +/// +/// Analyzes various text properties for complex script processing. +/// +interface DWRITE_DECLARE_INTERFACE("b7e6163e-7f46-43b4-84b3-e4e6249c365d") IDWriteTextAnalyzer : public IUnknown +{ + /// + /// Analyzes a text range for script boundaries, reading text attributes + /// from the source and reporting the Unicode script ID to the sink + /// callback SetScript. + /// + /// Source object to analyze. + /// Starting position within the source object. + /// Length to analyze. + /// Callback object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(AnalyzeScript)( + _In_ IDWriteTextAnalysisSource* analysisSource, + UINT32 textPosition, + UINT32 textLength, + _In_ IDWriteTextAnalysisSink* analysisSink + ) PURE; + + /// + /// Analyzes a text range for script directionality, reading attributes + /// from the source and reporting levels to the sink callback SetBidiLevel. + /// + /// Source object to analyze. + /// Starting position within the source object. + /// Length to analyze. + /// Callback object. + /// + /// Standard HRESULT error code. + /// + /// + /// While the function can handle multiple paragraphs, the text range + /// should not arbitrarily split the middle of paragraphs. Otherwise the + /// returned levels may be wrong, since the Bidi algorithm is meant to + /// apply to the paragraph as a whole. + /// + /// + /// Embedded control codes (LRE/LRO/RLE/RLO/PDF) are taken into account. + /// + STDMETHOD(AnalyzeBidi)( + _In_ IDWriteTextAnalysisSource* analysisSource, + UINT32 textPosition, + UINT32 textLength, + _In_ IDWriteTextAnalysisSink* analysisSink + ) PURE; + + /// + /// Analyzes a text range for spans where number substitution is applicable, + /// reading attributes from the source and reporting substitutable ranges + /// to the sink callback SetNumberSubstitution. + /// + /// Source object to analyze. + /// Starting position within the source object. + /// Length to analyze. + /// Callback object. + /// + /// Standard HRESULT error code. + /// + /// + /// While the function can handle multiple ranges of differing number + /// substitutions, the text ranges should not arbitrarily split the + /// middle of numbers. Otherwise it will treat the numbers separately + /// and will not translate any intervening punctuation. + /// + /// + /// Embedded control codes (LRE/LRO/RLE/RLO/PDF) are taken into account. + /// + STDMETHOD(AnalyzeNumberSubstitution)( + _In_ IDWriteTextAnalysisSource* analysisSource, + UINT32 textPosition, + UINT32 textLength, + _In_ IDWriteTextAnalysisSink* analysisSink + ) PURE; + + /// + /// Analyzes a text range for potential breakpoint opportunities, reading + /// attributes from the source and reporting breakpoint opportunities to + /// the sink callback SetLineBreakpoints. + /// + /// Source object to analyze. + /// Starting position within the source object. + /// Length to analyze. + /// Callback object. + /// + /// Standard HRESULT error code. + /// + /// + /// While the function can handle multiple paragraphs, the text range + /// should not arbitrarily split the middle of paragraphs, unless the + /// given text span is considered a whole unit. Otherwise the + /// returned properties for the first and last characters will + /// inappropriately allow breaks. + /// + /// + /// Special cases include the first, last, and surrogate characters. Any + /// text span is treated as if adjacent to inline objects on either side. + /// So the rules with contingent-break opportunities are used, where the + /// edge between text and inline objects is always treated as a potential + /// break opportunity, dependent on any overriding rules of the adjacent + /// objects to prohibit or force the break (see Unicode TR #14). + /// Surrogate pairs never break between. + /// + STDMETHOD(AnalyzeLineBreakpoints)( + _In_ IDWriteTextAnalysisSource* analysisSource, + UINT32 textPosition, + UINT32 textLength, + _In_ IDWriteTextAnalysisSink* analysisSink + ) PURE; + + /// + /// Parses the input text string and maps it to the set of glyphs and associated glyph data + /// according to the font and the writing system's rendering rules. + /// + /// The string to convert to glyphs. + /// The length of textString. + /// The font face to get glyphs from. + /// Set to true if the text is intended to be + /// drawn vertically. + /// Set to TRUE for right-to-left text. + /// Script analysis result from AnalyzeScript. + /// The locale to use when selecting glyphs. + /// e.g. the same character may map to different glyphs for ja-jp vs zh-chs. + /// If this is NULL then the default mapping based on the script is used. + /// Optional number substitution which + /// selects the appropriate glyphs for digits and related numeric characters, + /// depending on the results obtained from AnalyzeNumberSubstitution. Passing + /// null indicates that no substitution is needed and that the digits should + /// receive nominal glyphs. + /// An array of pointers to the sets of typographic + /// features to use in each feature range. + /// The length of each feature range, in characters. + /// The sum of all lengths should be equal to textLength. + /// The number of feature ranges. + /// The maximum number of glyphs that can be + /// returned. + /// The mapping from character ranges to glyph + /// ranges. + /// Per-character output properties. + /// Output glyph indices. + /// Per-glyph output properties. + /// The actual number of glyphs returned if + /// the call succeeds. + /// + /// Standard HRESULT error code. + /// + /// + /// Note that the mapping from characters to glyphs is, in general, many- + /// to-many. The recommended estimate for the per-glyph output buffers is + /// (3 * textLength / 2 + 16). This is not guaranteed to be sufficient. + /// + /// The value of the actualGlyphCount parameter is only valid if the call + /// succeeds. In the event that maxGlyphCount is not big enough + /// E_NOT_SUFFICIENT_BUFFER, which is equivalent to HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), + /// will be returned. The application should allocate a larger buffer and try again. + /// + STDMETHOD(GetGlyphs)( + _In_reads_(textLength) WCHAR const* textString, + UINT32 textLength, + _In_ IDWriteFontFace* fontFace, + BOOL isSideways, + BOOL isRightToLeft, + _In_ DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis, + _In_opt_z_ WCHAR const* localeName, + _In_opt_ IDWriteNumberSubstitution* numberSubstitution, + _In_reads_opt_(featureRanges) DWRITE_TYPOGRAPHIC_FEATURES const** features, + _In_reads_opt_(featureRanges) UINT32 const* featureRangeLengths, + UINT32 featureRanges, + UINT32 maxGlyphCount, + _Out_writes_(textLength) UINT16* clusterMap, + _Out_writes_(textLength) DWRITE_SHAPING_TEXT_PROPERTIES* textProps, + _Out_writes_(maxGlyphCount) UINT16* glyphIndices, + _Out_writes_(maxGlyphCount) DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProps, + _Out_ UINT32* actualGlyphCount + ) PURE; + + /// + /// Place glyphs output from the GetGlyphs method according to the font + /// and the writing system's rendering rules. + /// + /// The original string the glyphs came from. + /// The mapping from character ranges to glyph + /// ranges. Returned by GetGlyphs. + /// Per-character properties. Returned by + /// GetGlyphs. + /// The length of textString. + /// Glyph indices. See GetGlyphs + /// Per-glyph properties. See GetGlyphs + /// The number of glyphs. + /// The font face the glyphs came from. + /// Logical font size in DIP's. + /// Set to true if the text is intended to be + /// drawn vertically. + /// Set to TRUE for right-to-left text. + /// Script analysis result from AnalyzeScript. + /// The locale to use when selecting glyphs. + /// e.g. the same character may map to different glyphs for ja-jp vs zh-chs. + /// If this is NULL then the default mapping based on the script is used. + /// An array of pointers to the sets of typographic + /// features to use in each feature range. + /// The length of each feature range, in characters. + /// The sum of all lengths should be equal to textLength. + /// The number of feature ranges. + /// The advance width of each glyph. + /// The offset of the origin of each glyph. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetGlyphPlacements)( + _In_reads_(textLength) WCHAR const* textString, + _In_reads_(textLength) UINT16 const* clusterMap, + _Inout_updates_(textLength) DWRITE_SHAPING_TEXT_PROPERTIES* textProps, + UINT32 textLength, + _In_reads_(glyphCount) UINT16 const* glyphIndices, + _In_reads_(glyphCount) DWRITE_SHAPING_GLYPH_PROPERTIES const* glyphProps, + UINT32 glyphCount, + _In_ IDWriteFontFace* fontFace, + FLOAT fontEmSize, + BOOL isSideways, + BOOL isRightToLeft, + _In_ DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis, + _In_opt_z_ WCHAR const* localeName, + _In_reads_opt_(featureRanges) DWRITE_TYPOGRAPHIC_FEATURES const** features, + _In_reads_opt_(featureRanges) UINT32 const* featureRangeLengths, + UINT32 featureRanges, + _Out_writes_(glyphCount) FLOAT* glyphAdvances, + _Out_writes_(glyphCount) DWRITE_GLYPH_OFFSET* glyphOffsets + ) PURE; + + /// + /// Place glyphs output from the GetGlyphs method according to the font + /// and the writing system's rendering rules. + /// + /// The original string the glyphs came from. + /// The mapping from character ranges to glyph + /// ranges. Returned by GetGlyphs. + /// Per-character properties. Returned by + /// GetGlyphs. + /// The length of textString. + /// Glyph indices. See GetGlyphs + /// Per-glyph properties. See GetGlyphs + /// The number of glyphs. + /// The font face the glyphs came from. + /// Logical font size in DIP's. + /// Number of physical pixels per DIP. For example, if the DPI of the rendering surface is 96 this + /// value is 1.0f. If the DPI is 120, this value is 120.0f/96. + /// Optional transform applied to the glyphs and their positions. This transform is applied after the + /// scaling specified by the font size and pixelsPerDip. + /// + /// When set to FALSE, the metrics are the same as the metrics of GDI aliased text. + /// When set to TRUE, the metrics are the same as the metrics of text measured by GDI using a font + /// created with CLEARTYPE_NATURAL_QUALITY. + /// + /// Set to true if the text is intended to be + /// drawn vertically. + /// Set to TRUE for right-to-left text. + /// Script analysis result from AnalyzeScript. + /// The locale to use when selecting glyphs. + /// e.g. the same character may map to different glyphs for ja-jp vs zh-chs. + /// If this is NULL then the default mapping based on the script is used. + /// An array of pointers to the sets of typographic + /// features to use in each feature range. + /// The length of each feature range, in characters. + /// The sum of all lengths should be equal to textLength. + /// The number of feature ranges. + /// The advance width of each glyph. + /// The offset of the origin of each glyph. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetGdiCompatibleGlyphPlacements)( + _In_reads_(textLength) WCHAR const* textString, + _In_reads_(textLength) UINT16 const* clusterMap, + _In_reads_(textLength) DWRITE_SHAPING_TEXT_PROPERTIES* textProps, + UINT32 textLength, + _In_reads_(glyphCount) UINT16 const* glyphIndices, + _In_reads_(glyphCount) DWRITE_SHAPING_GLYPH_PROPERTIES const* glyphProps, + UINT32 glyphCount, + _In_ IDWriteFontFace * fontFace, + FLOAT fontEmSize, + FLOAT pixelsPerDip, + _In_opt_ DWRITE_MATRIX const* transform, + BOOL useGdiNatural, + BOOL isSideways, + BOOL isRightToLeft, + _In_ DWRITE_SCRIPT_ANALYSIS const* scriptAnalysis, + _In_opt_z_ WCHAR const* localeName, + _In_reads_opt_(featureRanges) DWRITE_TYPOGRAPHIC_FEATURES const** features, + _In_reads_opt_(featureRanges) UINT32 const* featureRangeLengths, + UINT32 featureRanges, + _Out_writes_(glyphCount) FLOAT* glyphAdvances, + _Out_writes_(glyphCount) DWRITE_GLYPH_OFFSET* glyphOffsets + ) PURE; +}; + +/// +/// The DWRITE_GLYPH_RUN structure contains the information needed by renderers +/// to draw glyph runs. All coordinates are in device independent pixels (DIPs). +/// +struct DWRITE_GLYPH_RUN +{ + /// + /// The physical font face to draw with. + /// + _Notnull_ IDWriteFontFace* fontFace; + + /// + /// Logical size of the font in DIPs, not points (equals 1/96 inch). + /// + FLOAT fontEmSize; + + /// + /// The number of glyphs. + /// + UINT32 glyphCount; + + /// + /// The indices to render. + /// + _Field_size_(glyphCount) UINT16 const* glyphIndices; + + /// + /// Glyph advance widths. + /// + _Field_size_opt_(glyphCount) FLOAT const* glyphAdvances; + + /// + /// Glyph offsets. + /// + _Field_size_opt_(glyphCount) DWRITE_GLYPH_OFFSET const* glyphOffsets; + + /// + /// If true, specifies that glyphs are rotated 90 degrees to the left and + /// vertical metrics are used. Vertical writing is achieved by specifying + /// isSideways = true and rotating the entire run 90 degrees to the right + /// via a rotate transform. + /// + BOOL isSideways; + + /// + /// The implicit resolved bidi level of the run. Odd levels indicate + /// right-to-left languages like Hebrew and Arabic, while even levels + /// indicate left-to-right languages like English and Japanese (when + /// written horizontally). For right-to-left languages, the text origin + /// is on the right, and text should be drawn to the left. + /// + UINT32 bidiLevel; +}; + +/// +/// The DWRITE_GLYPH_RUN_DESCRIPTION structure contains additional properties +/// related to those in DWRITE_GLYPH_RUN. +/// +struct DWRITE_GLYPH_RUN_DESCRIPTION +{ + /// + /// The locale name associated with this run. + /// + _Field_z_ WCHAR const* localeName; + + /// + /// The text associated with the glyphs. + /// + _Field_size_(stringLength) WCHAR const* string; + + /// + /// The number of characters (UTF16 code-units). + /// Note that this may be different than the number of glyphs. + /// + UINT32 stringLength; + + /// + /// An array of indices to the glyph indices array, of the first glyphs of + /// all the glyph clusters of the glyphs to render. + /// + _Field_size_opt_(stringLength) UINT16 const* clusterMap; + + /// + /// Corresponding text position in the original string + /// this glyph run came from. + /// + UINT32 textPosition; +}; + +/// +/// The DWRITE_UNDERLINE structure contains information about the size and +/// placement of underlines. All coordinates are in device independent +/// pixels (DIPs). +/// +struct DWRITE_UNDERLINE +{ + /// + /// Width of the underline, measured parallel to the baseline. + /// + FLOAT width; + + /// + /// Thickness of the underline, measured perpendicular to the + /// baseline. + /// + FLOAT thickness; + + /// + /// Offset of the underline from the baseline. + /// A positive offset represents a position below the baseline and + /// a negative offset is above. + /// + FLOAT offset; + + /// + /// Height of the tallest run where the underline applies. + /// + FLOAT runHeight; + + /// + /// Reading direction of the text associated with the underline. This + /// value is used to interpret whether the width value runs horizontally + /// or vertically. + /// + DWRITE_READING_DIRECTION readingDirection; + + /// + /// Flow direction of the text associated with the underline. This value + /// is used to interpret whether the thickness value advances top to + /// bottom, left to right, or right to left. + /// + DWRITE_FLOW_DIRECTION flowDirection; + + /// + /// Locale of the text the underline is being drawn under. Can be + /// pertinent where the locale affects how the underline is drawn. + /// For example, in vertical text, the underline belongs on the + /// left for Chinese but on the right for Japanese. + /// This choice is completely left up to higher levels. + /// + _Field_z_ WCHAR const* localeName; + + /// + /// The measuring mode can be useful to the renderer to determine how + /// underlines are rendered, e.g. rounding the thickness to a whole pixel + /// in GDI-compatible modes. + /// + DWRITE_MEASURING_MODE measuringMode; +}; + +/// +/// The DWRITE_STRIKETHROUGH structure contains information about the size and +/// placement of strikethroughs. All coordinates are in device independent +/// pixels (DIPs). +/// +struct DWRITE_STRIKETHROUGH +{ + /// + /// Width of the strikethrough, measured parallel to the baseline. + /// + FLOAT width; + + /// + /// Thickness of the strikethrough, measured perpendicular to the + /// baseline. + /// + FLOAT thickness; + + /// + /// Offset of the strikethrough from the baseline. + /// A positive offset represents a position below the baseline and + /// a negative offset is above. + /// + FLOAT offset; + + /// + /// Reading direction of the text associated with the strikethrough. This + /// value is used to interpret whether the width value runs horizontally + /// or vertically. + /// + DWRITE_READING_DIRECTION readingDirection; + + /// + /// Flow direction of the text associated with the strikethrough. This + /// value is used to interpret whether the thickness value advances top to + /// bottom, left to right, or right to left. + /// + DWRITE_FLOW_DIRECTION flowDirection; + + /// + /// Locale of the range. Can be pertinent where the locale affects the style. + /// + _Field_z_ WCHAR const* localeName; + + /// + /// The measuring mode can be useful to the renderer to determine how + /// underlines are rendered, e.g. rounding the thickness to a whole pixel + /// in GDI-compatible modes. + /// + DWRITE_MEASURING_MODE measuringMode; +}; + +/// +/// The DWRITE_LINE_METRICS structure contains information about a formatted +/// line of text. +/// +struct DWRITE_LINE_METRICS +{ + /// + /// The number of total text positions in the line. + /// This includes any trailing whitespace and newline characters. + /// + UINT32 length; + + /// + /// The number of whitespace positions at the end of the line. Newline + /// sequences are considered whitespace. + /// + UINT32 trailingWhitespaceLength; + + /// + /// The number of characters in the newline sequence at the end of the line. + /// If the count is zero, then the line was either wrapped or it is the + /// end of the text. + /// + UINT32 newlineLength; + + /// + /// Height of the line as measured from top to bottom. + /// + FLOAT height; + + /// + /// Distance from the top of the line to its baseline. + /// + FLOAT baseline; + + /// + /// The line is trimmed. + /// + BOOL isTrimmed; +}; + + +/// +/// The DWRITE_CLUSTER_METRICS structure contains information about a glyph cluster. +/// +struct DWRITE_CLUSTER_METRICS +{ + /// + /// The total advance width of all glyphs in the cluster. + /// + FLOAT width; + + /// + /// The number of text positions in the cluster. + /// + UINT16 length; + + /// + /// Indicate whether line can be broken right after the cluster. + /// + UINT16 canWrapLineAfter : 1; + + /// + /// Indicate whether the cluster corresponds to whitespace character. + /// + UINT16 isWhitespace : 1; + + /// + /// Indicate whether the cluster corresponds to a newline character. + /// + UINT16 isNewline : 1; + + /// + /// Indicate whether the cluster corresponds to soft hyphen character. + /// + UINT16 isSoftHyphen : 1; + + /// + /// Indicate whether the cluster is read from right to left. + /// + UINT16 isRightToLeft : 1; + + UINT16 padding : 11; +}; + + +/// +/// Overall metrics associated with text after layout. +/// All coordinates are in device independent pixels (DIPs). +/// +struct DWRITE_TEXT_METRICS +{ + /// + /// Left-most point of formatted text relative to layout box + /// (excluding any glyph overhang). + /// + FLOAT left; + + /// + /// Top-most point of formatted text relative to layout box + /// (excluding any glyph overhang). + /// + FLOAT top; + + /// + /// The width of the formatted text ignoring trailing whitespace + /// at the end of each line. + /// + FLOAT width; + + /// + /// The width of the formatted text taking into account the + /// trailing whitespace at the end of each line. + /// + FLOAT widthIncludingTrailingWhitespace; + + /// + /// The height of the formatted text. The height of an empty string + /// is determined by the size of the default font's line height. + /// + FLOAT height; + + /// + /// Initial width given to the layout. Depending on whether the text + /// was wrapped or not, it can be either larger or smaller than the + /// text content width. + /// + FLOAT layoutWidth; + + /// + /// Initial height given to the layout. Depending on the length of the + /// text, it may be larger or smaller than the text content height. + /// + FLOAT layoutHeight; + + /// + /// The maximum reordering count of any line of text, used + /// to calculate the most number of hit-testing boxes needed. + /// If the layout has no bidirectional text or no text at all, + /// the minimum level is 1. + /// + UINT32 maxBidiReorderingDepth; + + /// + /// Total number of lines. + /// + UINT32 lineCount; +}; + + +/// +/// Properties describing the geometric measurement of an +/// application-defined inline object. +/// +struct DWRITE_INLINE_OBJECT_METRICS +{ + /// + /// Width of the inline object. + /// + FLOAT width; + + /// + /// Height of the inline object as measured from top to bottom. + /// + FLOAT height; + + /// + /// Distance from the top of the object to the baseline where it is lined up with the adjacent text. + /// If the baseline is at the bottom, baseline simply equals height. + /// + FLOAT baseline; + + /// + /// Flag indicating whether the object is to be placed upright or alongside the text baseline + /// for vertical text. + /// + BOOL supportsSideways; +}; + + +/// +/// The DWRITE_OVERHANG_METRICS structure holds how much any visible pixels +/// (in DIPs) overshoot each side of the layout or inline objects. +/// +/// +/// Positive overhangs indicate that the visible area extends outside the layout +/// box or inline object, while negative values mean there is whitespace inside. +/// The returned values are unaffected by rendering transforms or pixel snapping. +/// Additionally, they may not exactly match final target's pixel bounds after +/// applying grid fitting and hinting. +/// +struct DWRITE_OVERHANG_METRICS +{ + /// + /// The distance from the left-most visible DIP to its left alignment edge. + /// + FLOAT left; + + /// + /// The distance from the top-most visible DIP to its top alignment edge. + /// + FLOAT top; + + /// + /// The distance from the right-most visible DIP to its right alignment edge. + /// + FLOAT right; + + /// + /// The distance from the bottom-most visible DIP to its bottom alignment edge. + /// + FLOAT bottom; +}; + + +/// +/// Geometry enclosing of text positions. +/// +struct DWRITE_HIT_TEST_METRICS +{ + /// + /// First text position within the geometry. + /// + UINT32 textPosition; + + /// + /// Number of text positions within the geometry. + /// + UINT32 length; + + /// + /// Left position of the top-left coordinate of the geometry. + /// + FLOAT left; + + /// + /// Top position of the top-left coordinate of the geometry. + /// + FLOAT top; + + /// + /// Geometry's width. + /// + FLOAT width; + + /// + /// Geometry's height. + /// + FLOAT height; + + /// + /// Bidi level of text positions enclosed within the geometry. + /// + UINT32 bidiLevel; + + /// + /// Geometry encloses text? + /// + BOOL isText; + + /// + /// Range is trimmed. + /// + BOOL isTrimmed; +}; + + +interface IDWriteTextRenderer; + + +/// +/// The IDWriteInlineObject interface wraps an application defined inline graphic, +/// allowing DWrite to query metrics as if it was a glyph inline with the text. +/// +interface DWRITE_DECLARE_INTERFACE("8339FDE3-106F-47ab-8373-1C6295EB10B3") IDWriteInlineObject : public IUnknown +{ + /// + /// The application implemented rendering callback (IDWriteTextRenderer::DrawInlineObject) + /// can use this to draw the inline object without needing to cast or query the object + /// type. The text layout does not call this method directly. + /// + /// The context passed to IDWriteTextLayout::Draw. + /// The renderer passed to IDWriteTextLayout::Draw as the object's containing parent. + /// X-coordinate at the top-left corner of the inline object. + /// Y-coordinate at the top-left corner of the inline object. + /// The object should be drawn on its side. + /// The object is in an right-to-left context and should be drawn flipped. + /// The drawing effect set in IDWriteTextLayout::SetDrawingEffect. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(Draw)( + _In_opt_ void* clientDrawingContext, + _In_ IDWriteTextRenderer* renderer, + FLOAT originX, + FLOAT originY, + BOOL isSideways, + BOOL isRightToLeft, + _In_opt_ IUnknown* clientDrawingEffect + ) PURE; + + /// + /// TextLayout calls this callback function to get the measurement of the inline object. + /// + /// Returned metrics + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetMetrics)( + _Out_ DWRITE_INLINE_OBJECT_METRICS* metrics + ) PURE; + + /// + /// TextLayout calls this callback function to get the visible extents (in DIPs) of the inline object. + /// In the case of a simple bitmap, with no padding and no overhang, all the overhangs will + /// simply be zeroes. + /// + /// Overshoot of visible extents (in DIPs) outside the object. + /// + /// Standard HRESULT error code. + /// + /// + /// The overhangs should be returned relative to the reported size of the object + /// (DWRITE_INLINE_OBJECT_METRICS::width/height), and should not be baseline + /// adjusted. If you have an image that is actually 100x100 DIPs, but you want it + /// slightly inset (perhaps it has a glow) by 20 DIPs on each side, you would + /// return a width/height of 60x60 and four overhangs of 20 DIPs. + /// + STDMETHOD(GetOverhangMetrics)( + _Out_ DWRITE_OVERHANG_METRICS* overhangs + ) PURE; + + /// + /// Layout uses this to determine the line breaking behavior of the inline object + /// amidst the text. + /// + /// Line-breaking condition between the object and the content immediately preceding it. + /// Line-breaking condition between the object and the content immediately following it. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetBreakConditions)( + _Out_ DWRITE_BREAK_CONDITION* breakConditionBefore, + _Out_ DWRITE_BREAK_CONDITION* breakConditionAfter + ) PURE; +}; + +/// +/// The IDWritePixelSnapping interface defines the pixel snapping properties of a text renderer. +/// +interface DWRITE_DECLARE_INTERFACE("eaf3a2da-ecf4-4d24-b644-b34f6842024b") IDWritePixelSnapping : public IUnknown +{ + /// + /// Determines whether pixel snapping is disabled. The recommended default is FALSE, + /// unless doing animation that requires subpixel vertical placement. + /// + /// The context passed to IDWriteTextLayout::Draw. + /// Receives TRUE if pixel snapping is disabled or FALSE if it not. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(IsPixelSnappingDisabled)( + _In_opt_ void* clientDrawingContext, + _Out_ BOOL* isDisabled + ) PURE; + + /// + /// Gets the current transform that maps abstract coordinates to DIPs, + /// which may disable pixel snapping upon any rotation or shear. + /// + /// The context passed to IDWriteTextLayout::Draw. + /// Receives the transform. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetCurrentTransform)( + _In_opt_ void* clientDrawingContext, + _Out_ DWRITE_MATRIX* transform + ) PURE; + + /// + /// Gets the number of physical pixels per DIP. A DIP (device-independent pixel) is 1/96 inch, + /// so the pixelsPerDip value is the number of logical pixels per inch divided by 96 (yielding + /// a value of 1 for 96 DPI and 1.25 for 120). + /// + /// The context passed to IDWriteTextLayout::Draw. + /// Receives the number of physical pixels per DIP. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetPixelsPerDip)( + _In_opt_ void* clientDrawingContext, + _Out_ FLOAT* pixelsPerDip + ) PURE; +}; + +/// +/// The IDWriteTextRenderer interface represents a set of application-defined +/// callbacks that perform rendering of text, inline objects, and decorations +/// such as underlines. +/// +interface DWRITE_DECLARE_INTERFACE("ef8a8135-5cc6-45fe-8825-c5a0724eb819") IDWriteTextRenderer : public IDWritePixelSnapping +{ + /// + /// IDWriteTextLayout::Draw calls this function to instruct the client to + /// render a run of glyphs. + /// + /// The context passed to + /// IDWriteTextLayout::Draw. + /// X-coordinate of the baseline. + /// Y-coordinate of the baseline. + /// Specifies measuring mode for glyphs in the run. + /// Renderer implementations may choose different rendering modes for given measuring modes, + /// but best results are seen when the rendering mode matches the corresponding measuring mode: + /// DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL for DWRITE_MEASURING_MODE_NATURAL + /// DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC for DWRITE_MEASURING_MODE_GDI_CLASSIC + /// DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL for DWRITE_MEASURING_MODE_GDI_NATURAL + /// + /// The glyph run to draw. + /// Properties of the characters + /// associated with this run. + /// The drawing effect set in + /// IDWriteTextLayout::SetDrawingEffect. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(DrawGlyphRun)( + _In_opt_ void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + DWRITE_MEASURING_MODE measuringMode, + _In_ DWRITE_GLYPH_RUN const* glyphRun, + _In_ DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, + _In_opt_ IUnknown* clientDrawingEffect + ) PURE; + + /// + /// IDWriteTextLayout::Draw calls this function to instruct the client to draw + /// an underline. + /// + /// The context passed to + /// IDWriteTextLayout::Draw. + /// X-coordinate of the baseline. + /// Y-coordinate of the baseline. + /// Underline logical information. + /// The drawing effect set in + /// IDWriteTextLayout::SetDrawingEffect. + /// + /// Standard HRESULT error code. + /// + /// + /// A single underline can be broken into multiple calls, depending on + /// how the formatting changes attributes. If font sizes/styles change + /// within an underline, the thickness and offset will be averaged + /// weighted according to characters. + /// To get the correct top coordinate of the underline rect, add underline::offset + /// to the baseline's Y. Otherwise the underline will be immediately under the text. + /// The x coordinate will always be passed as the left side, regardless + /// of text directionality. This simplifies drawing and reduces the + /// problem of round-off that could potentially cause gaps or a double + /// stamped alpha blend. To avoid alpha overlap, round the end points + /// to the nearest device pixel. + /// + STDMETHOD(DrawUnderline)( + _In_opt_ void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + _In_ DWRITE_UNDERLINE const* underline, + _In_opt_ IUnknown* clientDrawingEffect + ) PURE; + + /// + /// IDWriteTextLayout::Draw calls this function to instruct the client to draw + /// a strikethrough. + /// + /// The context passed to + /// IDWriteTextLayout::Draw. + /// X-coordinate of the baseline. + /// Y-coordinate of the baseline. + /// Strikethrough logical information. + /// The drawing effect set in + /// IDWriteTextLayout::SetDrawingEffect. + /// + /// Standard HRESULT error code. + /// + /// + /// A single strikethrough can be broken into multiple calls, depending on + /// how the formatting changes attributes. Strikethrough is not averaged + /// across font sizes/styles changes. + /// To get the correct top coordinate of the strikethrough rect, + /// add strikethrough::offset to the baseline's Y. + /// Like underlines, the x coordinate will always be passed as the left side, + /// regardless of text directionality. + /// + STDMETHOD(DrawStrikethrough)( + _In_opt_ void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + _In_ DWRITE_STRIKETHROUGH const* strikethrough, + _In_opt_ IUnknown* clientDrawingEffect + ) PURE; + + /// + /// IDWriteTextLayout::Draw calls this application callback when it needs to + /// draw an inline object. + /// + /// The context passed to IDWriteTextLayout::Draw. + /// X-coordinate at the top-left corner of the inline object. + /// Y-coordinate at the top-left corner of the inline object. + /// The object set using IDWriteTextLayout::SetInlineObject. + /// The object should be drawn on its side. + /// The object is in an right-to-left context and should be drawn flipped. + /// The drawing effect set in + /// IDWriteTextLayout::SetDrawingEffect. + /// + /// Standard HRESULT error code. + /// + /// + /// The right-to-left flag is a hint for those cases where it would look + /// strange for the image to be shown normally (like an arrow pointing to + /// right to indicate a submenu). + /// + STDMETHOD(DrawInlineObject)( + _In_opt_ void* clientDrawingContext, + FLOAT originX, + FLOAT originY, + _In_ IDWriteInlineObject* inlineObject, + BOOL isSideways, + BOOL isRightToLeft, + _In_opt_ IUnknown* clientDrawingEffect + ) PURE; +}; + +/// +/// The IDWriteTextLayout interface represents a block of text after it has +/// been fully analyzed and formatted. +/// +/// All coordinates are in device independent pixels (DIPs). +/// +interface DWRITE_DECLARE_INTERFACE("53737037-6d14-410b-9bfe-0b182bb70961") IDWriteTextLayout : public IDWriteTextFormat +{ + /// + /// Set layout maximum width + /// + /// Layout maximum width + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetMaxWidth)( + FLOAT maxWidth + ) PURE; + + /// + /// Set layout maximum height + /// + /// Layout maximum height + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetMaxHeight)( + FLOAT maxHeight + ) PURE; + + /// + /// Set the font collection. + /// + /// The font collection to set + /// Text range to which this change applies. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetFontCollection)( + _In_ IDWriteFontCollection* fontCollection, + DWRITE_TEXT_RANGE textRange + ) PURE; + + /// + /// Set null-terminated font family name. + /// + /// Font family name + /// Text range to which this change applies. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetFontFamilyName)( + _In_z_ WCHAR const* fontFamilyName, + DWRITE_TEXT_RANGE textRange + ) PURE; + + /// + /// Set font weight. + /// + /// Font weight + /// Text range to which this change applies. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetFontWeight)( + DWRITE_FONT_WEIGHT fontWeight, + DWRITE_TEXT_RANGE textRange + ) PURE; + + /// + /// Set font style. + /// + /// Font style + /// Text range to which this change applies. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetFontStyle)( + DWRITE_FONT_STYLE fontStyle, + DWRITE_TEXT_RANGE textRange + ) PURE; + + /// + /// Set font stretch. + /// + /// font stretch + /// Text range to which this change applies. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetFontStretch)( + DWRITE_FONT_STRETCH fontStretch, + DWRITE_TEXT_RANGE textRange + ) PURE; + + /// + /// Set font em height. + /// + /// Font em height + /// Text range to which this change applies. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetFontSize)( + FLOAT fontSize, + DWRITE_TEXT_RANGE textRange + ) PURE; + + /// + /// Set underline. + /// + /// The Boolean flag indicates whether underline takes place + /// Text range to which this change applies. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetUnderline)( + BOOL hasUnderline, + DWRITE_TEXT_RANGE textRange + ) PURE; + + /// + /// Set strikethrough. + /// + /// The Boolean flag indicates whether strikethrough takes place + /// Text range to which this change applies. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetStrikethrough)( + BOOL hasStrikethrough, + DWRITE_TEXT_RANGE textRange + ) PURE; + + /// + /// Set application-defined drawing effect. + /// + /// Pointer to an application-defined drawing effect. + /// Text range to which this change applies. + /// + /// Standard HRESULT error code. + /// + /// + /// This drawing effect is associated with the specified range and will be passed back + /// to the application via the callback when the range is drawn at drawing time. + /// + STDMETHOD(SetDrawingEffect)( + IUnknown* drawingEffect, + DWRITE_TEXT_RANGE textRange + ) PURE; + + /// + /// Set inline object. + /// + /// Pointer to an application-implemented inline object. + /// Text range to which this change applies. + /// + /// Standard HRESULT error code. + /// + /// + /// This inline object applies to the specified range and will be passed back + /// to the application via the DrawInlineObject callback when the range is drawn. + /// Any text in that range will be suppressed. + /// + STDMETHOD(SetInlineObject)( + _In_ IDWriteInlineObject* inlineObject, + DWRITE_TEXT_RANGE textRange + ) PURE; + + /// + /// Set font typography features. + /// + /// Pointer to font typography setting. + /// Text range to which this change applies. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetTypography)( + _In_ IDWriteTypography* typography, + DWRITE_TEXT_RANGE textRange + ) PURE; + + /// + /// Set locale name. + /// + /// Locale name + /// Text range to which this change applies. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetLocaleName)( + _In_z_ WCHAR const* localeName, + DWRITE_TEXT_RANGE textRange + ) PURE; + + /// + /// Get layout maximum width + /// + STDMETHOD_(FLOAT, GetMaxWidth)() PURE; + + /// + /// Get layout maximum height + /// + STDMETHOD_(FLOAT, GetMaxHeight)() PURE; + + /// + /// Get the font collection where the current position is at. + /// + /// The current text position. + /// The current font collection + /// Text range to which this change applies. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFontCollection)( + UINT32 currentPosition, + _COM_Outptr_ IDWriteFontCollection** fontCollection, + _Out_opt_ DWRITE_TEXT_RANGE* textRange = NULL + ) PURE; + + /// + /// Get the length of the font family name where the current position is at. + /// + /// The current text position. + /// Size of the character array in character count not including the terminated NULL character. + /// The position range of the current format. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFontFamilyNameLength)( + UINT32 currentPosition, + _Out_ UINT32* nameLength, + _Out_opt_ DWRITE_TEXT_RANGE* textRange = NULL + ) PURE; + + /// + /// Copy the font family name where the current position is at. + /// + /// The current text position. + /// Character array that receives the current font family name + /// Size of the character array in character count including the terminated NULL character. + /// The position range of the current format. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFontFamilyName)( + UINT32 currentPosition, + _Out_writes_z_(nameSize) WCHAR* fontFamilyName, + UINT32 nameSize, + _Out_opt_ DWRITE_TEXT_RANGE* textRange = NULL + ) PURE; + + /// + /// Get the font weight where the current position is at. + /// + /// The current text position. + /// The current font weight + /// The position range of the current format. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFontWeight)( + UINT32 currentPosition, + _Out_ DWRITE_FONT_WEIGHT* fontWeight, + _Out_opt_ DWRITE_TEXT_RANGE* textRange = NULL + ) PURE; + + /// + /// Get the font style where the current position is at. + /// + /// The current text position. + /// The current font style + /// The position range of the current format. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFontStyle)( + UINT32 currentPosition, + _Out_ DWRITE_FONT_STYLE* fontStyle, + _Out_opt_ DWRITE_TEXT_RANGE* textRange = NULL + ) PURE; + + /// + /// Get the font stretch where the current position is at. + /// + /// The current text position. + /// The current font stretch + /// The position range of the current format. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFontStretch)( + UINT32 currentPosition, + _Out_ DWRITE_FONT_STRETCH* fontStretch, + _Out_opt_ DWRITE_TEXT_RANGE* textRange = NULL + ) PURE; + + /// + /// Get the font em height where the current position is at. + /// + /// The current text position. + /// The current font em height + /// The position range of the current format. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetFontSize)( + UINT32 currentPosition, + _Out_ FLOAT* fontSize, + _Out_opt_ DWRITE_TEXT_RANGE* textRange = NULL + ) PURE; + + /// + /// Get the underline presence where the current position is at. + /// + /// The current text position. + /// The Boolean flag indicates whether text is underlined. + /// The position range of the current format. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetUnderline)( + UINT32 currentPosition, + _Out_ BOOL* hasUnderline, + _Out_opt_ DWRITE_TEXT_RANGE* textRange = NULL + ) PURE; + + /// + /// Get the strikethrough presence where the current position is at. + /// + /// The current text position. + /// The Boolean flag indicates whether text has strikethrough. + /// The position range of the current format. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetStrikethrough)( + UINT32 currentPosition, + _Out_ BOOL* hasStrikethrough, + _Out_opt_ DWRITE_TEXT_RANGE* textRange = NULL + ) PURE; + + /// + /// Get the application-defined drawing effect where the current position is at. + /// + /// The current text position. + /// The current application-defined drawing effect. + /// The position range of the current format. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetDrawingEffect)( + UINT32 currentPosition, + _COM_Outptr_ IUnknown** drawingEffect, + _Out_opt_ DWRITE_TEXT_RANGE* textRange = NULL + ) PURE; + + /// + /// Get the inline object at the given position. + /// + /// The given text position. + /// The inline object. + /// The position range of the current format. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetInlineObject)( + UINT32 currentPosition, + _COM_Outptr_ IDWriteInlineObject** inlineObject, + _Out_opt_ DWRITE_TEXT_RANGE* textRange = NULL + ) PURE; + + /// + /// Get the typography setting where the current position is at. + /// + /// The current text position. + /// The current typography setting. + /// The position range of the current format. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetTypography)( + UINT32 currentPosition, + _COM_Outptr_ IDWriteTypography** typography, + _Out_opt_ DWRITE_TEXT_RANGE* textRange = NULL + ) PURE; + + /// + /// Get the length of the locale name where the current position is at. + /// + /// The current text position. + /// Size of the character array in character count not including the terminated NULL character. + /// The position range of the current format. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetLocaleNameLength)( + UINT32 currentPosition, + _Out_ UINT32* nameLength, + _Out_opt_ DWRITE_TEXT_RANGE* textRange = NULL + ) PURE; + + /// + /// Get the locale name where the current position is at. + /// + /// The current text position. + /// Character array that receives the current locale name + /// Size of the character array in character count including the terminated NULL character. + /// The position range of the current format. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetLocaleName)( + UINT32 currentPosition, + _Out_writes_z_(nameSize) WCHAR* localeName, + UINT32 nameSize, + _Out_opt_ DWRITE_TEXT_RANGE* textRange = NULL + ) PURE; + + /// + /// Initiate drawing of the text. + /// + /// An application defined value + /// included in rendering callbacks. + /// The set of application-defined callbacks that do + /// the actual rendering. + /// X-coordinate of the layout's left side. + /// Y-coordinate of the layout's top side. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(Draw)( + _In_opt_ void* clientDrawingContext, + _In_ IDWriteTextRenderer* renderer, + FLOAT originX, + FLOAT originY + ) PURE; + + /// + /// GetLineMetrics returns properties of each line. + /// + /// The array to fill with line information. + /// The maximum size of the lineMetrics array. + /// The actual size of the lineMetrics + /// array that is needed. + /// + /// Standard HRESULT error code. + /// + /// + /// If maxLineCount is not large enough E_NOT_SUFFICIENT_BUFFER, + /// which is equivalent to HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), + /// is returned and *actualLineCount is set to the number of lines + /// needed. + /// + STDMETHOD(GetLineMetrics)( + _Out_writes_opt_(maxLineCount) DWRITE_LINE_METRICS* lineMetrics, + UINT32 maxLineCount, + _Out_ UINT32* actualLineCount + ) PURE; + + /// + /// GetMetrics retrieves overall metrics for the formatted string. + /// + /// The returned metrics. + /// + /// Standard HRESULT error code. + /// + /// + /// Drawing effects like underline and strikethrough do not contribute + /// to the text size, which is essentially the sum of advance widths and + /// line heights. Additionally, visible swashes and other graphic + /// adornments may extend outside the returned width and height. + /// + STDMETHOD(GetMetrics)( + _Out_ DWRITE_TEXT_METRICS* textMetrics + ) PURE; + + /// + /// GetOverhangMetrics returns the overhangs (in DIPs) of the layout and all + /// objects contained in it, including text glyphs and inline objects. + /// + /// Overshoots of visible extents (in DIPs) outside the layout. + /// + /// Standard HRESULT error code. + /// + /// + /// Any underline and strikethrough do not contribute to the black box + /// determination, since these are actually drawn by the renderer, which + /// is allowed to draw them in any variety of styles. + /// + STDMETHOD(GetOverhangMetrics)( + _Out_ DWRITE_OVERHANG_METRICS* overhangs + ) PURE; + + /// + /// Retrieve logical properties and measurement of each cluster. + /// + /// The array to fill with cluster information. + /// The maximum size of the clusterMetrics array. + /// The actual size of the clusterMetrics array that is needed. + /// + /// Standard HRESULT error code. + /// + /// + /// If maxClusterCount is not large enough E_NOT_SUFFICIENT_BUFFER, + /// which is equivalent to HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), + /// is returned and *actualClusterCount is set to the number of clusters + /// needed. + /// + STDMETHOD(GetClusterMetrics)( + _Out_writes_opt_(maxClusterCount) DWRITE_CLUSTER_METRICS* clusterMetrics, + UINT32 maxClusterCount, + _Out_ UINT32* actualClusterCount + ) PURE; + + /// + /// Determines the minimum possible width the layout can be set to without + /// emergency breaking between the characters of whole words. + /// + /// Minimum width. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(DetermineMinWidth)( + _Out_ FLOAT* minWidth + ) PURE; + + /// + /// Given a coordinate (in DIPs) relative to the top-left of the layout box, + /// this returns the corresponding hit-test metrics of the text string where + /// the hit-test has occurred. This is useful for mapping mouse clicks to caret + /// positions. When the given coordinate is outside the text string, the function + /// sets the output value *isInside to false but returns the nearest character + /// position. + /// + /// X coordinate to hit-test, relative to the top-left location of the layout box. + /// Y coordinate to hit-test, relative to the top-left location of the layout box. + /// Output flag indicating whether the hit-test location is at the leading or the trailing + /// side of the character. When the output *isInside value is set to false, this value is set according to the output + /// *position value to represent the edge closest to the hit-test location. + /// Output flag indicating whether the hit-test location is inside the text string. + /// When false, the position nearest the text's edge is returned. + /// Output geometry fully enclosing the hit-test location. When the output *isInside value + /// is set to false, this structure represents the geometry enclosing the edge closest to the hit-test location. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(HitTestPoint)( + FLOAT pointX, + FLOAT pointY, + _Out_ BOOL* isTrailingHit, + _Out_ BOOL* isInside, + _Out_ DWRITE_HIT_TEST_METRICS* hitTestMetrics + ) PURE; + + /// + /// Given a text position and whether the caret is on the leading or trailing + /// edge of that position, this returns the corresponding coordinate (in DIPs) + /// relative to the top-left of the layout box. This is most useful for drawing + /// the caret's current position, but it could also be used to anchor an IME to the + /// typed text or attach a floating menu near the point of interest. It may also be + /// used to programmatically obtain the geometry of a particular text position + /// for UI automation. + /// + /// Text position to get the coordinate of. + /// Flag indicating whether the location is of the leading or the trailing side of the specified text position. + /// Output caret X, relative to the top-left of the layout box. + /// Output caret Y, relative to the top-left of the layout box. + /// Output geometry fully enclosing the specified text position. + /// + /// Standard HRESULT error code. + /// + /// + /// When drawing a caret at the returned X,Y, it should be centered on X + /// and drawn from the Y coordinate down. The height will be the size of the + /// hit-tested text (which can vary in size within a line). + /// Reading direction also affects which side of the character the caret is drawn. + /// However, the returned X coordinate will be correct for either case. + /// You can get a text length back that is larger than a single character. + /// This happens for complex scripts when multiple characters form a single cluster, + /// when diacritics join their base character, or when you test a surrogate pair. + /// + STDMETHOD(HitTestTextPosition)( + UINT32 textPosition, + BOOL isTrailingHit, + _Out_ FLOAT* pointX, + _Out_ FLOAT* pointY, + _Out_ DWRITE_HIT_TEST_METRICS* hitTestMetrics + ) PURE; + + /// + /// The application calls this function to get a set of hit-test metrics + /// corresponding to a range of text positions. The main usage for this + /// is to draw highlighted selection of the text string. + /// + /// The function returns E_NOT_SUFFICIENT_BUFFER, which is equivalent to + /// HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), when the buffer size of + /// hitTestMetrics is too small to hold all the regions calculated by the + /// function. In such situation, the function sets the output value + /// *actualHitTestMetricsCount to the number of geometries calculated. + /// The application is responsible to allocate a new buffer of greater + /// size and call the function again. + /// + /// A good value to use as an initial value for maxHitTestMetricsCount may + /// be calculated from the following equation: + /// maxHitTestMetricsCount = lineCount * maxBidiReorderingDepth + /// + /// where lineCount is obtained from the value of the output argument + /// *actualLineCount from the function IDWriteTextLayout::GetLineMetrics, + /// and the maxBidiReorderingDepth value from the DWRITE_TEXT_METRICS + /// structure of the output argument *textMetrics from the function + /// IDWriteFactory::CreateTextLayout. + /// + /// First text position of the specified range. + /// Number of positions of the specified range. + /// Offset of the X origin (left of the layout box) which is added to each of the hit-test metrics returned. + /// Offset of the Y origin (top of the layout box) which is added to each of the hit-test metrics returned. + /// Pointer to a buffer of the output geometry fully enclosing the specified position range. + /// Maximum number of distinct metrics it could hold in its buffer memory. + /// Actual number of metrics returned or needed. + /// + /// Standard HRESULT error code. + /// + /// + /// There are no gaps in the returned metrics. While there could be visual gaps, + /// depending on bidi ordering, each range is contiguous and reports all the text, + /// including any hidden characters and trimmed text. + /// The height of each returned range will be the same within each line, regardless + /// of how the font sizes vary. + /// + STDMETHOD(HitTestTextRange)( + UINT32 textPosition, + UINT32 textLength, + FLOAT originX, + FLOAT originY, + _Out_writes_opt_(maxHitTestMetricsCount) DWRITE_HIT_TEST_METRICS* hitTestMetrics, + UINT32 maxHitTestMetricsCount, + _Out_ UINT32* actualHitTestMetricsCount + ) PURE; + + using IDWriteTextFormat::GetFontCollection; + using IDWriteTextFormat::GetFontFamilyNameLength; + using IDWriteTextFormat::GetFontFamilyName; + using IDWriteTextFormat::GetFontWeight; + using IDWriteTextFormat::GetFontStyle; + using IDWriteTextFormat::GetFontStretch; + using IDWriteTextFormat::GetFontSize; + using IDWriteTextFormat::GetLocaleNameLength; + using IDWriteTextFormat::GetLocaleName; +}; + + +/// +/// Encapsulates a 32-bit device independent bitmap and device context, which can be used for rendering glyphs. +/// +interface DWRITE_DECLARE_INTERFACE("5e5a32a3-8dff-4773-9ff6-0696eab77267") IDWriteBitmapRenderTarget : public IUnknown +{ + /// + /// Draws a run of glyphs to the bitmap. + /// + /// Horizontal position of the baseline origin, in DIPs, relative to the upper-left corner of the DIB. + /// Vertical position of the baseline origin, in DIPs, relative to the upper-left corner of the DIB. + /// Specifies measuring mode for glyphs in the run. + /// Renderer implementations may choose different rendering modes for different measuring modes, for example + /// DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL for DWRITE_MEASURING_MODE_NATURAL, + /// DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC for DWRITE_MEASURING_MODE_GDI_CLASSIC, and + /// DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL for DWRITE_MEASURING_MODE_GDI_NATURAL. + /// + /// Structure containing the properties of the glyph run. + /// Object that controls rendering behavior. + /// Specifies the foreground color of the text. + /// Optional rectangle that receives the bounding box (in pixels not DIPs) of all the pixels affected by + /// drawing the glyph run. The black box rectangle may extend beyond the dimensions of the bitmap. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(DrawGlyphRun)( + FLOAT baselineOriginX, + FLOAT baselineOriginY, + DWRITE_MEASURING_MODE measuringMode, + _In_ DWRITE_GLYPH_RUN const* glyphRun, + _In_ IDWriteRenderingParams* renderingParams, + COLORREF textColor, + _Out_opt_ RECT* blackBoxRect = NULL + ) PURE; + + /// + /// Gets a handle to the memory device context. + /// + /// + /// Returns the device context handle. + /// + /// + /// An application can use the device context to draw using GDI functions. An application can obtain the bitmap handle + /// (HBITMAP) by calling GetCurrentObject. An application that wants information about the underlying bitmap, including + /// a pointer to the pixel data, can call GetObject to fill in a DIBSECTION structure. The bitmap is always a 32-bit + /// top-down DIB. + /// + STDMETHOD_(HDC, GetMemoryDC)() PURE; + + /// + /// Gets the number of bitmap pixels per DIP. A DIP (device-independent pixel) is 1/96 inch so this value is the number + /// if pixels per inch divided by 96. + /// + /// + /// Returns the number of bitmap pixels per DIP. + /// + STDMETHOD_(FLOAT, GetPixelsPerDip)() PURE; + + /// + /// Sets the number of bitmap pixels per DIP. A DIP (device-independent pixel) is 1/96 inch so this value is the number + /// if pixels per inch divided by 96. + /// + /// Specifies the number of pixels per DIP. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetPixelsPerDip)( + FLOAT pixelsPerDip + ) PURE; + + /// + /// Gets the transform that maps abstract coordinate to DIPs. By default this is the identity + /// transform. Note that this is unrelated to the world transform of the underlying device + /// context. + /// + /// Receives the transform. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetCurrentTransform)( + _Out_ DWRITE_MATRIX* transform + ) PURE; + + /// + /// Sets the transform that maps abstract coordinate to DIPs. This does not affect the world + /// transform of the underlying device context. + /// + /// Specifies the new transform. This parameter can be NULL, in which + /// case the identity transform is implied. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(SetCurrentTransform)( + _In_opt_ DWRITE_MATRIX const* transform + ) PURE; + + /// + /// Gets the dimensions of the bitmap. + /// + /// Receives the size of the bitmap in pixels. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetSize)( + _Out_ SIZE* size + ) PURE; + + /// + /// Resizes the bitmap. + /// + /// New bitmap width, in pixels. + /// New bitmap height, in pixels. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(Resize)( + UINT32 width, + UINT32 height + ) PURE; +}; + +/// +/// The GDI interop interface provides interoperability with GDI. +/// +interface DWRITE_DECLARE_INTERFACE("1edd9491-9853-4299-898f-6432983b6f3a") IDWriteGdiInterop : public IUnknown +{ + /// + /// Creates a font object that matches the properties specified by the LOGFONT structure + /// in the system font collection (GetSystemFontCollection). + /// + /// Structure containing a GDI-compatible font description. + /// Receives a newly created font object if successful, or NULL in case of error. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateFontFromLOGFONT)( + _In_ LOGFONTW const* logFont, + _COM_Outptr_ IDWriteFont** font + ) PURE; + + /// + /// Initializes a LOGFONT structure based on the GDI-compatible properties of the specified font. + /// + /// Specifies a font. + /// Structure that receives a GDI-compatible font description. + /// Contains TRUE if the specified font object is part of the system font collection + /// or FALSE otherwise. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(ConvertFontToLOGFONT)( + _In_ IDWriteFont* font, + _Out_ LOGFONTW* logFont, + _Out_ BOOL* isSystemFont + ) PURE; + + /// + /// Initializes a LOGFONT structure based on the GDI-compatible properties of the specified font. + /// + /// Specifies a font face. + /// Structure that receives a GDI-compatible font description. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(ConvertFontFaceToLOGFONT)( + _In_ IDWriteFontFace* font, + _Out_ LOGFONTW* logFont + ) PURE; + + /// + /// Creates a font face object that corresponds to the currently selected HFONT. + /// + /// Handle to a device context into which a font has been selected. It is assumed that the client + /// has already performed font mapping and that the font selected into the DC is the actual font that would be used + /// for rendering glyphs. + /// Contains the newly created font face object, or NULL in case of failure. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateFontFaceFromHdc)( + HDC hdc, + _COM_Outptr_ IDWriteFontFace** fontFace + ) PURE; + + /// + /// Creates an object that encapsulates a bitmap and memory DC which can be used for rendering glyphs. + /// + /// Optional device context used to create a compatible memory DC. + /// Width of the bitmap. + /// Height of the bitmap. + /// Receives a pointer to the newly created render target. + STDMETHOD(CreateBitmapRenderTarget)( + _In_opt_ HDC hdc, + UINT32 width, + UINT32 height, + _COM_Outptr_ IDWriteBitmapRenderTarget** renderTarget + ) PURE; +}; + +/// +/// The DWRITE_TEXTURE_TYPE enumeration identifies a type of alpha texture. An alpha texture is a bitmap of alpha values, each +/// representing the darkness (i.e., opacity) of a pixel or subpixel. +/// +enum DWRITE_TEXTURE_TYPE +{ + /// + /// Specifies an alpha texture for aliased text rendering (i.e., bi-level, where each pixel is either fully opaque or fully transparent), + /// with one byte per pixel. + /// + DWRITE_TEXTURE_ALIASED_1x1, + + /// + /// Specifies an alpha texture for ClearType text rendering, with three bytes per pixel in the horizontal dimension and + /// one byte per pixel in the vertical dimension. + /// + DWRITE_TEXTURE_CLEARTYPE_3x1 +}; + +/// +/// Maximum alpha value in a texture returned by IDWriteGlyphRunAnalysis::CreateAlphaTexture. +/// +#define DWRITE_ALPHA_MAX 255 + +/// +/// Interface that encapsulates information used to render a glyph run. +/// +interface DWRITE_DECLARE_INTERFACE("7d97dbf7-e085-42d4-81e3-6a883bded118") IDWriteGlyphRunAnalysis : public IUnknown +{ + /// + /// Gets the bounding rectangle of the physical pixels affected by the glyph run. + /// + /// Specifies the type of texture requested. If a bi-level texture is requested, the + /// bounding rectangle includes only bi-level glyphs. Otherwise, the bounding rectangle includes only anti-aliased + /// glyphs. + /// Receives the bounding rectangle, or an empty rectangle if there are no glyphs + /// if the specified type. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetAlphaTextureBounds)( + DWRITE_TEXTURE_TYPE textureType, + _Out_ RECT* textureBounds + ) PURE; + + /// + /// Creates an alpha texture of the specified type. + /// + /// Specifies the type of texture requested. If a bi-level texture is requested, the + /// texture contains only bi-level glyphs. Otherwise, the texture contains only anti-aliased glyphs. + /// Specifies the bounding rectangle of the texture, which can be different than + /// the bounding rectangle returned by GetAlphaTextureBounds. + /// Receives the array of alpha values. + /// Size of the alphaValues array. The minimum size depends on the dimensions of the + /// rectangle and the type of texture requested. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateAlphaTexture)( + DWRITE_TEXTURE_TYPE textureType, + _In_ RECT const* textureBounds, + _Out_writes_bytes_(bufferSize) BYTE* alphaValues, + UINT32 bufferSize + ) PURE; + + /// + /// Gets properties required for ClearType blending. + /// + /// Rendering parameters object. In most cases, the values returned in the output + /// parameters are based on the properties of this object. The exception is if a GDI-compatible rendering mode + /// is specified. + /// Receives the gamma value to use for gamma correction. + /// Receives the enhanced contrast value. + /// Receives the ClearType level. + STDMETHOD(GetAlphaBlendParams)( + _In_ IDWriteRenderingParams* renderingParams, + _Out_ FLOAT* blendGamma, + _Out_ FLOAT* blendEnhancedContrast, + _Out_ FLOAT* blendClearTypeLevel + ) PURE; +}; + +/// +/// The root factory interface for all DWrite objects. +/// +interface DWRITE_DECLARE_INTERFACE("b859ee5a-d838-4b5b-a2e8-1adc7d93db48") IDWriteFactory : public IUnknown +{ + /// + /// Gets a font collection representing the set of installed fonts. + /// + /// Receives a pointer to the system font collection object, or NULL in case of failure. + /// If this parameter is nonzero, the function performs an immediate check for changes to the set of + /// installed fonts. If this parameter is FALSE, the function will still detect changes if the font cache service is running, but + /// there may be some latency. For example, an application might specify TRUE if it has itself just installed a font and wants to + /// be sure the font collection contains that font. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetSystemFontCollection)( + _COM_Outptr_ IDWriteFontCollection** fontCollection, + BOOL checkForUpdates = FALSE + ) PURE; + + /// + /// Creates a font collection using a custom font collection loader. + /// + /// Application-defined font collection loader, which must have been previously + /// registered using RegisterFontCollectionLoader. + /// Key used by the loader to identify a collection of font files. + /// Size in bytes of the collection key. + /// Receives a pointer to the system font collection object, or NULL in case of failure. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateCustomFontCollection)( + _In_ IDWriteFontCollectionLoader* collectionLoader, + _In_reads_bytes_(collectionKeySize) void const* collectionKey, + UINT32 collectionKeySize, + _COM_Outptr_ IDWriteFontCollection** fontCollection + ) PURE; + + /// + /// Registers a custom font collection loader with the factory object. + /// + /// Application-defined font collection loader. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(RegisterFontCollectionLoader)( + _In_ IDWriteFontCollectionLoader* fontCollectionLoader + ) PURE; + + /// + /// Unregisters a custom font collection loader that was previously registered using RegisterFontCollectionLoader. + /// + /// Application-defined font collection loader. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(UnregisterFontCollectionLoader)( + _In_ IDWriteFontCollectionLoader* fontCollectionLoader + ) PURE; + + /// + /// CreateFontFileReference creates a font file reference object from a local font file. + /// + /// Absolute file path. Subsequent operations on the constructed object may fail + /// if the user provided filePath doesn't correspond to a valid file on the disk. + /// Last modified time of the input file path. If the parameter is omitted, + /// the function will access the font file to obtain its last write time, so the clients are encouraged to specify this value + /// to avoid extra disk access. Subsequent operations on the constructed object may fail + /// if the user provided lastWriteTime doesn't match the file on the disk. + /// Contains newly created font file reference object, or NULL in case of failure. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateFontFileReference)( + _In_z_ WCHAR const* filePath, + _In_opt_ FILETIME const* lastWriteTime, + _COM_Outptr_ IDWriteFontFile** fontFile + ) PURE; + + /// + /// CreateCustomFontFileReference creates a reference to an application specific font file resource. + /// This function enables an application or a document to use a font without having to install it on the system. + /// The fontFileReferenceKey has to be unique only in the scope of the fontFileLoader used in this call. + /// + /// Font file reference key that uniquely identifies the font file resource + /// during the lifetime of fontFileLoader. + /// Size of font file reference key in bytes. + /// Font file loader that will be used by the font system to load data from the file identified by + /// fontFileReferenceKey. + /// Contains the newly created font file object, or NULL in case of failure. + /// + /// Standard HRESULT error code. + /// + /// + /// This function is provided for cases when an application or a document needs to use a font + /// without having to install it on the system. fontFileReferenceKey has to be unique only in the scope + /// of the fontFileLoader used in this call. + /// + STDMETHOD(CreateCustomFontFileReference)( + _In_reads_bytes_(fontFileReferenceKeySize) void const* fontFileReferenceKey, + UINT32 fontFileReferenceKeySize, + _In_ IDWriteFontFileLoader* fontFileLoader, + _COM_Outptr_ IDWriteFontFile** fontFile + ) PURE; + + /// + /// Creates a font face object. + /// + /// The file format of the font face. + /// The number of font files required to represent the font face. + /// Font files representing the font face. Since IDWriteFontFace maintains its own references + /// to the input font file objects, it's OK to release them after this call. + /// The zero based index of a font face in cases when the font files contain a collection of font faces. + /// If the font files contain a single face, this value should be zero. + /// Font face simulation flags for algorithmic emboldening and italicization. + /// Contains the newly created font face object, or NULL in case of failure. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateFontFace)( + DWRITE_FONT_FACE_TYPE fontFaceType, + UINT32 numberOfFiles, + _In_reads_(numberOfFiles) IDWriteFontFile* const* fontFiles, + UINT32 faceIndex, + DWRITE_FONT_SIMULATIONS fontFaceSimulationFlags, + _COM_Outptr_ IDWriteFontFace** fontFace + ) PURE; + + /// + /// Creates a rendering parameters object with default settings for the primary monitor. + /// + /// Holds the newly created rendering parameters object, or NULL in case of failure. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateRenderingParams)( + _COM_Outptr_ IDWriteRenderingParams** renderingParams + ) PURE; + + /// + /// Creates a rendering parameters object with default settings for the specified monitor. + /// + /// The monitor to read the default values from. + /// Holds the newly created rendering parameters object, or NULL in case of failure. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateMonitorRenderingParams)( + HMONITOR monitor, + _COM_Outptr_ IDWriteRenderingParams** renderingParams + ) PURE; + + /// + /// Creates a rendering parameters object with the specified properties. + /// + /// The gamma value used for gamma correction, which must be greater than zero and cannot exceed 256. + /// The amount of contrast enhancement, zero or greater. + /// The degree of ClearType level, from 0.0f (no ClearType) to 1.0f (full ClearType). + /// The geometry of a device pixel. + /// Method of rendering glyphs. In most cases, this should be DWRITE_RENDERING_MODE_DEFAULT to automatically use an appropriate mode. + /// Holds the newly created rendering parameters object, or NULL in case of failure. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateCustomRenderingParams)( + FLOAT gamma, + FLOAT enhancedContrast, + FLOAT clearTypeLevel, + DWRITE_PIXEL_GEOMETRY pixelGeometry, + DWRITE_RENDERING_MODE renderingMode, + _COM_Outptr_ IDWriteRenderingParams** renderingParams + ) PURE; + + /// + /// Registers a font file loader with DirectWrite. + /// + /// Pointer to the implementation of the IDWriteFontFileLoader for a particular file resource type. + /// + /// Standard HRESULT error code. + /// + /// + /// This function registers a font file loader with DirectWrite. + /// Font file loader interface handles loading font file resources of a particular type from a key. + /// The font file loader interface is recommended to be implemented by a singleton object. + /// A given instance can only be registered once. + /// Succeeding attempts will return an error that it has already been registered. + /// IMPORTANT: font file loader implementations must not register themselves with DirectWrite + /// inside their constructors and must not unregister themselves in their destructors, because + /// registration and unregistration operations increment and decrement the object reference count respectively. + /// Instead, registration and unregistration of font file loaders with DirectWrite should be performed + /// outside of the font file loader implementation as a separate step. + /// + STDMETHOD(RegisterFontFileLoader)( + _In_ IDWriteFontFileLoader* fontFileLoader + ) PURE; + + /// + /// Unregisters a font file loader that was previously registered with the DirectWrite font system using RegisterFontFileLoader. + /// + /// Pointer to the file loader that was previously registered with the DirectWrite font system using RegisterFontFileLoader. + /// + /// This function will succeed if the user loader is requested to be removed. + /// It will fail if the pointer to the file loader identifies a standard DirectWrite loader, + /// or a loader that is never registered or has already been unregistered. + /// + /// + /// This function unregisters font file loader callbacks with the DirectWrite font system. + /// The font file loader interface is recommended to be implemented by a singleton object. + /// IMPORTANT: font file loader implementations must not register themselves with DirectWrite + /// inside their constructors and must not unregister themselves in their destructors, because + /// registration and unregistration operations increment and decrement the object reference count respectively. + /// Instead, registration and unregistration of font file loaders with DirectWrite should be performed + /// outside of the font file loader implementation as a separate step. + /// + STDMETHOD(UnregisterFontFileLoader)( + _In_ IDWriteFontFileLoader* fontFileLoader + ) PURE; + + /// + /// Create a text format object used for text layout. + /// + /// Name of the font family + /// Font collection. NULL indicates the system font collection. + /// Font weight + /// Font style + /// Font stretch + /// Logical size of the font in DIP units. A DIP ("device-independent pixel") equals 1/96 inch. + /// Locale name + /// Contains newly created text format object, or NULL in case of failure. + /// + /// Standard HRESULT error code. + /// + /// + /// If fontCollection is nullptr, the system font collection is used, grouped by typographic family name + /// (DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE) without downloadable fonts. + /// + STDMETHOD(CreateTextFormat)( + _In_z_ WCHAR const* fontFamilyName, + _In_opt_ IDWriteFontCollection* fontCollection, + DWRITE_FONT_WEIGHT fontWeight, + DWRITE_FONT_STYLE fontStyle, + DWRITE_FONT_STRETCH fontStretch, + FLOAT fontSize, + _In_z_ WCHAR const* localeName, + _COM_Outptr_ IDWriteTextFormat** textFormat + ) PURE; + + /// + /// Create a typography object used in conjunction with text format for text layout. + /// + /// Contains newly created typography object, or NULL in case of failure. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateTypography)( + _COM_Outptr_ IDWriteTypography** typography + ) PURE; + + /// + /// Create an object used for interoperability with GDI. + /// + /// Receives the GDI interop object if successful, or NULL in case of failure. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(GetGdiInterop)( + _COM_Outptr_ IDWriteGdiInterop** gdiInterop + ) PURE; + + /// + /// CreateTextLayout takes a string, format, and associated constraints + /// and produces an object representing the fully analyzed + /// and formatted result. + /// + /// The string to layout. + /// The length of the string. + /// The format to apply to the string. + /// Width of the layout box. + /// Height of the layout box. + /// The resultant object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateTextLayout)( + _In_reads_(stringLength) WCHAR const* string, + UINT32 stringLength, + _In_ IDWriteTextFormat* textFormat, + FLOAT maxWidth, + FLOAT maxHeight, + _COM_Outptr_ IDWriteTextLayout** textLayout + ) PURE; + + /// + /// CreateGdiCompatibleTextLayout takes a string, format, and associated constraints + /// and produces and object representing the result formatted for a particular display resolution + /// and measuring mode. The resulting text layout should only be used for the intended resolution, + /// and for cases where text scalability is desired, CreateTextLayout should be used instead. + /// + /// The string to layout. + /// The length of the string. + /// The format to apply to the string. + /// Width of the layout box. + /// Height of the layout box. + /// Number of physical pixels per DIP. For example, if rendering onto a 96 DPI device then pixelsPerDip + /// is 1. If rendering onto a 120 DPI device then pixelsPerDip is 120/96. + /// Optional transform applied to the glyphs and their positions. This transform is applied after the + /// scaling specified the font size and pixelsPerDip. + /// + /// When set to FALSE, instructs the text layout to use the same metrics as GDI aliased text. + /// When set to TRUE, instructs the text layout to use the same metrics as text measured by GDI using a font + /// created with CLEARTYPE_NATURAL_QUALITY. + /// + /// The resultant object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateGdiCompatibleTextLayout)( + _In_reads_(stringLength) WCHAR const* string, + UINT32 stringLength, + _In_ IDWriteTextFormat* textFormat, + FLOAT layoutWidth, + FLOAT layoutHeight, + FLOAT pixelsPerDip, + _In_opt_ DWRITE_MATRIX const* transform, + BOOL useGdiNatural, + _COM_Outptr_ IDWriteTextLayout** textLayout + ) PURE; + + /// + /// The application may call this function to create an inline object for trimming, using an ellipsis as the omission sign. + /// The ellipsis will be created using the current settings of the format, including base font, style, and any effects. + /// Alternate omission signs can be created by the application by implementing IDWriteInlineObject. + /// + /// Text format used as a template for the omission sign. + /// Created omission sign. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateEllipsisTrimmingSign)( + _In_ IDWriteTextFormat* textFormat, + _COM_Outptr_ IDWriteInlineObject** trimmingSign + ) PURE; + + /// + /// Return an interface to perform text analysis with. + /// + /// The resultant object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateTextAnalyzer)( + _COM_Outptr_ IDWriteTextAnalyzer** textAnalyzer + ) PURE; + + /// + /// Creates a number substitution object using a locale name, + /// substitution method, and whether to ignore user overrides (uses NLS + /// defaults for the given culture instead). + /// + /// Method of number substitution to use. + /// Which locale to obtain the digits from. + /// Ignore the user's settings and use the locale defaults + /// Receives a pointer to the newly created object. + STDMETHOD(CreateNumberSubstitution)( + _In_ DWRITE_NUMBER_SUBSTITUTION_METHOD substitutionMethod, + _In_z_ WCHAR const* localeName, + _In_ BOOL ignoreUserOverride, + _COM_Outptr_ IDWriteNumberSubstitution** numberSubstitution + ) PURE; + + /// + /// Creates a glyph run analysis object, which encapsulates information + /// used to render a glyph run. + /// + /// Structure specifying the properties of the glyph run. + /// Number of physical pixels per DIP. For example, if rendering onto a 96 DPI bitmap then pixelsPerDip + /// is 1. If rendering onto a 120 DPI bitmap then pixelsPerDip is 120/96. + /// Optional transform applied to the glyphs and their positions. This transform is applied after the + /// scaling specified by the emSize and pixelsPerDip. + /// Specifies the rendering mode, which must be one of the raster rendering modes (i.e., not default + /// and not outline). + /// Specifies the method to measure glyphs. + /// Horizontal position of the baseline origin, in DIPs. + /// Vertical position of the baseline origin, in DIPs. + /// Receives a pointer to the newly created object. + /// + /// Standard HRESULT error code. + /// + STDMETHOD(CreateGlyphRunAnalysis)( + _In_ DWRITE_GLYPH_RUN const* glyphRun, + FLOAT pixelsPerDip, + _In_opt_ DWRITE_MATRIX const* transform, + DWRITE_RENDERING_MODE renderingMode, + DWRITE_MEASURING_MODE measuringMode, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + _COM_Outptr_ IDWriteGlyphRunAnalysis** glyphRunAnalysis + ) PURE; + +}; // interface IDWriteFactory + + +/// +/// Creates a DirectWrite factory object that is used for subsequent creation of individual DirectWrite objects. +/// +/// Identifies whether the factory object will be shared or isolated. +/// Identifies the DirectWrite factory interface, such as __uuidof(IDWriteFactory). +/// Receives the DirectWrite factory object. +/// +/// Standard HRESULT error code. +/// +/// +/// Obtains DirectWrite factory object that is used for subsequent creation of individual DirectWrite classes. +/// DirectWrite factory contains internal state such as font loader registration and cached font data. +/// In most cases it is recommended to use the shared factory object, because it allows multiple components +/// that use DirectWrite to share internal DirectWrite state and reduce memory usage. +/// However, there are cases when it is desirable to reduce the impact of a component, +/// such as a plug-in from an untrusted source, on the rest of the process by sandboxing and isolating it +/// from the rest of the process components. In such cases, it is recommended to use an isolated factory for the sandboxed +/// component. +/// + +#if _MSC_VER >= 1900 +#define WIN_NOEXCEPT noexcept +#else +#define WIN_NOEXCEPT throw() +#endif + +extern "C" HRESULT DWRITE_EXPORT DWriteCreateFactory( + _In_ DWRITE_FACTORY_TYPE factoryType, + _In_ REFIID iid, + _COM_Outptr_ IUnknown **factory + ) WIN_NOEXCEPT; + +// Macros used to define DirectWrite error codes. +#define FACILITY_DWRITE 0x898 +#define DWRITE_ERR_BASE 0x5000 +#define MAKE_DWRITE_HR(severity, code) MAKE_HRESULT(severity, FACILITY_DWRITE, (DWRITE_ERR_BASE + code)) +#define MAKE_DWRITE_HR_ERR(code) MAKE_DWRITE_HR(SEVERITY_ERROR, code) + +// DWrite errors have moved to winerror.h + + +#endif /* DWRITE_H_INCLUDED */ diff --git a/opennurbs/Include/opennurbs.h b/opennurbs/Include/opennurbs.h new file mode 100644 index 0000000..84991d3 --- /dev/null +++ b/opennurbs/Include/opennurbs.h @@ -0,0 +1,180 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2016 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +//////////////////////////////////////////////////////////////// +// +// Includes all openNURBS toolkit headers required to use the +// openNURBS toolkit library. See readme.txt for details. +// +//////////////////////////////////////////////////////////////// + +#pragma warning (disable:4189) + +#if !defined(OPENNURBS_INC_) +#define OPENNURBS_INC_ + +#define OPENNURBS_INC_IN_PROGRESS + +#include "opennurbs_system.h" /* system headers used by openNURBS code */ + +#include "opennurbs_wip.h" /* works in progress defines that control availability */ + +#include "opennurbs_3dm.h" /* 3DM typecode (TCODE) definitions */ + +#include "opennurbs_defines.h" /* openNURBS defines and enums */ +#include "opennurbs_error.h" /* error handling */ +#include "opennurbs_memory.h" /* memory managment (onmalloc(), onrealloc(), onfree(), ...) */ +#include "opennurbs_rand.h" /* random number generator */ +#include "opennurbs_crc.h" /* cyclic redundancy check tool */ +#include "opennurbs_uuid.h" /* universally unique identifiers (UUID, a.k.a, GUID) */ +#include "opennurbs_unicode.h" /* unicode string conversion */ + +#if defined(ON_CPLUSPLUS) +#include "opennurbs_sleeplock.h" +#include "opennurbs_topology.h" +#include "opennurbs_cpp_base.h" // for safe use of STL classes as private data members +#include "opennurbs_locale.h" +#include "opennurbs_date.h" +#include "opennurbs_version_number.h" +#include "opennurbs_compstat.h" +#include "opennurbs_progress_reporter.h" // ON_ProgressReporter class +#include "opennurbs_terminator.h" // ON_Terminator class +#include "opennurbs_lock.h" // simple atomic operation lock setter +#include "opennurbs_fsp.h" // fixed size memory pool +#include "opennurbs_function_list.h" /* list of functions to run */ +#include "opennurbs_std_string.h" // std::string utilities +#include "opennurbs_md5.h" +#include "opennurbs_sha1.h" +#include "opennurbs_string.h" // dynamic string classes (single and double byte) +#include "opennurbs_hash_table.h" +#include "opennurbs_file_utilities.h" +#include "opennurbs_array.h" // dynamic array templates +#include "opennurbs_compress.h" +#include "opennurbs_base64.h" // base64 encodeing and decoding +#include "opennurbs_color.h" // R G B color +#include "opennurbs_linestyle.h" // line pattern, scale, and width +#include "opennurbs_point.h" // double precision 2d, 3d, 4d points and 2d, 3d vectors +#include "opennurbs_fpoint.h" // float precision 2d, 3d, 4d points and 2d, 3d vectors +#include "opennurbs_ipoint.h" // 2d integer point, rectangle and size +#include "opennurbs_base32.h" // base32 encodeing and decoding +#include "opennurbs_pluginlist.h" +#include "opennurbs_bounding_box.h" // simple 3d axis aligned bounding box +#include "opennurbs_matrix.h" // general m X n matrix +#include "opennurbs_xform.h" // 4 X 4 transformation matrix +#include "opennurbs_quaternion.h" +#include "opennurbs_workspace.h" // workspace memory allocation +#include "opennurbs_plane.h" // simple 3d plane +#include "opennurbs_circle.h" // simple 3d circle +#include "opennurbs_ellipse.h" // simple 3d ellipse +#include "opennurbs_parse.h" // number, length unit, length, angle, point parsing +#include "opennurbs_string_value.h" // Robust length, angle and scale value information for UI + + +#include "opennurbs_line.h" // simple line +#include "opennurbs_symmetry.h" +#include "opennurbs_polyline.h" // simple polyline +#include "opennurbs_cylinder.h" // simple 3d elliptical cylinder +#include "opennurbs_cone.h" // simple 3d right circular cone +#include "opennurbs_sphere.h" // simple 3d sphere +#include "opennurbs_box.h" // simple 3d box +#include "opennurbs_torus.h" // simple 3d torus +#include "opennurbs_convex_poly.h" // simple 3d simplex and 3d convex polyhedra +#include "opennurbs_bezier.h" // simple bezier and polynomial curves and surfaces +#include "opennurbs_math.h" // utilities for performing simple calculations +#include "opennurbs_intersect.h" // utilities for performing simple intersections +#include "opennurbs_optimize.h" // utilities for finding extrema and zeros +#include "opennurbs_knot.h" // utilities for working with NURBS knot vectors +#include "opennurbs_evaluate_nurbs.h" // utilities for evaluating Beziers and NURBS +#include "opennurbs_textlog.h" // text log for dumps, error logs, etc. +#include "opennurbs_rtree.h" // ON_RTree spatial search utility. +#include "opennurbs_mapchan.h" +#include "opennurbs_rendering.h" +#include "opennurbs_object.h" // virtual base class for all openNURBS objects +#include "opennurbs_model_component.h" +#include "opennurbs_archive.h" // binary arcive objects for serialization to file, memory blocks, etc. +#include "opennurbs_model_geometry.h" +#include "opennurbs_arc.h" // simple 3d circular arc +#include "opennurbs_userdata.h" // class for attaching persistent user information to openNURBS objects +#include "opennurbs_geometry.h" // virtual base class for geometric objects +#include "opennurbs_curve.h" // virtual parametric curve +#include "opennurbs_surface.h" // virtual parametric surface +#include "opennurbs_viewport.h" // simple renering projection +#include "opennurbs_texture_mapping.h" // texture coordinate evaluation +#include "opennurbs_texture.h" // texture definition +#include "opennurbs_material.h" // simple rendering material +#include "opennurbs_layer.h" // layer definition +#include "opennurbs_linetype.h" // linetype definition +#include "opennurbs_group.h" // group name and index +#include "opennurbs_light.h" // light +#include "opennurbs_pointgeometry.h" // single point +#include "opennurbs_pointcloud.h" // point set +#include "opennurbs_curveproxy.h" // proxy curve provides a way to use an existing curve +#include "opennurbs_surfaceproxy.h" // proxy surface provides a way to use another surface +#include "opennurbs_mesh.h" // mesh object + + +#include "opennurbs_pointgrid.h" // point grid object +#include "opennurbs_linecurve.h" // line as a paramtric curve object +#include "opennurbs_arccurve.h" // arc/circle as a paramtric curve object +#include "opennurbs_polylinecurve.h" // polyline as a paramtric curve object +#include "opennurbs_nurbscurve.h" // NURBS curve +#include "opennurbs_polycurve.h" // polycurve (composite curve) +#include "opennurbs_curveonsurface.h" // curve on surface (other kind of composite curve) +#include "opennurbs_nurbssurface.h" // NURBS surface +#include "opennurbs_planesurface.h" // plane surface +#include "opennurbs_revsurface.h" // surface of revolution +#include "opennurbs_sumsurface.h" // sum surface +#include "opennurbs_brep.h" // boundary rep +#include "opennurbs_beam.h" // lightweight extrusion object +#include "opennurbs_subd.h" // subdivison surface object +#include "opennurbs_bitmap.h" // Windows and OpenGL bitmaps +#include "opennurbs_instance.h" // instance definitions and references +#include "opennurbs_3dm_properties.h" +#include "opennurbs_3dm_settings.h" +#include "opennurbs_3dm_attributes.h" +#include "opennurbs_textglyph.h" +#include "opennurbs_textcontext.h" +#include "opennurbs_textrun.h" +#include "opennurbs_font.h" // font +#include "opennurbs_text_style.h" +#include "opennurbs_dimensionstyle.h" // dimension style +#include "opennurbs_text.h" +#include "opennurbs_hatch.h" // hatch geometry definitions +#include "opennurbs_hatch.h" // hatch geometry definitions +#include "opennurbs_linetype.h" // linetype pattern definitions +#include "opennurbs_objref.h" // ON_ObjRef definition +#include "opennurbs_offsetsurface.h" // ON_OffsetSurface definition +#include "opennurbs_detail.h" // ON_Detail definition +#include "opennurbs_lookup.h" // ON_SerialNumberTable +#include "opennurbs_object_history.h" +#include "opennurbs_annotationbase.h" // Base class for text, leaders and dimensions +#include "opennurbs_textobject.h" +#include "opennurbs_leader.h" +#include "opennurbs_dimension.h" +#include "opennurbs_dimensionformat.h" // Formatting dimension measurements to strings + +#include "opennurbs_photogrammetry.h" + +#include "opennurbs_extensions.h" + +#include "opennurbs_freetype.h" + + +#endif + +#undef OPENNURBS_INC_IN_PROGRESS + +#endif diff --git a/opennurbs/Include/opennurbs_3dm.h b/opennurbs/Include/opennurbs_3dm.h new file mode 100644 index 0000000..e04d3de --- /dev/null +++ b/opennurbs/Include/opennurbs_3dm.h @@ -0,0 +1,532 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_THREEDM_INC_) +#define OPENNURBS_THREEDM_INC_ + +/* 3dm defines, structs and typedefs */ + +/* Typecode format 4 bytes long + + x xxxxxxxxxxxxxxx,x xxx xxxx xxxx x x xx + | | | | | | | + | | | | + | | | | +--- "stuff" bit + | | | | + | | | +-- specific codes + | | | + | | +-- RESERVED - DO NOT USE (should be 0) (will be used to control CRC on/off) + | | + | +-- category:_000 0000 0000 0001 Legacy geometry TCODE_LEGACY_GEOMETRY + | _000 0000 0000 0010 openNURBS object TCODE_OPENNURBS_OBJECT + | _000 0000 0000 0100 -- RESERVED - DO NOT USE (should be 0 in any typecode) -- + | _000 0000 0000 1000 -- RESERVED - DO NOT USE (should be 0 in any typecode) -- + | _000 0000 0001 0000 Geometry TCODE_GEOMETRY + | _000 0000 0010 0000 Annotation + | _000 0000 0100 0000 Display Attributes TCODE_DISPLAY + | _000 0000 1000 0000 Rendering TCODE_RENDER + | _000 0001 0000 0000 + | _000 0010 0000 0000 Interface TCODE_INTERFACE + | _000 0100 0000 0000 -- RESERVED - DO NOT USE (should be 0 in any typecode) -- + | _000 1000 0000 0000 Tolerances TCODE_TOLERANCE + | _001 0000 0000 0000 Tables TCODE_TABLE + | _010 0000 0000 0000 Table record TCODE_TABLEREC + | _100 0000 0000 0000 User information TCODE_USER + | + +-- format: 0 - data size in header - data block follows TCODE_SHORT + 1 - data in header - no data block follows + +*/ + + +/* +// The TCODE_COMMENTBLOCK is the first chunk in the file, starts 32 bytes into +// the file, and contains text information terminated with a ^Z. This ^Z and +// contents of this chunk were expanded in February 2000. Files written with +// code released earlier than this will not have the ^Z. +// +// The TCODE_ENDOFFILE is the last chunk in the file and the first 4 bytes +// of information in this chunk is an integer that contains the file length. +// This chunk was added in February 2000 and files written with code released +// earlier than this will not have this termination block. +*/ +#define TCODE_COMMENTBLOCK 0x00000001 +#define TCODE_ENDOFFILE 0x00007FFF +#define TCODE_ENDOFFILE_GOO 0x00007FFE /* + // this typecode is returned when + // a rogue eof marker is found + // Some v1 3dm file writers put + // these markers in a "goo". + // Simply skip these chunks and continue. + */ +#define TCODE_LEGACY_GEOMETRY 0x00010000 +#define TCODE_OPENNURBS_OBJECT 0x00020000 +#define TCODE_GEOMETRY 0x00100000 +#define TCODE_ANNOTATION 0x00200000 +#define TCODE_DISPLAY 0x00400000 +#define TCODE_RENDER 0x00800000 +#define TCODE_INTERFACE 0x02000000 +#define TCODE_TOLERANCE 0x08000000 +#define TCODE_TABLE 0x10000000 +#define TCODE_TABLEREC 0x20000000 +#define TCODE_USER 0x40000000 +#define TCODE_SHORT 0x80000000 + +#define TCODE_CRC 0x8000 + +#define TCODE_ANONYMOUS_CHUNK (TCODE_USER | TCODE_CRC | 0x0000 ) +#define TCODE_UTF8_STRING_CHUNK (TCODE_USER | TCODE_CRC | 0x0001 ) +#define TCODE_MODEL_ATTRIBUTES_CHUNK (TCODE_USER | TCODE_CRC | 0x0002 ) + +#define TCODE_DICTIONARY (TCODE_USER | TCODE_CRC | 0x0010) +#define TCODE_DICTIONARY_ID (TCODE_USER | TCODE_CRC | 0x0011) +#define TCODE_DICTIONARY_ENTRY (TCODE_USER | TCODE_CRC | 0x0012) +#define TCODE_DICTIONARY_END (TCODE_USER | TCODE_SHORT | 0x0013) +#define TCODE_XDATA (TCODE_USER | 0x0001) + + +/* The openNURBS toolkit allows users to write all openNURBS classed that are +// derived from ON_Object using using TCODE_OPENNURBS_CLASS chunks. +// In the .3dm file these TCODE_OPENNURBS_CLASS chunks are always have the +// following format. +*/ + +/* tables added 17 February 2000 */ +#define TCODE_MATERIAL_TABLE (TCODE_TABLE | 0x0010) /* rendering materials */ +#define TCODE_LAYER_TABLE (TCODE_TABLE | 0x0011) /* layers */ +#define TCODE_LIGHT_TABLE (TCODE_TABLE | 0x0012) /* rendering lights */ +#define TCODE_OBJECT_TABLE (TCODE_TABLE | 0x0013) /* geometry and annotation */ +#define TCODE_PROPERTIES_TABLE (TCODE_TABLE | 0x0014) /* model properties: + // revision history + // notes + // preview image + */ +#define TCODE_SETTINGS_TABLE (TCODE_TABLE | 0x0015) /* file properties including, + // units, tolerancess, + // annotation defaults, + // render mesh defaults, + // current layer, + // current material, + // current color, + // named construction planes, + // named viewports, + // current viewports, + */ +#define TCODE_BITMAP_TABLE (TCODE_TABLE | 0x0016) /* embedded bitmaps */ +#define TCODE_USER_TABLE (TCODE_TABLE | 0x0017) /* user table */ + +#define TCODE_GROUP_TABLE (TCODE_TABLE | 0x0018) /* group table */ + +#define TCODE_FONT_TABLE (TCODE_TABLE | 0x0019) /* annotation font table */ +#define TCODE_DIMSTYLE_TABLE (TCODE_TABLE | 0x0020) /* annotation dimension style table */ + +#define TCODE_INSTANCE_DEFINITION_TABLE (TCODE_TABLE | 0x0021) /* instance definition table */ + +#define TCODE_HATCHPATTERN_TABLE (TCODE_TABLE | 0x0022) /* hatch pattern table */ + +#define TCODE_LINETYPE_TABLE (TCODE_TABLE | 0x0023) /* linetype table */ + +#define TCODE_OBSOLETE_LAYERSET_TABLE (TCODE_TABLE | 0x0024) /* obsolete layer set table */ + +#define TCODE_TEXTURE_MAPPING_TABLE (TCODE_TABLE | 0x0025) /* texture mappings */ + +#define TCODE_HISTORYRECORD_TABLE (TCODE_TABLE | 0x0026) /* history records */ + +#define TCODE_ENDOFTABLE 0xFFFFFFFF + +/* records in properties table */ +#define TCODE_PROPERTIES_REVISIONHISTORY (TCODE_TABLEREC | TCODE_CRC | 0x0021) +#define TCODE_PROPERTIES_NOTES (TCODE_TABLEREC | TCODE_CRC | 0x0022) +#define TCODE_PROPERTIES_PREVIEWIMAGE (TCODE_TABLEREC | TCODE_CRC | 0x0023) +#define TCODE_PROPERTIES_APPLICATION (TCODE_TABLEREC | TCODE_CRC | 0x0024) +#define TCODE_PROPERTIES_COMPRESSED_PREVIEWIMAGE (TCODE_TABLEREC | TCODE_CRC | 0x0025) +#define TCODE_PROPERTIES_OPENNURBS_VERSION (TCODE_TABLEREC | TCODE_SHORT | 0x0026) +#define TCODE_PROPERTIES_AS_FILE_NAME (TCODE_TABLEREC | TCODE_CRC | 0x0027 ) + +/* records in settings table */ +#define TCODE_SETTINGS_PLUGINLIST (TCODE_TABLEREC | TCODE_CRC | 0x0135) +#define TCODE_SETTINGS_UNITSANDTOLS (TCODE_TABLEREC | TCODE_CRC | 0x0031) +#define TCODE_SETTINGS_RENDERMESH (TCODE_TABLEREC | TCODE_CRC | 0x0032) +#define TCODE_SETTINGS_ANALYSISMESH (TCODE_TABLEREC | TCODE_CRC | 0x0033) +#define TCODE_SETTINGS_ANNOTATION (TCODE_TABLEREC | TCODE_CRC | 0x0034) +#define TCODE_SETTINGS_NAMED_CPLANE_LIST (TCODE_TABLEREC | TCODE_CRC | 0x0035) +#define TCODE_SETTINGS_NAMED_VIEW_LIST (TCODE_TABLEREC | TCODE_CRC | 0x0036) +#define TCODE_SETTINGS_VIEW_LIST (TCODE_TABLEREC | TCODE_CRC | 0x0037) +#define TCODE_SETTINGS_CURRENT_LAYER_INDEX (TCODE_TABLEREC | TCODE_SHORT | 0x0038) +#define TCODE_SETTINGS_CURRENT_MATERIAL_INDEX (TCODE_TABLEREC | TCODE_CRC | 0x0039) +#define TCODE_SETTINGS_CURRENT_COLOR (TCODE_TABLEREC | TCODE_CRC | 0x003A) +#define TCODE_SETTINGS__NEVER__USE__THIS (TCODE_TABLEREC | TCODE_CRC | 0x003E) +#define TCODE_SETTINGS_CURRENT_WIRE_DENSITY (TCODE_TABLEREC | TCODE_SHORT | 0x003C) +#define TCODE_SETTINGS_RENDER (TCODE_TABLEREC | TCODE_CRC | 0x003D) +#define TCODE_SETTINGS_GRID_DEFAULTS (TCODE_TABLEREC | TCODE_CRC | 0x003F) +#define TCODE_SETTINGS_MODEL_URL (TCODE_TABLEREC | TCODE_CRC | 0x0131) +#define TCODE_SETTINGS_CURRENT_FONT_INDEX (TCODE_TABLEREC | TCODE_SHORT | 0x0132) +#define TCODE_SETTINGS_CURRENT_DIMSTYLE_INDEX (TCODE_TABLEREC | TCODE_SHORT | 0x0133) +/* added 29 October 2002 as a chunk to hold new and future ON_3dmSettings information */ +#define TCODE_SETTINGS_ATTRIBUTES (TCODE_TABLEREC | TCODE_CRC | 0x0134) +/* 2016-Nov-28 RH-33298 ON_3dmRenderSettings user data in ON_3dmSettings.m_RenderSettings */ +#define TCODE_SETTINGS_RENDER_USERDATA (TCODE_TABLEREC | TCODE_CRC | 0x0136) + +/* views are subrecords in the settings table */ +#define TCODE_VIEW_RECORD (TCODE_TABLEREC | TCODE_CRC | 0x003B) +/* subrecords if view record */ +#define TCODE_VIEW_CPLANE (TCODE_TABLEREC | TCODE_CRC | 0x013B) +#define TCODE_VIEW_VIEWPORT (TCODE_TABLEREC | TCODE_CRC | 0x023B) +#define TCODE_VIEW_SHOWCONGRID (TCODE_TABLEREC | TCODE_SHORT | 0x033B) +#define TCODE_VIEW_SHOWCONAXES (TCODE_TABLEREC | TCODE_SHORT | 0x043B) +#define TCODE_VIEW_SHOWWORLDAXES (TCODE_TABLEREC | TCODE_SHORT | 0x053B) +#define TCODE_VIEW_TRACEIMAGE (TCODE_TABLEREC | TCODE_CRC | 0x063B) +#define TCODE_VIEW_WALLPAPER (TCODE_TABLEREC | TCODE_CRC | 0x073B) +#define TCODE_VIEW_WALLPAPER_V3 (TCODE_TABLEREC | TCODE_CRC | 0x074B) +#define TCODE_VIEW_TARGET (TCODE_TABLEREC | TCODE_CRC | 0x083B) +#define TCODE_VIEW_V3_DISPLAYMODE (TCODE_TABLEREC | TCODE_SHORT | 0x093B) +#define TCODE_VIEW_NAME (TCODE_TABLEREC | TCODE_CRC | 0x0A3B) +#define TCODE_VIEW_POSITION (TCODE_TABLEREC | TCODE_CRC | 0x0B3B) + +/* added 29 October 2002 as a chunk to hold new and future ON_3dmView information */ +#define TCODE_VIEW_ATTRIBUTES (TCODE_TABLEREC | TCODE_CRC | 0x0C3B) + +/* added 27 June 2008 as a chunk to hold userdata on ON_Viewports saved in named view list */ +#define TCODE_VIEW_VIEWPORT_USERDATA (TCODE_TABLEREC | TCODE_CRC | 0x0D3B) + +/* records in bitmap table */ +#define TCODE_BITMAP_RECORD (TCODE_TABLEREC | TCODE_CRC | 0x0090) /* bitmap table record derived from ON_Bitmap */ + +/* records in material table */ +#define TCODE_MATERIAL_RECORD (TCODE_TABLEREC | TCODE_CRC | 0x0040) /* material table record derived from ON_Material */ + +/* records in layer table */ +#define TCODE_LAYER_RECORD (TCODE_TABLEREC | TCODE_CRC | 0x0050) /* layer table record derived from ON_Layer */ + +/* records in light table */ +#define TCODE_LIGHT_RECORD (TCODE_TABLEREC | TCODE_CRC | 0x0060) /* light table record derived from ON_Light */ +#define TCODE_LIGHT_RECORD_ATTRIBUTES (TCODE_INTERFACE | TCODE_CRC | 0x0061) /* ON_3dmObjectAttributes chunk */ +#define TCODE_LIGHT_RECORD_ATTRIBUTES_USERDATA (TCODE_INTERFACE | 0x0062) /* ON_3dmObjectAttributes userdata chunk */ + +#define TCODE_LIGHT_RECORD_END (TCODE_INTERFACE | TCODE_SHORT | 0x006F) + +/* records in user table + Each user table entery has two top level chunks, a TCODE_USER_TABLE_UUID chunk + and a TCODE_USER_RECORD chunk. +*/ + +/* The TCODE_USER_TABLE_UUID chunk + contains the plug-in id and, if the archive is V5 or later + and was written by an opennurbs with version >= 200910190, + a TCODE_USER_TABLE_RECORD_HEADER chunk. +*/ +#define TCODE_USER_TABLE_UUID (TCODE_TABLEREC | TCODE_CRC | 0x0080) +/* the user record header was added in 200910190 and is inside the TCODE_USER_TABLE_UUID chunk */ +#define TCODE_USER_TABLE_RECORD_HEADER (TCODE_TABLEREC | TCODE_CRC | 0x0082) +/* information saved by the plug-in is in a TCODE_USER_RECORD chunk */ +#define TCODE_USER_RECORD (TCODE_TABLEREC | 0x0081) + + +/* records in group table */ +#define TCODE_GROUP_RECORD (TCODE_TABLEREC | TCODE_CRC | 0x0073) + +/* records in font table */ +#define TCODE_FONT_RECORD (TCODE_TABLEREC | TCODE_CRC | 0x0074) + +/* records in dimension style table */ +#define TCODE_DIMSTYLE_RECORD (TCODE_TABLEREC | TCODE_CRC | 0x0075) + +/* records in instance definition table */ +#define TCODE_INSTANCE_DEFINITION_RECORD (TCODE_TABLEREC | TCODE_CRC | 0x0076) + +/* records in hatch pattern table */ +#define TCODE_HATCHPATTERN_RECORD (TCODE_TABLEREC | TCODE_CRC | 0x0077) + +/* records in linetye pattern table */ +#define TCODE_LINETYPE_RECORD (TCODE_TABLEREC | TCODE_CRC | 0x0078) + +/* OBSOLETE records in layer set table */ +#define TCODE_OBSOLETE_LAYERSET_RECORD (TCODE_TABLEREC | TCODE_CRC | 0x0079) + +/* records in linetye pattern table */ +#define TCODE_TEXTURE_MAPPING_RECORD (TCODE_TABLEREC | TCODE_CRC | 0x007A) + +/* records in history record pattern table */ +#define TCODE_HISTORYRECORD_RECORD (TCODE_TABLEREC | TCODE_CRC | 0x007B) + +/* records in object table */ +#define TCODE_OBJECT_RECORD (TCODE_TABLEREC | TCODE_CRC | 0x0070) +#define TCODE_OBJECT_RECORD_TYPE (TCODE_INTERFACE | TCODE_SHORT | 0x0071) /* ON::object_type value */ +#define TCODE_OBJECT_RECORD_ATTRIBUTES (TCODE_INTERFACE | TCODE_CRC | 0x0072) /* ON_3dmObjectAttributes chunk */ +#define TCODE_OBJECT_RECORD_ATTRIBUTES_USERDATA (TCODE_INTERFACE | 0x0073) /* ON_3dmObjectAttributes userdata chunk */ +#define TCODE_OBJECT_RECORD_HISTORY (TCODE_INTERFACE | TCODE_CRC | 0x0074) /* construction history */ +#define TCODE_OBJECT_RECORD_HISTORY_HEADER (TCODE_INTERFACE | TCODE_CRC | 0x0075) /* construction history header*/ +#define TCODE_OBJECT_RECORD_HISTORY_DATA (TCODE_INTERFACE | TCODE_CRC | 0x0076) /* construction history data */ +#define TCODE_OBJECT_RECORD_END (TCODE_INTERFACE | TCODE_SHORT | 0x007F) + +/* +///////////////////////////////////////////////////////////////////////////////////// +// +// TCODE_OBJECT_RECORD +// 4 byte length of entire object record +// +// TCODE_OBJECT_RECORD_TYPE required - used to quickly filter and skip unwanted objects +// 4 byte ON::object_type +// +// TCODE_OPENNURBS_CLASS +// 4 byte length +// TCODE_OPENNURBS_CLASS_UUID +// 4 byte length = 20 +// value of ON_ClassId::m_uuid for this class +// 4 byte CRC +// TCODE_OPENNURBS_CLASS_DATA +// 4 byte length +// class specific data for geometry or annotation object +// 4 byte CRC +// TCODE_OPENNURBS_CLASS_USERDATA (1 chunk per piece of user data) +// 4 byte length +// 2 byte chunk version 2.1 +// TCODE_OPENNURBS_CLASS_USERDATA_HEADER +// 4 byte length +// 16 byte value of ON_ClassId::m_uuid for this child class of ON_UserData +// 16 byte value of ON_UserData::m_userdata_uuid +// 4 byte value of ON_UserData::m_userdata_copycount +// 128 byte value of ON_UserData::m_userdata_xform +// 16 byte value of ON_UserData::m_application_uuid (in ver 2.1 chunks) +// TCODE_ANONYMOUS_CHUNK +// 4 byte length +// specific user data +// TCODE_OPENNURBS_CLASS_END +// +// TCODE_OBJECT_RECORD_ATTRIBUTES (optional) +// 4 byte length +// ON_3dmObjectAttributes information +// 4 byte crc +// +// TCODE_OBJECT_RECORD_ATTRIBUTES_USERDATA (optional) +// 4 byte length +// TCODE_OPENNURBS_CLASS_USERDATA (1 chunk per piece of user data) +// 4 byte length +// 2 byte chunk version 2.1 +// TCODE_OPENNURBS_CLASS_USERDATA_HEADER +// 4 byte length +// 16 byte value of ON_ClassId::m_uuid for this child class of ON_UserData +// 16 byte value of ON_UserData::m_userdata_uuid +// 4 byte value of ON_UserData::m_userdata_copycount +// 128 byte value of ON_UserData::m_userdata_xform +// 16 byte value of ON_UserData::m_application_uuid (in ver 2.1 chunks) +// TCODE_ANONYMOUS_CHUNK +// 4 byte length +// specific user data +// +// TCODE_OBJECT_RECORD_HISTORY (optional) construction history +// 4 byte length +// 2 byte chunk version +// TCODE_OBJECT_RECORD_HISTORY_HEADER +// 4 byte length +// 2 byte chunk version +// ... +// 4 byte crc +// TCODE_OBJECT_RECORD_HISTORY_DATA +// 4 byte length +// 2 byte chunk version +// ... +// 4 byte crc +// +// TCODE_OBJECT_RECORD_END required - marks end of object record +// +///////////////////////////////////////////////////////////////////////////////////// +*/ + +#define TCODE_OPENNURBS_CLASS (TCODE_OPENNURBS_OBJECT | 0x7FFA) +#define TCODE_OPENNURBS_CLASS_UUID (TCODE_OPENNURBS_OBJECT | TCODE_CRC | 0x7FFB) +#define TCODE_OPENNURBS_CLASS_DATA (TCODE_OPENNURBS_OBJECT | TCODE_CRC | 0x7FFC) +#define TCODE_OPENNURBS_CLASS_USERDATA (TCODE_OPENNURBS_OBJECT | 0x7FFD) +#define TCODE_OPENNURBS_CLASS_USERDATA_HEADER (TCODE_OPENNURBS_OBJECT | TCODE_CRC | 0x7FF9) +#define TCODE_OPENNURBS_CLASS_END (TCODE_OPENNURBS_OBJECT | TCODE_SHORT | 0x7FFF) + +/* +///////////////////////////////////////////////////////////////////////////////////// +// +// TCODE_OPENNURBS_CLASS +// length of entire openNURBS class object chunk +// +// TCODE_OPENNURBS_CLASS_UUID +// length of uuid (16 byte UUID + 4 byte CRC) +// 16 byte UUID ( a.k.a. GUID ) openNURBS class ID - determines specific openNURBS class +// 4 bytes (32 bit CRC of the UUID) +// +// TCODE_OPENNURBS_CLASS_DATA +// length of object data +// ... data that defines object +// use ON_classname::Read() to read this data and ON_classname::Write() +// to write this data +// 4 bytes (32 bit CRC of the object data) +// +// TCODE_OPENNURBS_CLASS_USERDATA ( 0 or more user data chunks) +// +// TCODE_OPENNURBS_CLASS_END +// 4 bytes = 0 +// +///////////////////////////////////////////////////////////////////////////////////// +*/ + +/* +///////////////////////////////////////////////////////////////////////////////////// +// +// +// The TCODEs below were used in the version 1 file format and are needed so that +// the these files can be read and (optionally) written by the current OpenNURBS +// toolkit. +// +// +///////////////////////////////////////////////////////////////////////////////////// +*/ + + +#define TCODE_ANNOTATION_SETTINGS (TCODE_ANNOTATION | 0x0001) + +#define TCODE_TEXT_BLOCK (TCODE_ANNOTATION | 0x0004) +#define TCODE_ANNOTATION_LEADER (TCODE_ANNOTATION | 0x0005) +#define TCODE_LINEAR_DIMENSION (TCODE_ANNOTATION | 0x0006) +#define TCODE_ANGULAR_DIMENSION (TCODE_ANNOTATION | 0x0007) +#define TCODE_RADIAL_DIMENSION (TCODE_ANNOTATION | 0x0008) + +/* old RhinoIO toolkit (pre February 2000) defines */ +#define TCODE_RHINOIO_OBJECT_NURBS_CURVE (TCODE_OPENNURBS_OBJECT | 0x0008) /* old CRhinoNurbsCurve */ +#define TCODE_RHINOIO_OBJECT_NURBS_SURFACE (TCODE_OPENNURBS_OBJECT | 0x0009) /* old CRhinoNurbsSurface */ +#define TCODE_RHINOIO_OBJECT_BREP (TCODE_OPENNURBS_OBJECT | 0x000B) /* old CRhinoBrep */ +#define TCODE_RHINOIO_OBJECT_DATA (TCODE_OPENNURBS_OBJECT | 0xFFFE) /* obsolete - don't confuse with TCODE_OPENNURBS_OBJECT_DATA */ +#define TCODE_RHINOIO_OBJECT_END (TCODE_OPENNURBS_OBJECT | 0xFFFF) /* obsolete - don't confuse with TCODE_OPENNURBS_OBJECT_END */ + +/* OpenNURBS classes the require a unique tcode */ +#define TCODE_OPENNURBS_BUFFER (TCODE_OPENNURBS_OBJECT | TCODE_CRC | 0x0100) /* chunk stores ON_Buffer classes */ + +/* legacy objects from Rhino 1.x */ +#define TCODE_LEGACY_ASM (TCODE_LEGACY_GEOMETRY | 0x0001) +#define TCODE_LEGACY_PRT (TCODE_LEGACY_GEOMETRY | 0x0002) +#define TCODE_LEGACY_SHL (TCODE_LEGACY_GEOMETRY | 0x0003) +#define TCODE_LEGACY_FAC (TCODE_LEGACY_GEOMETRY | 0x0004) +#define TCODE_LEGACY_BND (TCODE_LEGACY_GEOMETRY | 0x0005) +#define TCODE_LEGACY_TRM (TCODE_LEGACY_GEOMETRY | 0x0006) +#define TCODE_LEGACY_SRF (TCODE_LEGACY_GEOMETRY | 0x0007) +#define TCODE_LEGACY_CRV (TCODE_LEGACY_GEOMETRY | 0x0008) +#define TCODE_LEGACY_SPL (TCODE_LEGACY_GEOMETRY | 0x0009) +#define TCODE_LEGACY_PNT (TCODE_LEGACY_GEOMETRY | 0x000A) + +#define TCODE_STUFF 0x0100 + +#define TCODE_LEGACY_ASMSTUFF (TCODE_LEGACY_GEOMETRY | TCODE_STUFF | TCODE_LEGACY_ASM) +#define TCODE_LEGACY_PRTSTUFF (TCODE_LEGACY_GEOMETRY | TCODE_STUFF | TCODE_LEGACY_PRT) +#define TCODE_LEGACY_SHLSTUFF (TCODE_LEGACY_GEOMETRY | TCODE_STUFF | TCODE_LEGACY_SHL) +#define TCODE_LEGACY_FACSTUFF (TCODE_LEGACY_GEOMETRY | TCODE_STUFF | TCODE_LEGACY_FAC) +#define TCODE_LEGACY_BNDSTUFF (TCODE_LEGACY_GEOMETRY | TCODE_STUFF | TCODE_LEGACY_BND) +#define TCODE_LEGACY_TRMSTUFF (TCODE_LEGACY_GEOMETRY | TCODE_STUFF | TCODE_LEGACY_TRM) +#define TCODE_LEGACY_SRFSTUFF (TCODE_LEGACY_GEOMETRY | TCODE_STUFF | TCODE_LEGACY_SRF) +#define TCODE_LEGACY_CRVSTUFF (TCODE_LEGACY_GEOMETRY | TCODE_STUFF | TCODE_LEGACY_CRV) +#define TCODE_LEGACY_SPLSTUFF (TCODE_LEGACY_GEOMETRY | TCODE_STUFF | TCODE_LEGACY_SPL) +#define TCODE_LEGACY_PNTSTUFF (TCODE_LEGACY_GEOMETRY | TCODE_STUFF | TCODE_LEGACY_PNT) + +/* legacy objects from Rhino 1.x */ +#define TCODE_RH_POINT (TCODE_GEOMETRY | 0x0001) + +#define TCODE_RH_SPOTLIGHT (TCODE_RENDER | 0x0001) + +#define TCODE_OLD_RH_TRIMESH (TCODE_GEOMETRY | 0x0011) +#define TCODE_OLD_MESH_VERTEX_NORMALS (TCODE_GEOMETRY | 0x0012) +#define TCODE_OLD_MESH_UV (TCODE_GEOMETRY | 0x0013) +#define TCODE_OLD_FULLMESH (TCODE_GEOMETRY | 0x0014) + + +#define TCODE_MESH_OBJECT (TCODE_GEOMETRY | 0x0015) +#define TCODE_COMPRESSED_MESH_GEOMETRY (TCODE_GEOMETRY | 0x0017) +#define TCODE_ANALYSIS_MESH (TCODE_GEOMETRY | 0x0018) + +#define TCODE_NAME (TCODE_INTERFACE | 0x0001) +#define TCODE_VIEW (TCODE_INTERFACE | 0x0002) +#define TCODE_CPLANE (TCODE_INTERFACE | 0x0003) + +#define TCODE_NAMED_CPLANE (TCODE_INTERFACE | 0x0004) +#define TCODE_NAMED_VIEW (TCODE_INTERFACE | 0x0005) +#define TCODE_VIEWPORT (TCODE_INTERFACE | 0x0006) + +#define TCODE_SHOWGRID (TCODE_SHORT | TCODE_INTERFACE | 0x0007) +#define TCODE_SHOWGRIDAXES (TCODE_SHORT | TCODE_INTERFACE | 0x0008) +#define TCODE_SHOWWORLDAXES (TCODE_SHORT | TCODE_INTERFACE | 0x0009) + +#define TCODE_VIEWPORT_POSITION (TCODE_INTERFACE | 0x000A) +#define TCODE_VIEWPORT_TRACEINFO (TCODE_INTERFACE | 0x000B) +#define TCODE_SNAPSIZE (TCODE_INTERFACE | 0x000C) +#define TCODE_NEAR_CLIP_PLANE (TCODE_INTERFACE | 0x000D) +#define TCODE_HIDE_TRACE (TCODE_INTERFACE | 0x000E) + +#define TCODE_NOTES (TCODE_INTERFACE | 0x000F) +#define TCODE_UNIT_AND_TOLERANCES (TCODE_INTERFACE | 0x0010) + +#define TCODE_MAXIMIZED_VIEWPORT (TCODE_SHORT | TCODE_INTERFACE | 0x0011) +#define TCODE_VIEWPORT_WALLPAPER (TCODE_INTERFACE | 0x0012) + + +#define TCODE_SUMMARY (TCODE_INTERFACE | 0x0013) +#define TCODE_BITMAPPREVIEW (TCODE_INTERFACE | 0x0014) +#define TCODE_VIEWPORT_V1_DISPLAYMODE (TCODE_SHORT | TCODE_INTERFACE | 0x0015) + + +#define TCODE_LAYERTABLE (TCODE_SHORT | TCODE_TABLE | 0x0001) /* obsolete - do not use */ +#define TCODE_LAYERREF (TCODE_SHORT | TCODE_TABLEREC | 0x0001) + +#define TCODE_RGB (TCODE_SHORT | TCODE_DISPLAY | 0x0001) +#define TCODE_TEXTUREMAP (TCODE_DISPLAY | 0x0002) +#define TCODE_BUMPMAP (TCODE_DISPLAY | 0x0003) +#define TCODE_TRANSPARENCY (TCODE_SHORT | TCODE_DISPLAY | 0x0004) +#define TCODE_DISP_AM_RESOLUTION (TCODE_SHORT | TCODE_DISPLAY | 0x0005) +#define TCODE_RGBDISPLAY (TCODE_SHORT | TCODE_DISPLAY | 0x0006) /* will be used for color by object */ +#define TCODE_RENDER_MATERIAL_ID (TCODE_DISPLAY | 0x0007) /* id for render material */ + +#define TCODE_LAYER (TCODE_DISPLAY | 0x0010) + +/* obsolete layer typecodes from earlier betas - not used anymore */ +#define TCODE_LAYER_OBSELETE_1 (TCODE_SHORT | TCODE_DISPLAY | 0x0013) +#define TCODE_LAYER_OBSELETE_2 (TCODE_SHORT | TCODE_DISPLAY | 0x0014) +#define TCODE_LAYER_OBSELETE_3 (TCODE_SHORT | TCODE_DISPLAY | 0x0015) + +/* these were only ever used by AccuModel and never by Rhino */ +#define TCODE_LAYERON (TCODE_SHORT | TCODE_DISPLAY | 0x0016) +#define TCODE_LAYERTHAWED (TCODE_SHORT | TCODE_DISPLAY | 0x0017) +#define TCODE_LAYERLOCKED (TCODE_SHORT | TCODE_DISPLAY | 0x0018) + + +#define TCODE_LAYERVISIBLE (TCODE_SHORT | TCODE_DISPLAY | 0x0012) +#define TCODE_LAYERPICKABLE (TCODE_SHORT | TCODE_DISPLAY | 0x0030) +#define TCODE_LAYERSNAPABLE (TCODE_SHORT | TCODE_DISPLAY | 0x0031) +#define TCODE_LAYERRENDERABLE (TCODE_SHORT | TCODE_DISPLAY | 0x0032) + + +/* use LAYERSTATE ( 0 = LAYER_ON, 1 = LAYER_OFF, 2 = LAYER_LOCKED ) instead of above individual toggles */ +#define TCODE_LAYERSTATE (TCODE_SHORT | TCODE_DISPLAY | 0x0033) +#define TCODE_LAYERINDEX (TCODE_SHORT | TCODE_DISPLAY | 0x0034) +#define TCODE_LAYERMATERIALINDEX (TCODE_SHORT | TCODE_DISPLAY | 0x0035) + +#define TCODE_RENDERMESHPARAMS (TCODE_DISPLAY | 0x0020) /* block of parameters for render meshes */ + + + +#define TCODE_DISP_CPLINES (TCODE_SHORT | TCODE_DISPLAY | 0x0022) +#define TCODE_DISP_MAXLENGTH (TCODE_DISPLAY | 0x0023) + +#define TCODE_CURRENTLAYER (TCODE_SHORT | TCODE_DISPLAY | 0x0025 ) + +#define TCODE_LAYERNAME (TCODE_DISPLAY | 0x0011) + +#define TCODE_LEGACY_TOL_FIT (TCODE_TOLERANCE | 0x0001) +#define TCODE_LEGACY_TOL_ANGLE (TCODE_TOLERANCE | 0x0002) + +#endif diff --git a/opennurbs/Include/opennurbs_3dm_attributes.h b/opennurbs/Include/opennurbs_3dm_attributes.h new file mode 100644 index 0000000..9baad4c --- /dev/null +++ b/opennurbs/Include/opennurbs_3dm_attributes.h @@ -0,0 +1,590 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +//////////////////////////////////////////////////////////////// +// +// defines ON_3dmObjectAttributes +// +//////////////////////////////////////////////////////////////// + +#if !defined(OPENNURBS_3DM_ATTRIBUTES_INC_) +#define OPENNURBS_3DM_ATTRIBUTES_INC_ + + +/* +Description: + Top level OpenNURBS objects have geometry and attributes. The + geometry is stored in some class derived from ON_Geometry and + the attributes are stored in an ON_3dmObjectAttributes class. + Examples of attributes are object name, object id, display + attributes, group membership, layer membership, and so on. + +Remarks: + 7 January 2003 Dale Lear + Derived from ON_Object so ON_UserData can be attached + to ON_3dmObjectAttributes. +*/ + +class ON_CLASS ON_3dmObjectAttributes : public ON_Object +{ + ON_OBJECT_DECLARE(ON_3dmObjectAttributes); + +public: + static const ON_3dmObjectAttributes Unset; + static const ON_3dmObjectAttributes DefaultAttributes; + +public: + // ON_Object virtual interface. See ON_Object + // for details. + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + // virtual + void Dump( ON_TextLog& ) const override; + // virtual + unsigned int SizeOf() const override; + // virtual + bool Write(ON_BinaryArchive&) const override; + // virtual + bool Read(ON_BinaryArchive&) override; + + /* + Returns: + True if successful. + (xform is invertable or didn't need to be). + */ + bool Transform( const ON_Xform& xform ); + + // attributes of geometry and dimension table objects +public: + ON_3dmObjectAttributes(); + ~ON_3dmObjectAttributes(); + + // Default C++ copy constructor and operator= work fine + // Do not provide custom versions + // NO // ON_3dmObjectAttributes(const ON_3dmObjectAttributes&); + // NO // ON_3dmObjectAttributes& operator=(const ON_3dmObjectAttributes&); + + bool operator==(const ON_3dmObjectAttributes&) const; + bool operator!=(const ON_3dmObjectAttributes&) const; + + // Initializes all attributes to the default values. + void Default(); + + + bool UpdateReferencedComponents( + const class ON_ComponentManifest& source_manifest, + const class ON_ComponentManifest& destination_manifest, + const class ON_ManifestMap& manifest_map + ) override; + + // Interface //////////////////////////////////////////////////////// + + // An OpenNURBS object must be in one of three modes: normal, locked + // or hidden. If an object is in normal mode, then the object's layer + // controls visibility and selectability. If an object is locked, then + // the object's layer controls visibility by the object cannot be selected. + // If the object is hidden, it is not visible and it cannot be selected. + ON::object_mode Mode() const; + void SetMode( ON::object_mode ); // See Mode(). + + /* + Description: + Use this query to determine if an object is part of an + instance definition. + Returns: + True if the object is part of an instance definition. + */ + bool IsInstanceDefinitionObject() const; + + /* + Returns: + Returns true if object is visible. + See Also: + ON_3dmObjectAttributes::SetVisible + */ + bool IsVisible() const; + + /* + Description: + Controls object visibility + Parameters: + bVisible - [in] true to make object visible, + false to make object invisible + See Also: + ON_3dmObjectAttributes::IsVisible + */ + void SetVisible( bool bVisible ); + + // The Linetype used to display an OpenNURBS object is specified in one of two ways. + // If LinetypeSource() is ON::linetype_from_layer, then the object's layer + // ON_Layer::Linetype() is used. + // If LinetypeSource() is ON::linetype_from_object, then value of m_linetype is used. + ON::object_linetype_source LinetypeSource() const; + void SetLinetypeSource( ON::object_linetype_source ); // See LinetypeSource(). + + // The color used to display an OpenNURBS object is specified in one of three ways. + // If ColorSource() is ON::color_from_layer, then the object's layer + // ON_Layer::Color() is used. + // If ColorSource() is ON::color_from_object, then value of m_color is used. + // If ColorSource() is ON::color_from_material, then the diffuse color of the object's + // render material is used. See ON_3dmObjectAttributes::MaterialSource() to + // determine where to get the definition of the object's render material. + ON::object_color_source ColorSource() const; + void SetColorSource( ON::object_color_source ); // See ColorSource(). + + // The color used to plot an OpenNURBS object on paper is specified + // in one of three ways. + // If PlotColorSource() is ON::plot_color_from_layer, then the object's layer + // ON_Layer::PlotColor() is used. + // If PlotColorSource() is ON::plot_color_from_object, then value of PlotColor() is used. + ON::plot_color_source PlotColorSource() const; + void SetPlotColorSource( ON::plot_color_source ); // See PlotColorSource(). + + ON::plot_weight_source PlotWeightSource() const; + void SetPlotWeightSource( ON::plot_weight_source ); + + /* + Description: + If "this" has attributes (color, plot weight, ...) with + "by parent" sources, then the values of those attributes + on parent_attributes are copied. + Parameters: + parent_attributes - [in] + parent_layer - [in] + control_limits - [in] + The bits in control_limits determine which attributes may + may be copied. + 1: visibility + 2: color + 4: render material + 8: plot color + 0x10: plot weight + 0x20: linetype + 0x40: display order + + Returns: + The bits in the returned integer indicate which attributes were + actually modified. + + 1: visibility + 2: color + 4: render material + 8: plot color + 0x10: plot weight + 0x20: linetype + 0x40: display order + */ + //ON_DEPRECATED unsigned int ApplyParentalControl( + // const ON_3dmObjectAttributes& parent_attributes, + // unsigned int control_limits = 0xFFFFFFFF + // ); + + unsigned int ApplyParentalControl( + const ON_3dmObjectAttributes& parent_attributes, + const ON_Layer& parent_layer, + unsigned int control_limits = 0xFFFFFFFF + ); + + // Every OpenNURBS object has a UUID (universally unique identifier). The + // default value is nullptr. When an OpenNURBS object is added to a model, the + // value is checked. If the value is nullptr, a new UUID is created. If the + // value is not nullptr but it is already used by another object in the model, + // a new UUID is created. If the value is not nullptr and it is not used by + // another object in the model, then that value persists. When an object + // is updated, by a move for example, the value of m_uuid persists. + ON_UUID m_uuid; + + // The m_name member is public to avoid breaking the SDK. + // Use SetName() and Name() for proper validation. + // OpenNURBS object have optional text names. More than one object in + // a model can have the same name and some objects may have no name. + // ON_ModelComponent::IsValidComponentName(m_name) should be true. + ON_wString m_name; + + bool SetName( + const wchar_t* name, + bool bFixInvalidName + ); + + const ON_wString Name() const; + + // OpenNURBS objects may have an URL. There are no restrictions on what + // value this URL may have. As an example, if the object came from a + // commercial part library, the URL might point to the definition of that + // part. + ON_wString m_url; + + // Layer definitions in an OpenNURBS model are stored in a layer table. + // The layer table is conceptually an array of ON_Layer classes. Every + // OpenNURBS object in a model is on some layer. The object's layer + // is specified by zero based indicies into the ON_Layer array. + int m_layer_index; + + // Linetype definitions in an OpenNURBS model are stored in a linetype table. + // The linetype table is conceptually an array of ON_Linetype classes. Every + // OpenNURBS object in a model references some linetype. The object's linetype + // is specified by zero based indicies into the ON_Linetype array. + // index 0 is reserved for continuous linetype (no pattern) + int m_linetype_index; + + // Rendering material: + // If you want something simple and fast, set + // m_material_index to the index of the rendering material + // and ignore m_rendering_attributes. + // If you are developing a high quality plug-in renderer, + // and a user is assigning one of your fabulous rendering + // materials to this object, then add rendering material + // information to the m_rendering_attributes.m_materials[] + // array. + // + // Developers: + // As soon as m_rendering_attributes.m_materials[] is not empty, + // rendering material queries slow down. Do not populate + // m_rendering_attributes.m_materials[] when setting + // m_material_index will take care of your needs. + int m_material_index; + ON_ObjectRenderingAttributes m_rendering_attributes; + + ////////////////////////////////////////////////////////////////// + // + // BEGIN: Per object mesh parameter support + // + + /* + Parameters: + mp - [in] + per object mesh parameters + Returns: + True if successful. + */ + bool SetCustomRenderMeshParameters(const class ON_MeshParameters& mp); + + /* + Parameters: + bEnable - [in] + true to enable use of the per object mesh parameters. + false to disable use of the per object mesh parameters. + Returns: + False if the object doe not have per object mesh parameters + and bEnable was true. Use SetMeshParameters() to set + per object mesh parameters. + Remarks: + Sets the value of ON_MeshParameters::m_bCustomSettingsDisabled + to !bEnable + */ + bool EnableCustomRenderMeshParameters(bool bEnable); + + /* + Returns: + Null or a pointer to fragile mesh parameters. + If a non-null pointer is returned, copy it and use the copy. + * DO NOT SAVE THIS POINTER FOR LATER USE. A call to + DeleteMeshParameters() will delete the class. + * DO NOT const_cast the returned pointer and change its + settings. You must use either SetMeshParameters() + or EnableMeshParameters() to change settings. + Remarks: + If the value of ON_MeshParameters::m_bCustomSettingsDisabled is + true, then do no use these parameters to make a render mesh. + */ + const ON_MeshParameters* CustomRenderMeshParameters() const; + + /* + Description: + Deletes any per object mesh parameters. + */ + void DeleteCustomRenderMeshParameters(); + + // + // END: Per object mesh parameter support + // + ////////////////////////////////////////////////////////////////// + + + /* + Description: + Determine if the simple material should come from + the object or from it's layer. + High quality rendering plug-ins should use m_rendering_attributes. + Returns: + Where to get material information if you do are too lazy + to look in m_rendering_attributes.m_materials[]. + */ + ON::object_material_source MaterialSource() const; + + /* + Description: + Specifies if the simple material should be the one + indicated by the material index or the one indicated + by the object's layer. + Parameters: + ms - [in] + */ + void SetMaterialSource( ON::object_material_source ms ); + + // If ON::color_from_object == ColorSource(), then m_color is the object's + // display color. + ON_Color m_color; + + // If ON::plot_color_from_object == PlotColorSource(), then m_color is the object's + // display color. + ON_Color m_plot_color; + + // Display order used to force objects to be drawn on top or behind each other + // 0 = draw object in standard depth buffered order + // <0 = draw object behind "normal" draw order objects + // >0 = draw object on top of "noraml" draw order objects + // Larger number draws on top of smaller number. + int m_display_order; + + // Plot weight in millimeters. + // =0.0 means use the default width + // <0.0 means don't plot (visible for screen display, but does not show on plot) + double m_plot_weight_mm; + + // Used to indicate an object has a decoration (like an arrowhead on a curve) + ON::object_decoration m_object_decoration; + + // When a surface object is displayed in wireframe, m_wire_density controls + // how many isoparametric wires are used. + // + // @table + // value number of isoparametric wires + // -1 boundary wires + // 0 boundary and knot wires + // 1 boundary and knot wires and, if there are no + // interior knots, a single interior wire. + // N>=2 boundary and knot wires and (N-1) interior wires + int m_wire_density; + + + // If m_viewport_id is nil, the object is active in + // all viewports. If m_viewport_id is not nil, then + // this object is only active in a specific view. + // This field is primarily used to assign page space + // objects to a specific page, but it can also be used + // to restrict model space to a specific view. + ON_UUID m_viewport_id; + + // Starting with V4, objects can be in either model space + // or page space. If an object is in page space, then + // m_viewport_id is not nil and identifies the page it + // is on. + ON::active_space m_space; + +private: + bool m_bVisible; + unsigned char m_mode; // (m_mode % 16) = ON::object_mode values + // (m_mode / 16) = ON::display_mode values + unsigned char m_color_source; // ON::object_color_source values + unsigned char m_plot_color_source; // ON::plot_color_source values + unsigned char m_plot_weight_source; // ON::plot_weight_source values + unsigned char m_material_source; // ON::object_material_source values + unsigned char m_linetype_source; // ON::object_linetype_source values + + unsigned char m_reserved_0; + + ON_Xform m_reserved_future_frame = ON_Xform::Nan; + + ON_SimpleArray m_group; // array of zero based group indices + +private: + ON__UINT_PTR m_reserved_ptr = 0; + +public: + // group interface + + // returns number of groups object belongs to + int GroupCount() const; + + // Returns and array an array of GroupCount() zero based + // group indices. If GroupCount() is zero, then GroupList() + // returns nullptr. + const int* GroupList() const; + + // Returns GroupCount() and puts a list of zero based group indices + // into the array. + int GetGroupList(ON_SimpleArray&) const; + + // Returns the index of the last group in the group list + // or -1 if the object is not in any groups + int TopGroup() const; + + // Returns true if object is in group with the specified index + bool IsInGroup( + int // zero based group index + ) const; + + // Returns true if the object is in any of the groups in the list + bool IsInGroups( + int, // group_list_count + const int* // group_list[] array + ) const; + + // Returns true if object is in any of the groups in the list + bool IsInGroups( + const ON_SimpleArray& // group_list[] array + ) const; + + // Adds object to the group with specified index by appending index to + // group list (If the object is already in group, nothing is changed.) + void AddToGroup( + int // zero based group index + ); + + // Removes object from the group with specified index. If the + // object is not in the group, nothing is changed. + void RemoveFromGroup( + int // zero based group index + ); + + // removes the object from the last group in the group list + void RemoveFromTopGroup(); + + // Removes object from all groups. + void RemoveFromAllGroups(); + + + // display material references + + /* + Description: + Searches for a matching display material. For a given + viewport id, there is at most one display material. + For a given display material id, there can be multiple + viewports. If there is a display reference in the + list with a nil viewport id, then the display material + will be used in all viewports that are not explictly + referenced in other ON_DisplayMaterialRefs. + + Parameters: + search_material - [in] + found_material - [out] + + If FindDisplayMaterialRef(), the input value of search_material + is never changed. If FindDisplayMaterialRef() returns true, + the chart shows the output value of display_material. When + there are multiple possibilities for a match, the matches + at the top of the chart have higher priority. + + search_material found_material + input value output value + + (nil,nil) (nil,did) if (nil,did) is in the list. + (nil,did) (vid,did) if (vid,did) is in the list. + (nil,did) (nil,did) if (nil,did) is in the list. + (vid,nil) (vid,did) if (vid,did) is in the list + (vid,nil) (vid,did) if (nil,did) is in the list + (vid,did) (vid,did) if (vid,did) is in the list. + + Example: + ON_UUID display_material_id = ON_nil_uuid; + ON_Viewport vp = ...; + ON_DisplayMaterialRef search_dm; + search_dm.m_viewport_id = vp.ViewportId(); + ON_DisplayMaterialRef found_dm; + if ( attributes.FindDisplayMaterial(search_dm, &found_dm) ) + { + display_material_id = found_dm.m_display_material_id; + } + + Returns: + True if a matching display material is found. + See Also: + ON_3dmObjectAttributes::AddDisplayMaterialRef + ON_3dmObjectAttributes::RemoveDisplayMaterialRef + */ + bool FindDisplayMaterialRef( + const ON_DisplayMaterialRef& search_material, + ON_DisplayMaterialRef* found_material = nullptr + ) const; + + /* + Description: + Quick way to see if a viewport has a special material. + Parameters: + viewport_id - [in] + display_material_id - [out] + Returns: + True if a material_id is assigned. + */ + bool FindDisplayMaterialId( + const ON_UUID& viewport_id, + ON_UUID* display_material_id = nullptr + ) const; + + /* + Description: + Add a display material reference to the attributes. If + there is an existing entry with a matching viewport id, + the existing entry is replaced. + Parameters: + display_material - [in] + Returns: + True if input is valid (material id != nil) + See Also: + ON_3dmObjectAttributes::FindDisplayMaterialRef + ON_3dmObjectAttributes::RemoveDisplayMaterialRef + */ + bool AddDisplayMaterialRef( + ON_DisplayMaterialRef display_material + ); + + /* + Description: + Remove a display material reference from the list. + Parameters: + viewport_id - [in] Any display material references + with this viewport id will be removed. If nil, + then viewport_id is ignored. + display_material_id - [in] + Any display material references that match the + viewport_id and have this display_material_id + will be removed. If nil, then display_material_id + is ignored. + Returns: + True if a display material reference was removed. + See Also: + ON_3dmObjectAttributes::FindDisplayMaterialRef + ON_3dmObjectAttributes::AddDisplayMaterialRef + */ + bool RemoveDisplayMaterialRef( + ON_UUID viewport_id, + ON_UUID display_material_id = ON_nil_uuid + ); + + /* + Description: + Remove a the entire display material reference list. + */ + void RemoveAllDisplayMaterialRefs(); + + /* + Returns: + Number of diplay material refences. + */ + int DisplayMaterialRefCount() const; + + ON_SimpleArray m_dmref; + +private: + bool Internal_WriteV5( ON_BinaryArchive& archive ) const; + bool Internal_ReadV5( ON_BinaryArchive& archive ); +}; + +#endif + +// Brian G adding another comment on Tim's machine. \ No newline at end of file diff --git a/opennurbs/Include/opennurbs_3dm_properties.h b/opennurbs/Include/opennurbs_3dm_properties.h new file mode 100644 index 0000000..f6700a0 --- /dev/null +++ b/opennurbs/Include/opennurbs_3dm_properties.h @@ -0,0 +1,186 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_3DM_PROPERTIES_INC_) +#define OPENNURBS_3DM_PROPERTIES_INC_ + +////////////////////////////////////////////////////////////////////////////////////////// + +class ON_CLASS ON_3dmRevisionHistory +{ +public: + /* + Default construction sets this = ON_3dmRevisionHistory::Empty + */ + ON_3dmRevisionHistory(); + + ~ON_3dmRevisionHistory() = default; + + ON_3dmRevisionHistory(const ON_3dmRevisionHistory&) = default; + ON_3dmRevisionHistory& operator=(const ON_3dmRevisionHistory&) = default; + + /* + Description: + The Empty revision has a revision number zero, + all time values set to zero and all string + values empty. + */ + static const ON_3dmRevisionHistory Empty; + + /* + Returns: + A revision history with + m_revision_count = 1 + m_create_time = now + m_last_edit_time = now + m_sCreatedBy = current user + m_sLastEditedBy = current user + */ + static ON_3dmRevisionHistory FirstRevision(); + + int NewRevision(); // returns updated revision count + + bool IsValid() const; + bool IsEmpty() const; + bool Read( ON_BinaryArchive& ); + bool Write( ON_BinaryArchive& ) const; + void Dump( ON_TextLog& ) const; + + /* + Returns: + true + if m_create_time is >= January 1, 1970 + */ + bool CreateTimeIsSet() const; + + /* + Returns: + true + if m_last_edit_time is >= January 1, 1970 + */ + bool LastEditedTimeIsSet() const; + + ON_wString m_sCreatedBy; + ON_wString m_sLastEditedBy; + struct tm m_create_time; // UCT create time + struct tm m_last_edit_time; // UCT las edited time + int m_revision_count = 0; +}; + +////////////////////////////////////////////////////////////////////////////////////////// + +class ON_CLASS ON_3dmNotes +{ +public: + ON_3dmNotes(); + ~ON_3dmNotes(); + + static const ON_3dmNotes Empty; + + bool IsValid() const; + bool IsEmpty() const; + + bool Read( ON_BinaryArchive& ); + bool Write( ON_BinaryArchive& ) const; + + void Dump(ON_TextLog&) const; + + //////////////////////////////////////////////////////////////// + // + // Interface - this information is serialized. Applications + // may want to derive a runtime class that has additional + // window and font information. + ON_wString m_notes; + + bool m_bVisible; // true if notes window is showing + bool m_bHTML; // true if notes are in HTML + + // last window position + int m_window_left; + int m_window_top; + int m_window_right; + int m_window_bottom; +}; + +////////////////////////////////////////////////////////////////////////////////////////// + +class ON_CLASS ON_3dmApplication +{ + // application that created the 3dm file +public: + ON_3dmApplication(); + ~ON_3dmApplication(); + + static const ON_3dmApplication Empty; + + bool IsValid() const; + + bool IsEmpty() const; + + bool Read( ON_BinaryArchive& ); + bool Write( ON_BinaryArchive& ) const; + + void Dump( ON_TextLog& ) const; + + ON_wString m_application_name; // short name like "Rhino 2.0" + ON_wString m_application_URL; // URL + ON_wString m_application_details; // whatever you want +}; + +////////////////////////////////////////////////////////////////////////////////////////// + +class ON_CLASS ON_3dmProperties +{ +public: + ON_3dmProperties() = default; + ~ON_3dmProperties() = default;; + ON_3dmProperties(const ON_3dmProperties&) = default; + ON_3dmProperties& operator=(const ON_3dmProperties&) = default; + + static const ON_3dmProperties Empty; + + bool IsEmpty() const; + + bool Read( + ON_BinaryArchive& archive + ); + + /* + Remarks: + If archive.ArchiveFileName() is not empty, that value is + written in place of m_3dmArchiveFullPathName in the 3dm archive. + If archive.ArchiveFileName() is empty, then m_3dmArchiveFullPathName + is written in the 3dm archive. + */ + bool Write( + ON_BinaryArchive& archive + ) const; + + void Dump( ON_TextLog& ) const; + + ON_3dmRevisionHistory m_RevisionHistory; + ON_3dmNotes m_Notes; + ON_WindowsBitmap m_PreviewImage; // preview image of model + ON_3dmApplication m_Application; // application that created 3DM file + + // name of .3dm archive when it was written. Used to find referenced files + // when the archive is moved or copied and then read. + ON_wString m_3dmArchiveFullPathName; +}; + +////////////////////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/opennurbs/Include/opennurbs_3dm_settings.h b/opennurbs/Include/opennurbs_3dm_settings.h new file mode 100644 index 0000000..2687ac1 --- /dev/null +++ b/opennurbs/Include/opennurbs_3dm_settings.h @@ -0,0 +1,1737 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_3DM_SETTINGS_INC_) +#define OPENNURBS_3DM_SETTINGS_INC_ + + +/////////////////////////////////////////////////////////////////////// +// +// units and tolerances +// + +class ON_CLASS ON_3dmUnitsAndTolerances +{ +public: + // The default constructor set units to millimeters and tolerance = 0.001mm + ON_3dmUnitsAndTolerances() = default; + ~ON_3dmUnitsAndTolerances() = default; + + ON_3dmUnitsAndTolerances(const ON_3dmUnitsAndTolerances&) = default; + ON_3dmUnitsAndTolerances& operator=(const ON_3dmUnitsAndTolerances&) = default; + + bool Read( ON_BinaryArchive& ); + bool Write( ON_BinaryArchive& ) const; + + void Dump( ON_TextLog& ) const; + + /* + Returns: + True if tolerances (m_absolute_tolerance, m_angle_tolerance, m_relative_tolerance) + are set to valid values. + */ + bool TolerancesAreValid() const; + + /* + Description: + If m_absolute_tolerance is not set to a valid value, it is set + to ON_3dmUnitsAndTolerances::DefaultValue.m_absolute_tolerance. + If m_angle_tolerance is not set to a valid value, it is set + to ON_3dmUnitsAndTolerances::DefaultValue.m_angle_tolerance. + If m_relative_tolerance is not set to a valid value, it is set + to ON_3dmUnitsAndTolerances::DefaultValue.m_relative_tolerance. + Returns: + 0: all tolerances were valid + 0 != (rc & 1): + m_absolute_tolerance was invalid and set to the default value + 0 != (rc & 2): + m_angle_tolerance was invalid and set to the default value + 0 != (rc & 4): + m_relative_tolerance was invalid and set to the default value + */ + unsigned int SetInvalidTolerancesToDefaultValues(); + + ////////// + // Returns scale factor that needs to be applied to change from + // the argument's unit system to m_unit_system. + // When m_unit_system is not ON::LengthUnitSystem::CustomUnits, + // Scale(us) = ON::UnitScale(us,m_unit_system). When Scale(us) + // When m_unit_system is ON::LengthUnitSystem::CustomUnits, + // Scale(us) = ON::UnitScale(us,ON::LengthUnitSystem::Meters)*m_custom_unit_scale. + double Scale( ON::LengthUnitSystem ) const; + + ON_UnitSystem m_unit_system = ON_UnitSystem::Millimeters; + + double m_absolute_tolerance = 0.001; // in units > 0.0 + double m_angle_tolerance = ON_PI/180.0; // in radians > 0.0 and <= ON_PI + double m_relative_tolerance = 0.01; // fraction > 0.0 and < 1.0 + + ON::OBSOLETE_DistanceDisplayMode m_distance_display_mode = ON::OBSOLETE_DistanceDisplayMode::Decimal; // decimal or fractional + int m_distance_display_precision = 3; // decimal mode: number of decimal places + // fractional modes: + // denominator = (1/2)^m_distance_display_precision + +public: + /* + DefaultValue + m_unit_system ON::LengthUnitSystem::Millimeters + m_absolute_tolerance 0.001 + m_angle_tolerance pi/180 = 1 degree + m_relative_tolerance 0.01 = 1% + m_distance_display_mode ON::OBSOLETE_DistanceDisplayMode::Decimal + m_distance_display_precision 3 + */ + static const ON_3dmUnitsAndTolerances Millimeters; +}; + +/////////////////////////////////////////////////////////////////////// +// +// Model settings +// render mesh defaults +// viewports +// construction planes +// + +class ON_CLASS ON_3dmAnnotationSettings +{ +public: + ON_3dmAnnotationSettings() = default; + ~ON_3dmAnnotationSettings() = default; + ON_3dmAnnotationSettings(const ON_3dmAnnotationSettings&) = default; + ON_3dmAnnotationSettings& operator=(const ON_3dmAnnotationSettings&) = default; + + static const ON_3dmAnnotationSettings Default; + + bool Read( ON_BinaryArchive& ); + bool Write( ON_BinaryArchive& ) const; + + void Dump( ON_TextLog& text_log ) const; + + // these are the running defaults for making dimensions + // they are also the things written to the 3dm file as dimension settings + double m_dimscale = 1.0; // model size / plotted size + double m_textheight = 1.0; + double m_dimexe = 1.0; + double m_dimexo = 1.0; + double m_arrowlength = 1.0; + double m_arrowwidth = 1.0; + double m_centermark = 1.0; + + /* + Returns: + Value of m_world_view_text_scale; + */ + double WorldViewTextScale() const; + + /* + Parameters: + world_view_text_scale - [in] + Sets value of m_world_view_text_scale. + */ + void SetWorldViewTextScale(double world_view_text_scale ); + + /* + Returns: + Value of m_world_view_hatch_scale; + */ + double WorldViewHatchScale() const; + + /* + Parameters: + world_view_hatch_scale - [in] + Sets value of m_world_view_hatch_scale. + */ + void SetWorldViewHatchScale(double world_view_hatch_scale ); + + + /* + Returns: + Value of m_b_V5_EnableAnnotationScaling; + */ + bool Is_V5_AnnotationScalingEnabled() const; + + /* + Parameters: + bEnable - [in] + Sets value of m_b_V5_EnableAnnotationScaling. + */ + void Enable_V5_AnnotationScaling(bool bEnable); + + /* + Parameters: + bEnable - [in] + Sets value of m_bEnableModelSpaceAnnotationScaling. + */ + void EnableModelSpaceAnnotationScaling(bool bEnable); + + /* + Returns: + Value of m_bEnableModelSpaceAnnotationScaling; + */ + bool IsModelSpaceAnnotationScalingEnabled() const; + + /* + Parameters: + bEnable - [in] + Sets value of m_bEnableLayoutSpaceAnnotationScaling. + */ + void EnableLayoutSpaceAnnotationScaling(bool bEnable); + + /* + Returns: + Value of m_bEnableLayoutSpaceAnnotationScaling; + */ + bool IsLayoutSpaceAnnotationScalingEnabled() const; + + /* + Returns: + Value of m_bEnableHatchScaling; + */ + bool IsHatchScalingEnabled() const; + + /* + Parameters: + bEnable - [in] + Sets value of m_bEnableHatchScaling. + */ + void EnableHatchScaling( bool bEnable ); + + // Present but not used in V4 or V5 - removed 5 August 2010 to make room + // for m_world_view_text_scale and m_bEnableAnnotationScaling + //// added 12/28/05 LW + //double m_dimdle; + //double m_dimgap; +private: + // If m_bEnableAnnotationScaling is true, + // and ON_OBSOLETE_V5_Annotation::m_annotative_scale is true, + // and ON_OBSOLETE_V5_Annotation::m_type == ON::dtTextBlock, + // and the text object is being displayed in a world + // view (not a detail view and not a page view), + // then the text will be scaled by m_world_view_text_scale. + // The default is 1.0. Values <= 0.0 are not valid. + float m_world_view_text_scale = 1.0f; + float m_world_view_hatch_scale = 1.0f; + +private: + // If m_bEnableAnnotationScaling is false: + // * m_world_view_text_scale is ignored. + // * text is not scaled. + // * ON_DimStyle::DimScale() determines the scale + // applied to all other annotation objects in all + // types of views. + // * The value of ON_DetailView::m_page_per_model_ratio + // is applied to all objects (annotation and geometry) + // in the detail view. + // + // If m_bEnableAnnotationScaling is true: + // * m_world_view_text_scale is used as described above. + // * ON_DimStyle::DimScale() determines the scale + // applied to all non text annotation objects in + // world views. + // * ON_DimStyle::DimScale() is ignored in page and + // detail views. + // * ON_DetailView::m_page_per_model_ratio is ingored + // for annotation objects in detail views, other + // geometry is scaled. + // + // Default is true. + unsigned char m_b_V5_EnableAnnotationScaling = 1; + + // [Lowell 3-28-2013] New fields for V6 + unsigned char m_bEnableModelSpaceAnnotationScaling = 1; + unsigned char m_bEnableLayoutSpaceAnnotationScaling = 1; + + unsigned char m_bEnableHatchScaling = 1; + +private: + ON__UINT32 m_reserved1 = 0; + ON__UINT8 m_reserved2 = 0; + ON__UINT8 m_reserved3 = 0; + ON__UINT8 m_reserved4 = 0; + +public: + ON::LengthUnitSystem m_dimunits = ON::LengthUnitSystem::None; // units used to measure the dimension + int m_arrowtype = 0; // 0: filled narrow triangular arrow (= ((ON_Arrowhead::arrow_type enum value as int ) - 2)) + int m_angularunits = 0; // 0: degrees, 1: radians + int m_lengthformat = 0; // 2 = ON_DimStyle::LengthDisplay::FeetAndInches, treat everything else as ON_DimStyle::LengthDisplay::ModelUnits + int m_angleformat = 0; // 0: decimal degrees, ... ( ON_DimStyle::angle_format enum as int ) + + //ON_INTERNAL_OBSOLETE::V5_TextDisplayMode m_settings_textalign; // In V2 files - 0: above line, 1: in line, 2: horizontal + // // After V2 files - 0: normal (converts to above_line), 1: horizontal, 2: above_line, 3: in_line + + int m_resolution = 0; // depends on m_lengthformat + // for decimal, digits past the decimal point + + ON_wString m_facename; // [LF_FACESIZE] // windows font name +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// +// ON_3dmConstructionPlaneGridDefaults +// +// Default settings used for construction plane grids +class ON_CLASS ON_3dmConstructionPlaneGridDefaults +{ +public: + ON_3dmConstructionPlaneGridDefaults() = default; + ~ON_3dmConstructionPlaneGridDefaults() = default; + ON_3dmConstructionPlaneGridDefaults(const ON_3dmConstructionPlaneGridDefaults&) = default; + ON_3dmConstructionPlaneGridDefaults& operator=(const ON_3dmConstructionPlaneGridDefaults&) = default; + + static const ON_3dmConstructionPlaneGridDefaults Default; + + bool Write( ON_BinaryArchive& ) const; + bool Read( ON_BinaryArchive& ); + + void Dump( ON_TextLog& text_log ) const; + + double m_grid_spacing = 1.0; // distance between grid lines + double m_snap_spacing = 1.0; // when "grid snap" is enabled, the + // distance between snap points. Typically + // this is the same distance as grid spacing. + int m_grid_line_count = 70; // number of grid lines in each direction + int m_grid_thick_frequency = 5; // thick line frequency + // 0: none, + // 1: all lines are thick, + // 2: every other is thick, ... + + bool m_bShowGrid = true; + bool m_bShowGridAxes = true; + bool m_bShowWorldAxes = true; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// +// ON_3dmConstructionPlane +// +class ON_CLASS ON_3dmConstructionPlane +{ +public: + ON_3dmConstructionPlane(); + ~ON_3dmConstructionPlane(); + + ON_3dmConstructionPlane(const ON_Plane& plane); + + // default copy constructor and operator= work fine + //ON_3dmConstructionPlane(const ON_3dmConstructionPlane&); + //ON_3dmConstructionPlane& operator=(const ON_3dmConstructionPlane&); + + void Default(); + + bool Write( ON_BinaryArchive& ) const; + bool Read( ON_BinaryArchive& ); + + void Dump( ON_TextLog& text_log ) const; + + ON_Plane m_plane; + + // construction grid appearance + double m_grid_spacing; // distance between grid lines + double m_snap_spacing; // when "grid snap" is enabled, the + // distance between snap points. Typically + // this is the same distance as grid spacing. + int m_grid_line_count; // number of grid lines in each direction + int m_grid_thick_frequency; // thick line frequency + // 0: none, + // 1: all lines are thick, + // 2: every other is thick, ... + bool m_bDepthBuffer; // false=grid is always drawn behind 3d geometry + // true=grid is drawn at its depth as a 3d plane + // and grid lines obscure things behind the grid. + + ON_wString m_name; +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; +#endif + +////////////////////////////////////////////////////////////////////////////////////////// +// +// ON_3dmViewPosition +// +class ON_CLASS ON_3dmViewPosition +{ +public: + // view window relative position and state in parent frame + ON_3dmViewPosition(); + ~ON_3dmViewPosition(); + ON_3dmViewPosition(const ON_3dmViewPosition&); + ON_3dmViewPosition& operator=(const ON_3dmViewPosition&); + + void Default(); + + bool Write( ON_BinaryArchive& ) const; + bool Read( ON_BinaryArchive& ); + + // relative position of view window in main frame + // if m_floating_viewport>0, this is relative position of the view window + // on the virtual screen (union of potentially multiple monitors) + double m_wnd_left; // 0.0 to 1.0 + double m_wnd_right; + double m_wnd_top; + double m_wnd_bottom; + + bool m_bMaximized; // true if view window is maximized + + // m_floating_viewport is used to track floating viewport information. + // 0 = the view is docked in the main application window. + // >0 = the view is floating. When floating, this corresponds to the + // number of monitors on on the user's computer when the file was saved + unsigned char m_floating_viewport; +private: + // reserved for future use + unsigned char m_reserved_1; + unsigned char m_reserved_2; + unsigned char m_reserved_3; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// +// ON_3dmViewTraceImage +// +class ON_CLASS ON_3dmViewTraceImage +{ +public: + ON_3dmViewTraceImage(); + ~ON_3dmViewTraceImage(); + bool operator==( const ON_3dmViewTraceImage& ) const; + bool operator!=( const ON_3dmViewTraceImage& ) const; + + void Default(); + + bool Write( ON_BinaryArchive& ) const; + bool Read( ON_BinaryArchive& ); + + // view window relative position and state in parent frame + ON_Plane m_plane; + double m_width; + double m_height; + + ON_FileReference m_image_file_reference; + + bool m_bGrayScale; // true if image should be black and white + bool m_bHidden; // true if image is currently hidden from view + bool m_bFiltered; // true if image should be filtered (bilinear) before displayed. +}; + + +////////////////////////////////////////////////////////////////////////////////////////// +// +// ON_3dmViewTraceImage +// +class ON_CLASS ON_3dmWallpaperImage +{ +public: + ON_3dmWallpaperImage(); + ~ON_3dmWallpaperImage(); + bool operator==( const ON_3dmWallpaperImage& ) const; + bool operator!=( const ON_3dmWallpaperImage& ) const; + + void Default(); + + bool Write( ON_BinaryArchive& ) const; + bool Read( ON_BinaryArchive& ); + + ON_FileReference m_image_file_reference; + + bool m_bGrayScale; // true if image should be black and white + bool m_bHidden; // true if image is currently hidden from view +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// +// ON_3dmView +// + +class ON_CLASS ON_3dmPageSettings +{ +public: + ON_3dmPageSettings(); + ~ON_3dmPageSettings(); + + bool IsValid( ON_TextLog* text_log = 0 ) const; + + void Default(); + + int m_page_number; + + // Overall size of the page in millimeters + double m_width_mm; + double m_height_mm; + + // Page margins in millimeters + double m_left_margin_mm; + double m_right_margin_mm; + double m_top_margin_mm; + double m_bottom_margin_mm; + + ON_wString m_printer_name; + + bool Write(ON_BinaryArchive& archive) const; + bool Read(ON_BinaryArchive& archive); +}; + +class ON_CLASS ON_StandardDisplayModeId +{ +public: + static const ON_UUID Wireframe; // {1311ADCB-D89E-4051-A3F0-F64441FB8EC6} + static const ON_UUID Shaded; // {8BC8DEBE-C83B-4c47-B13C-9DB074510CAC} + static const ON_UUID Rendered; // {CAE60BAE-2D51-4299-ABF7-A339FCA86F3B} + static const ON_UUID Ghosted; // {FF608B97-81D3-4186-831C-41F7DC140881} + static const ON_UUID XrayShade; // {B5C19D5D-0AEC-4ff7-A10E-E052E660263A} + static const ON_UUID RenderedShadows; // {A5545314-9D87-428d-95AE-91052EEAD0FA} + static const ON_UUID Technical; // {63612C72-778F-4afd-B81B-17426FDFE8A6} + static const ON_UUID Artistic; // {B46AB226-05A0-4568-B454-4B1AB721C675} + static const ON_UUID Pen; // {F4616FA5-A831-4620-A97E-9B807D5EC376} + static const ON_UUID AmbientOcclusion; // {C32B72C3-41BD-4ADC-82A8-B7AEF4456A37} + static const ON_UUID Raytraced; // {69E0C7A5-1C6A-46C8-B98B-8779686CD181} + + /* + Parameters: + id - [in] + Returns: + True if id is one of the standard display modes listed above. + */ + static bool IsStandardDisplayModeId( + ON_UUID id + ); + + /* + Parameters: + id - [in] + Returns: + The legacy V3 display mode enum that is the closest match to + the display mode id. + */ + static ON::v3_display_mode ToV3DisplayMode( + ON_UUID id + ); + + /* + Parameters: + dm - [in] + v3 display mode enum value + Returns: + display mode id that corresponds to the enum value. + */ + static ON_UUID FromV3DisplayMode( + ON::v3_display_mode dm + ); + + +private: + // prohibit instantiation + ON_StandardDisplayModeId(); // no implementation + ~ON_StandardDisplayModeId(); // no implementation +}; + +enum class ON_FocalBlurModes : unsigned int +{ + None, // No focal blur. + Automatic, // Autofocus on selected objects. + Manual, // Fully manual focus. +}; + +class ON_CLASS ON_3dmView +{ +public: + ON_3dmView(); + ~ON_3dmView(); + + // The C++ default copy constructor and operator= work fine. + // Do not provide customized versions. + // NO // ON_3dmView(const ON_3dmView&); + // NO // ON_3dmView& operator=(const ON_3dmView&); + + void Default(); + + bool Write( ON_BinaryArchive& ) const; + bool Read( ON_BinaryArchive& ); + + void Dump( ON_TextLog& text_log ) const; + + bool IsValid( ON_TextLog* text_log = 0 ) const; + + // view projection information + ON_Viewport m_vp; + + // clipping planes + // Prior to Dec 14, 2010 m_clipping_planes was not saved with the view. + // After Dec 14, 2010 m_clipping_planes is saved. + ON_SimpleArray m_clipping_planes; + + // If true, the the camera location, camera direction, + // and lens angle should not be changed. + // It is ok to adjust clipping planes. + bool m_bLockedProjection; + + /////////////////////////////////////////////////////////////////////// + // + // target point + // + + /* + Returns: + Target point. This point is saved on m_vp.m_target_point. + The default constructor sets the target point to + ON_3dPoint::UnsetPoint. You must explicitly set the target + point if you want to use it. + Remarks: + The target point is stored on m_vp.m_target_point. The + value ON_3dmView.m_target is obsolete. This function always + returns the value of m_vp.m_target_point. + + */ + ON_3dPoint TargetPoint() const; + + /* + Description: + Sets the viewport target point. + Parameters: + target_point - [in] + When in doubt, the point m_vp.FrustumCenterPoint(ON_UNSET_VALUE) + is a good choice. + Remarks: + This point is saved on m_vp.m_target_point. + */ + bool SetTargetPoint(ON_3dPoint target_point); + + // + /////////////////////////////////////////////////////////////////////// + + ON_wString m_name; // name on window + + // The value of m_display_mode_id can be one of the "standard" ids + // from ON_StandardDisplayModeId, nil, or a custom display mode + // settings on a particular computer. If you encounter a nil id + // or any other id that is not one of the "standard" display mode + // ids, then your application should use a default display mode, + // typically either wireframe or shaded, that is appropriate for + // general model viewing. The function ON::RhinoV3DisplayMode(id) + // will convert a display mode id into a legacy Rhino V3 display + // mode enum value. + ON_UUID m_display_mode_id; + + // position of view in parent window + // (relative display device coordinates) + ON_3dmViewPosition m_position; + + ON::view_type m_view_type; // model, page, or nested + + // If m_view_type == ON::page_view_type, then the m_page_settings + // records the page size. Otherwise, m_page_settings should + // be ignored. + ON_3dmPageSettings m_page_settings; + + /////////////////////////////////////////////////////////////////////// + // + // Named view information + // + // If this view was created from a named view, then m_named_view_id + // identifies the named view. + // + // The named views are ON_3dmView classes saved in ON_3dmSettings.m_named_views[]. + // A named view's id is the value returned by ON_3dmView.m_vp.ViewportId() + // A named view's name is the value returned by ON_3dmView.m_name + // + // If this view is a named view, then m_named_view_id should be equal to + // m_vp.m_viewport_id. + // + // If this view is not a named view and not created from a named view, + // then m_named_view_id is equal to ON_nil_uuid. + ON_UUID m_named_view_id; + + /////////////////////////////////////////////////////////////////////// + // + // Construction plane + // + ON_3dmConstructionPlane m_cplane; + bool m_bShowConstructionGrid; + bool m_bShowConstructionAxes; + bool m_bShowConstructionZAxis; + + // world axes icon + bool m_bShowWorldAxes; + + // tracing image + ON_3dmViewTraceImage m_trace_image; + + // wallpaper image + ON_3dmWallpaperImage m_wallpaper_image; + +public: + + double FocalBlurDistance(void) const; + void SetFocalBlurDistance(double d); + + double FocalBlurAperture(void) const; + void SetFocalBlurAperture(double d); + + double FocalBlurJitter(void) const; + void SetFocalBlurJitter(double d); + + unsigned int FocalBlurSampleCount(void) const; + void SetFocalBlurSampleCount(unsigned int count); + + ON_FocalBlurModes FocalBlurMode(void) const; + void SetFocalBlurMode(ON_FocalBlurModes m); + + ON_2iSize RenderingSize() const; + void SetRenderingSize(const ON_2iSize& size); + + //Focal blur settings - per view for renderers. +private: + double m_dFocalBlurDistance = 100.0; + double m_dFocalBlurAperture = 64.0; + double m_dFocalBlurJitter = 0.1; + unsigned int m_uFocalBlurSampleCount = 10; + ON_FocalBlurModes m_FocalBlurMode = ON_FocalBlurModes::None; + ON_2iSize m_sizeRendering = ON_2iSize(640, 480); + +private: + ON__INT_PTR reserved = 0; +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; +#endif + +////////////////////////////////////////////////////////////////////////////////////////// +// +// ON_3dmRenderSettings +// + +class ON_CLASS ON_3dmRenderSettings : public ON_Object +{ + ON_OBJECT_DECLARE(ON_3dmRenderSettings); + +public: + ON_3dmRenderSettings() = default; + ~ON_3dmRenderSettings() = default; + ON_3dmRenderSettings(const ON_3dmRenderSettings&) = default; + ON_3dmRenderSettings& operator=(const ON_3dmRenderSettings&) = default; + + static const ON_3dmRenderSettings Default; + + bool Write( ON_BinaryArchive& ) const override; + bool Read( ON_BinaryArchive& ) override; + void Dump( ON_TextLog& text_log ) const override; + +private: + static bool UseV5ReadWrite(const ON_BinaryArchive&); + bool WriteV5( ON_BinaryArchive& ) const; + bool ReadV5( ON_BinaryArchive& ); + +public: + //New for V6, rendering source (render directly from a NamedView or Snapshot) + //https://mcneel.myjetbrains.com/youtrack/issue/RH-39593 + enum class RenderingSources : unsigned int + { + ActiveViewport, // Get the rendering view from the currently active viewport (as in all previous versions of Rhino) + SpecificViewport, // Get the rendering view from the named viewport (see NamedViewport below) + NamedView, // Get the rendering view from a specific named view (see NamedView below) + SnapShot, // Before rendering, restore the Snapshot specified in Snapshot below, then render. + }; + + RenderingSources RenderingSource(void) const; + void SetRenderingSource(RenderingSources); + + ON_wString SpecificViewport(void) const; + void SetSpecificViewport(const ON_wString&); + + ON_wString NamedView(void) const; + void SetNamedView(const ON_wString&); + + ON_wString Snapshot(void) const; + void SetSnapshot(const ON_wString&); + +private: + RenderingSources m_rendering_source = RenderingSources::ActiveViewport; + ON_wString m_specific_viewport; + ON_wString m_named_view; + ON_wString m_snapshot; + +public: + bool ScaleBackgroundToFit() const; + void SetScaleBackgroundToFit( bool bScaleBackgroundToFit ); + +private: + unsigned short m_reserved1 = 0; + +public: + ////////////////////////////////////////////////////////////// + // + // Force viewport aspect ratio: + // If m_bCustomImageSize is true and m_bForceViewportAspectRatio is true + // then the image height should be calculated by multiplying the m_image_width + // by the viewport aspect ratio. Note that this might be affected by m_rendering_source + // In this case, m_image_height should not be used. + // + bool m_bForceViewportAspectRatio = false; + ////////////////////////////////////////////////////////////// + // + // Custom image size: + // If m_bCustomImageSize is true, then the image pixel size + // is m_image_width X m_image_height pixels. + // If m_bCustomImageSize is false, then the image pixel size + // is the size of the viewport being rendered. + // + bool m_bCustomImageSize = false; + int m_image_width = 800; // image width in pixels + int m_image_height = 600; // image height in pixels + +private: + unsigned int m_reserved3 = 0; +public: + + //////// + // Number of dots/inch (dots=pixels) to use when printing and + // saving bitmaps. The default is 72.0 dots/inch. + double m_image_dpi = 72.0; + + ////////// + // unit system to use when converting image pixel size and dpi + // information into a print size. Default = inches + ON::LengthUnitSystem m_image_us = ON::LengthUnitSystem::Inches; + + ON_Color m_ambient_light = ON_Color::Black; + + int m_background_style = 0; // 0 = solid color, 1 = "wallpaper" image, 2 = Gradient, 3 = Environment + + // m_background_color was changed from ON_Color::Gray160 to ON_Color::White for "white studio" look. + // m_background_color = Top color of gradient... + ON_Color m_background_color = ON_Color::White; + ON_Color m_background_bottom_color = ON_Color::Gray160; + + + ON_wString m_background_bitmap_filename; + // If m_background_bitmap_filename is not empty, the file cannot be found, + // and m_embedded_file_id identifes an embedded image file in the model, + // then that file will be used as the background bitmap. + ON_UUID m_embedded_image_file_id = ON_nil_uuid; + + bool m_bUseHiddenLights = false; + + bool m_bDepthCue = false; + bool m_bFlatShade = false; + + bool m_bRenderBackfaces = true; + bool m_bRenderPoints = false; + bool m_bRenderCurves = false; + bool m_bRenderIsoparams = false; + bool m_bRenderMeshEdges = false; + bool m_bRenderAnnotation = false; + bool m_bScaleBackgroundToFit = false; + bool m_bTransparentBackground = false; + +private: + unsigned char m_reserved4 = 0; + unsigned int m_reserved5 = 0; +public: + + int m_antialias_style = 1; // 0 = none, 1 = normal, 2 = medium, 3 = best + + int m_shadowmap_style = 1; // 0 = none, 1 = normal, 2 = best + int m_shadowmap_width= 1000; + int m_shadowmap_height = 1000; + double m_shadowmap_offset = 0.75; + + + // Flags that are used to determine which render settings a render + // plugin uses, and which ones the display pipeline should use. + // Note: Render plugins set these, and they don't need to persist + // in the document...Also, when set, they turn OFF their + // corresponding setting in the Display Attributes Manager's + // UI pages for "Rendered" mode. + bool m_bUsesAmbientAttr = true; + bool m_bUsesBackgroundAttr = true; + bool m_bUsesBackfaceAttr = false; + bool m_bUsesPointsAttr = false; + bool m_bUsesCurvesAttr = true; + bool m_bUsesIsoparmsAttr = true; + bool m_bUsesMeshEdgesAttr = false; + bool m_bUsesAnnotationAttr = true; + bool m_bUsesHiddenLightsAttr = true; + +private: + unsigned char m_reserved6 = 0; + unsigned short m_reserved7 = 0; + unsigned short m_reserved8 = 0; + +private: + ON__INT_PTR m_reserved9 = 0; +}; + + +////////////////////////////////////////////////////////////////////////////////////////// +// +// ON_EarthAnchorPoint +// + +class ON_CLASS ON_EarthAnchorPoint +{ +public: + ON_EarthAnchorPoint() = default; + ~ON_EarthAnchorPoint() = default; + ON_EarthAnchorPoint(const ON_EarthAnchorPoint&) = default; + ON_EarthAnchorPoint& operator=(const ON_EarthAnchorPoint&) = default; + + // Latitude, longitude, and elevation are ON_UNSET_VALUE. + static const ON_EarthAnchorPoint Unset; + + // Latitude, longitude, and elevation are the Seattle Space Needle. + static const ON_EarthAnchorPoint SeattleSpaceNeedle; + + static + int Compare( + const ON_EarthAnchorPoint*, + const ON_EarthAnchorPoint* + ); + + static + int CompareEarthLocation( + const ON_EarthAnchorPoint*, + const ON_EarthAnchorPoint* + ); + + static + int CompareModelDirection( + const ON_EarthAnchorPoint*, + const ON_EarthAnchorPoint* + ); + + static + int CompareIdentification( + const ON_EarthAnchorPoint*, + const ON_EarthAnchorPoint* + ); + + bool Read( ON_BinaryArchive& ); + bool Write( ON_BinaryArchive& ) const; + + /* + Returns: + True if the latitude, longitude, and elevation are set. + */ + bool EarthLocationIsSet() const; + + /* + Returns: + True if model basepoint, north and east are set. + */ + bool ModelLocationIsSet() const; + + /* + Parameters: + elevation_unit_system - [in] + elevation - [in] + */ + void SetEarthLocation( + ON::EarthCoordinateSystem earth_coordinate_system, + const class ON_UnitSystem& elevation_unit_system, + double latitude_degrees, + double longitude_degrees, + double elevation + ); + + void SetEarthLocation( + ON::EarthCoordinateSystem earth_coordinate_system, + ON::LengthUnitSystem elevation_unit_system, + double latitude_degrees, + double longitude_degrees, + double elevation + ); + + void SetLatitudeAndLongitude( + double latitude_degrees, + double longitude_degrees + ); + + /* + Returns: + A 3d point with coordinates (latitude in degrees, longitude in degrees, elevation in meters). + Remarks: + Some coordinates may be ON_UNSET_VALUE. + */ + ON_3dPoint EarthLocation() const; + + /* + Parameters: + unset_location - [in] + Location to return if EarlocationIsSet() is false. + Returns: + A 3d point with coordinates (latitude, longitude, elevation). + */ + ON_3dPoint EarthLocation( + ON_3dPoint unset_location + ) const; + + /* + Returns: + Earth location latitude in degrees. Can be ON_UNSET_VALUE + */ + double Latitude() const; + + /* + Parameters: + unset_latitude - [in] + Value to return if the Earth location latitude is not set. + Returns: + Earth location latitude in degrees. + */ + double Latitude( + double unset_latitude + ) const; + + void SetLatitude( + double latitude_degrees + ); + + /* + Returns: + Earth location longitude in degrees. Can be ON_UNSET_VALUE + */ + double Longitude() const; + + /* + Parameters: + unset_longitude - [in] + Value to return if the Earth location latitude is not set. + Returns: + Earth location longitude in degrees. + */ + double Longitude( + double unset_longitude + ) const; + + void SetLongitude( + double longitude_degrees + ); + + /* + System used to define latiude, longitude and elevation. + */ + ON::EarthCoordinateSystem EarthCoordinateSystem() const; + + /* + System used to define Earth latiude, longitude, and elevation coordinates. + */ + void SetEarthCoordinateSystem( + ON::EarthCoordinateSystem earth_coordinate_system + ); + + double ElevationInMeters() const; + + + /* + Parameters: + elevation_unit_system - [in] + length unit system for returned value. + Returns: + Earth location elevation in in elevation_unit_system. + The value is with + Can be ON_UNSET_VALUE + */ + double Elevation( + const class ON_UnitSystem& elevation_unit_system + ) const; + + /* + Parameters: + elevation_unit_system - [in] + length unit system for returned value. + Returns: + Earth location elevation in degrees. Can be ON_UNSET_VALUE + */ + double Elevation( + ON::LengthUnitSystem elevation_unit_system + ) const; + + /* + Parameters: + elevation_unit_system - [in] + length unit system for returned value. + unset_elevation - [in] + Value to return if the Earth location elevation is not set. + */ + double Elevation( + const class ON_UnitSystem& elevation_unit_system, + double unset_elevation + ) const; + + /* + Parameters: + elevation_unit_system - [in] + length unit system for returned value. + unset_elevation - [in] + Value to return if the Earth location elevation is not set. + */ + double Elevation( + ON::LengthUnitSystem elevation_unit_system, + double unset_elevation + ) const; + + /* + Parameters: + elevation_unit_system - [in] + elevation - [in] + */ + void SetElevation( + const ON_UnitSystem& elevation_unit_system, + double elevation + ); + + void SetElevation( + ON::LengthUnitSystem elevation_unit_system, + double elevation + ); + + const ON_3dPoint& ModelPoint() const; + const ON_3dVector& ModelNorth() const; + const ON_3dVector& ModelEast() const; + + void SetModelPoint( + ON_3dPoint model_point + ); + + void SetModelNorth( + ON_3dVector model_north + ); + + void SetModelEast( + ON_3dVector model_east + ); + + void SetModelLocation( + ON_3dPoint model_point, + ON_3dVector model_north, + ON_3dVector model_east + ); + + /* + Description: + Find the Keyhole Markup Language (KML) orientation angles (in radians) of a rotation + transformation that maps model (east,north,up) to ((1,0,0),(0,1,0),(0,0,1)). + KML Earth Z axis = up, KML Earth X axis = east, KML Earth Y axis = north. + NOTE WELL: In KML, postive rotations are CLOCKWISE looking down + specied axis vector towards the origin. This is rotation direction + is opposite the conventional "right hand rule." + Parameters: + heading_radians - [out] + angle (in radians) of rotation around KML Earth Z axis (Earth up). + NOTE WELL: In KML, postive rotations are CLOCKWISE looking down + specied axis vector towards the origin. This is rotation direction + is opposite the conventional "right hand rule." + tilt_radians - [out] + angle (in radians) of rotation around KML Earth X axis (Earth east). + NOTE WELL: In KML, postive rotations are CLOCKWISE looking down + specied axis vector towards the origin. This is rotation direction + is opposite the conventional "right hand rule." + roll_radians - [out] + angle (in radians) of rotation around KML Earth Y axis (Earth north). + NOTE WELL: In KML, postive rotations are CLOCKWISE looking down + specied axis vector towards the origin. This is rotation direction + is opposite the conventional "right hand rule." + Returns: + True if the model location is set (this->ModelLocationIsSet() is true) + and the KML orientation angles are returned. + Otherwise false is returned and all of the angle values are ON_DLB_QNAN. + See Also: + https://developers.google.com/kml/documentation/kmlreference#orientation + */ + bool GetKMLOrientationAnglesRadians( + double& heading_radians, + double& tilt_radians, + double& roll_radians + ) const; + + /* + If the model location is set (this->ModelLocationIsSet() is true), then the + Keyhole Markup Language orientation heading angle in radians is returned. + Otherwise ON_DBL_QNAN is returned. + See Also: + https://developers.google.com/kml/documentation/kmlreference#orientation + */ + const double KMLOrientationHeadingAngleRadians() const; + + /* + Returns: + If the model location is set (this->ModelLocationIsSet() is true), then the + Keyhole Markup Language orientation tilt angle in radians is returned. + Otherwise ON_DBL_QNAN is returned. + See Also: + https://developers.google.com/kml/documentation/kmlreference#orientation + */ + const double KMLOrientationTiltAngleRadians() const; + + /* + Returns: + If the model location is set (this->ModelLocationIsSet() is true), then the + Keyhole Markup Language orientation roll angle in radians is returned. + Otherwise ON_DBL_QNAN is returned. + See Also: + https://developers.google.com/kml/documentation/kmlreference#orientation + */ + const double KMLOrientationRollAngleRadians() const; + + /* + Description: + Find the Keyhole Markup Language (KML) orientation angles (in degrees) of a rotation + transformation that maps model (east,north,up) to ((1,0,0),(0,1,0),(0,0,1)). + KML Earth Z axis = up, KML Earth X axis = east, KML Earth Y axis = north. + NOTE WELL: In KML, postive rotations are CLOCKWISE looking down + specied axis vector towards the origin. This is rotation direction + is opposite the conventional "right hand rule." + Parameters: + heading_degrees - [out] + angle (in degrees) of rotation around KML Earth Z axis (Earth up). + NOTE WELL: In KML, postive rotations are CLOCKWISE looking down + specied axis vector towards the origin. This is rotation direction + is opposite the conventional "right hand rule." + tilt_degrees - [out] + angle (in degrees) of rotation around KML Earth X axis (Earth east). + NOTE WELL: In KML, postive rotations are CLOCKWISE looking down + specied axis vector towards the origin. This is rotation direction + is opposite the conventional "right hand rule." + roll_degrees - [out] + angle (in degrees) of rotation around KML Earth Y axis (Earth north). + NOTE WELL: In KML, postive rotations are CLOCKWISE looking down + specied axis vector towards the origin. This is rotation direction + is opposite the conventional "right hand rule." + Returns: + True if the model location is set (this->ModelLocationIsSet() is true) + and the KML orientation angles are returned. + Otherwise false is returned and all of the angle values are ON_DLB_QNAN. + See Also: + https://developers.google.com/kml/documentation/kmlreference#orientation + */ + bool GetKMLOrientationAnglesDegrees( + double& heading_degrees, + double& tilt_degrees, + double& roll_degrees + ) const; + + /* + Returns: + If the model location is set (this->ModelLocationIsSet() is true), then the + Keyhole Markup Language orientation heading angle in degrees is returned. + Otherwise ON_DBL_QNAN is returned. + See Also: + https://developers.google.com/kml/documentation/kmlreference#orientation + */ + const double KMLOrientationHeadingAngleDegrees() const; + + /* + Returns: + If the model location is set (this->ModelLocationIsSet() is true), then the + Keyhole Markup Language orientation tilt angle in degrees is returned. + Otherwise ON_DBL_QNAN is returned. + See Also: + https://developers.google.com/kml/documentation/kmlreference#orientation + */ + const double KMLOrientationTiltAngleDegrees() const; + + /* + If the model location is set (this->ModelLocationIsSet() is true), then the + Keyhole Markup Language orientation roll angle in degrees is returned. + Otherwise ON_DBL_QNAN is returned. + See Also: + https://developers.google.com/kml/documentation/kmlreference#orientation + */ + const double KMLOrientationRollAngleDegrees() const; + +private: + // Point on the Earth + // Latitude (degrees): +90 = north pole, 0 = equator, -90 = south pole + // Longitude (degrees): 0 = prime meridian (Greenwich meridian) + // Elevation (meters): + double m_earth_latitude = ON_UNSET_VALUE; // in decimal degrees + double m_earth_longitude = ON_UNSET_VALUE; // in decimal degrees + double m_earth_elevation_meters = 0.0; + + ON::EarthCoordinateSystem m_earth_coordinate_system = ON::EarthCoordinateSystem::Unset; + +private: + unsigned char m_reserved1 = 0; + unsigned char m_reserved2 = 0; + unsigned char m_reserved3 = 0; + ON__UINT32 m_reserved4 = 0; + +private: + // Corresponding model point in model coordinates. + ON_3dPoint m_model_point = ON_3dPoint::Origin; // in model coordinates + + // Earth directions in model coordinates + ON_3dVector m_model_north = ON_3dVector::YAxis; // in model coordinates + ON_3dVector m_model_east = ON_3dVector::XAxis; // in model coordinates + +public: + // Identification information about this location + ON_UUID m_id = ON_nil_uuid; // unique id for this anchor point + ON_wString m_name; + ON_wString m_description; + ON_wString m_url; + ON_wString m_url_tag; // UI link text for m_url + + /* + Parameters: + model_compass - [out] + A plane in model coordinates whose xaxis points East, + yaxis points North and zaxis points up. The origin + is set to m_model_basepoint. + */ + bool GetModelCompass( + ON_Plane& model_compass + ) const; + + /* + Description: + Get a transformation from model coordinates to earth coordinates. + This transformation assumes the model is small enough that + the curvature of the earth can be ignored. + Parameters: + model_unit_system - [in] + model_to_earth - [out] + Transformation from model coordinates to earth locations + (degrees latitude,degrees longitude,elevation in meters) + Remarks: + If M is a point in model coordinates and E = model_to_earth*M, + then + E.x = latitude in decimal degrees + E.y = longitude in decimal degrees + E.z = elevation in meters above mean sea level + + Because the earth is not flat, there is a small amount of error + when using a linear transformation to calculate oblate spherical + coordinates. This error is small. If the distance from P to M + is d meters, then the approximation error is + + latitude error <= + longitude error <= + elevation error <= 6379000*((1 + (d/6356000)^2)-1) meters + + In particular, if every point in the model is within 1000 meters of + the m_model_basepoint, then the maximum approximation errors are + + latitude error <= + longitude error <= + elevation error <= 8 centimeters + */ + bool GetModelToEarthXform( + const ON_UnitSystem& model_unit_system, + ON_Xform& model_to_earth + ) const; + +private: + const ON_Xform Internal_KMLOrientationXform() const; +}; + + + +class ON_CLASS ON_3dmIOSettings +{ +public: + ON_3dmIOSettings() = default; + ~ON_3dmIOSettings() = default; + ON_3dmIOSettings(const ON_3dmIOSettings&) = default; + ON_3dmIOSettings& operator=(const ON_3dmIOSettings&) = default; + + static const ON_3dmIOSettings Default; + + bool Read(ON_BinaryArchive&); + bool Write(ON_BinaryArchive&) const; + + // bitmaps associated with rendering materials + bool m_bSaveTextureBitmapsInFile = false; + + // As of 7 February 2012, the m_idef_link_update setting + // controls if, when and how linked and linked_and_embedded + // instance defintions are updated when the source archive + // that was used to create the idef has changed. + int m_idef_link_update = 1; + // 1 = prompt - ask the user if the idef should be updated. + // 2 = always update - no prompting + // 3 = never update - no prompting + // Any value not equal to 1,2 or 3 shall be treated as 1. +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// +// ON_3dmSettings +// + +class ON_CLASS ON_3dmSettings +{ +public: + ON_3dmSettings() = default; + ~ON_3dmSettings() = default; + + ON_3dmSettings(const ON_3dmSettings&) = default; + ON_3dmSettings& operator=(const ON_3dmSettings&) = default; + + static const ON_3dmSettings Default; + + bool Read(ON_BinaryArchive&); + bool Write(ON_BinaryArchive&) const; + + void Dump( ON_TextLog& ) const; + + // model URL (can be empty) + ON_wString m_model_URL = ON_wString::EmptyString; + + // Model basepoint is used when the file is read as + // an instance definition and is the point that is + // mapped to the origin in the instance definition. + ON_3dPoint m_model_basepoint = ON_3dPoint::Origin; + + // If set, this is the model's location on the earth. + // This information is used when the model is used + // with GIS information. + ON_EarthAnchorPoint m_earth_anchor_point = ON_EarthAnchorPoint::Unset; + + // Model space tolerances and unit system + ON_3dmUnitsAndTolerances m_ModelUnitsAndTolerances = ON_3dmUnitsAndTolerances::Millimeters; + + // Page space (printing/paper) tolerances and unit system + ON_3dmUnitsAndTolerances m_PageUnitsAndTolerances = ON_3dmUnitsAndTolerances::Millimeters; + + // settings used for automatically created rendering meshes + ON_MeshParameters m_RenderMeshSettings = ON_MeshParameters::DefaultMesh; + + // saved custom settings + ON_MeshParameters m_CustomRenderMeshSettings = ON_MeshParameters::DefaultMesh; + + /* + Returns: + ON_MeshParameters::render_mesh_fast + m_RenderMeshSettings and ON_MeshParameters::FastRenderMesh have + the same mesh geometry parameter settings. + ON_MeshParameters::render_mesh_quality + m_RenderMeshSettings and ON_MeshParameters::QualityRenderMesh have + the same mesh geometry parameter settings. + ON_MeshParameters::render_mesh_custom + m_RenderMeshSettings and m_CustomRenderMeshSettings have + the same mesh geometry parameter settings. + no_match_found_result + otherwise + */ + ON_MeshParameters::MESH_STYLE RenderMeshStyle( + ON_MeshParameters::MESH_STYLE no_match_found_result + ) const; + + // settings used for automatically created analysis meshes + ON_MeshParameters m_AnalysisMeshSettings = ON_MeshParameters::DefaultAnalysisMesh; + + // settings used when annotation objects are created + ON_3dmAnnotationSettings m_AnnotationSettings; + + ON_ClassArray m_named_cplanes; + ON_ClassArray m_named_views; + ON_ClassArray m_views; // current viewports + ON_UUID m_active_view_id = ON_nil_uuid; // id of "active" viewport + + // These fields determine what layer, material, color, line style, and + // wire density are used for new objects. + +public: + void SetCurrentLayerId( + ON_UUID layer_id + ); + void SetV5CurrentLayerIndex( + int V5_current_layer_index + ); + int CurrentLayerIndex() const; + ON_UUID CurrentLayerId() const; +private: + // The index is for reading V5 and earlier files. + int m_V5_current_layer_index = ON_UNSET_INT_INDEX; + ON_UUID m_current_layer_id = ON_nil_uuid; + +public: + void SetCurrentMaterialId( + ON_UUID material_id + ); + int CurrentMaterialIndex() const; + ON_UUID CurrentMaterialId() const; +private: + // The index is for reading V5 and earlier files. + int m_V5_current_render_material_index = ON_UNSET_INT_INDEX; + ON_UUID m_current_render_material_id = ON_nil_uuid; + +public: + ON::object_material_source m_current_material_source = ON::material_from_layer; + + ON_Color m_current_color = ON_Color::Black; + ON::object_color_source m_current_color_source = ON::color_from_layer; + + ON_Color m_current_plot_color = ON_Color::UnsetColor; + ON::plot_color_source m_current_plot_color_source = ON::plot_color_from_layer; + +public: + void SetCurrentLinePatternId( + ON_UUID line_pattern_id + ); + int CurrentLinePatternIndex() const; + ON_UUID CurrentLinePatternId() const; +private: + // The index is for reading V5 and earlier files. + int m_V5_current_line_pattern_index = ON_UNSET_INT_INDEX; + ON_UUID m_current_line_pattern_id = ON_nil_uuid; + +public: + ON::object_linetype_source m_current_linetype_source = ON::linetype_from_layer; + +public: + void SetCurrentTextStyleId( + ON_UUID text_style_id + ); + int CurrentTextStyleIndex() const; + ON_UUID CurrentTextStyleId() const; +private: + // The index is for reading V5 and earlier files. + int m_V5_current_text_style_index = ON_UNSET_INT_INDEX; + ON_UUID m_current_text_style_id = ON_nil_uuid; + +public: + void SetCurrentDimensionStyleId( + ON_UUID dimension_style_id + ); + int CurrentDimensionStyleIndex() const; + ON_UUID CurrentDimensionStyleId() const; +private: + // The index is for reading V5 and earlier files. + int m_V5_current_dimension_style_index = ON_UNSET_INT_INDEX; + ON_UUID m_current_dimension_style_id = ON_nil_uuid; + +public: + void SetCurrentHatchPatternId( + ON_UUID hatch_pattern_id + ); + ON_UUID CurrentHatchPatternId() const; +private: + ON_UUID m_current_hatch_pattern_id = ON_nil_uuid; + +public: + // Surface wireframe density + // + // @untitled table + // 0 boundary + "knot" wires + // 1 boundary + "knot" wires + 1 interior wire if no interior "knots" + // N>=2 boundry + "knot" wires + (N-1) interior wires + int m_current_wire_density = 1; + + ON_3dmRenderSettings m_RenderSettings = ON_3dmRenderSettings::Default; + + // default settings for construction plane grids + ON_3dmConstructionPlaneGridDefaults m_GridDefaults = ON_3dmConstructionPlaneGridDefaults::Default; + + // World scale factor to apply to non-solid linetypes + // for model display. For plotting, the linetype settings + // are used without scaling. + double m_linetype_display_scale = 1.0; + + // Plugins that were loaded when the file was saved. + ON_ClassArray m_plugin_list; + + ON_3dmIOSettings m_IO_settings = ON_3dmIOSettings::Default; +private: + bool Read_v1(ON_BinaryArchive&); + bool Read_v2(ON_BinaryArchive&); + bool Write_v1(ON_BinaryArchive&) const; + bool Write_v2(ON_BinaryArchive&) const; +}; + + +////////////////////////////////////////////////////////////////////////////////////////// +// +// ON_3dmAnimationProperties +// + +class ON_CLASS ON_3dmAnimationProperties +{ +public: + ON_3dmAnimationProperties() = default; + ~ON_3dmAnimationProperties() = default; + ON_3dmAnimationProperties(const ON_3dmAnimationProperties&) = default; + ON_3dmAnimationProperties& operator=(const ON_3dmAnimationProperties&) = default; + + static const ON_3dmAnimationProperties Default; + + bool Read(ON_BinaryArchive&); + bool Write(ON_BinaryArchive&) const; + +public: + enum class CaptureTypes : int + { + path = 0, + turntable, + flythrough, + day_sun_study, + seasonal_sun_study, + none + }; + + CaptureTypes CaptureType(void) const; + void SetCaptureType(CaptureTypes t); + + ON_wString FileExtension(void) const; + void SetFileExtension(const ON_wString& s); + + ON_wString CaptureMethod(void) const; + void SetCaptureMethod(const ON_wString& s); + + ON_wString ViewportName(void) const; + void SetViewportName(const ON_wString& s); + + ON_wString HtmlFilename(void) const; + void SetHtmlFilename(const ON_wString& s); + + ON_UUID DisplayMode(void) const; + void SetDisplayMode(const ON_UUID& id); + + ON_3dPointArray& CameraPoints(void); + const ON_3dPointArray& CameraPoints(void) const; + + ON_3dPointArray& TargetPoints(void); + const ON_3dPointArray& TargetPoints(void) const; + + int FrameCount(void) const; + void SetFrameCount(int i); + + int CurrentFrame(void) const; + void SetCurrentFrame(int i); + + ON_UUID CameraPathId(void) const; + void SetCameraPathId(const ON_UUID& id); + + ON_UUID TargetPathId(void) const; + void SetTargetPathId(const ON_UUID& id); + + double Latitude(void) const; + void SetLatitude(double d); + + double Longitude(void) const; + void SetLongitude(double d); + + double NorthAngle(void) const; + void SetNorthAngle(double d); + + int StartDay(void) const; + void SetStartDay(int i); + + int StartMonth(void) const; + void SetStartMonth(int i); + + int StartYear(void) const; + void SetStartYear(int i); + + int EndDay(void) const; + void SetEndDay(int i); + + int EndMonth(void) const; + void SetEndMonth(int i); + + int EndYear(void) const; + void SetEndYear(int i); + + int StartHour(void) const; + void SetStartHour(int i); + + int StartMinutes(void) const; + void SetStartMinutes(int i); + + int StartSeconds(void) const; + void SetStartSeconds(int i); + + int EndHour(void) const; + void SetEndHour(int i); + + int EndMinutes(void) const; + void SetEndMinutes(int i); + + int EndSeconds(void) const; + void SetEndSeconds(int i); + + int DaysBetweenFrames(void) const; + void SetDaysBetweenFrames(int i); + + int MinutesBetweenFrames(void) const; + void SetMinutesBetweenFrames(int i); + + int LightIndex(void) const; + void SetLightIndex(int i); + + ON_wString FolderName(void) const; + void SetFolderName(const ON_wString& s); + + ON_ClassArray& Images(void); + const ON_ClassArray& Images(void) const; + + ON_ClassArray& Dates(void); + const ON_ClassArray& Dates(void) const; + + bool RenderFull(void) const; + void SetRenderFull(const bool b); + + bool RenderPreview(void) const; + void SetRenderPreview(const bool b); + +private: + CaptureTypes m_CaptureTypes = CaptureTypes::none; + ON_wString m_sFileExtension = L"jpg"; + ON_wString m_sCaptureMethod; + ON_wString m_sHtmlFilename; + ON_wString m_sViewport; + ON_UUID m_idDisplayMode = ON_nil_uuid; + ON_3dPointArray m_aCameraPoints; + ON_3dPointArray m_aTargetPoints; + int m_iFrameCount = 100; + int m_iCurrentFrame = 1; + ON_UUID m_idCameraPath = ON_nil_uuid; + ON_UUID m_idTargetPath = ON_nil_uuid; + double m_dLatitude = 51.2838; + double m_dLongitude = 0.0; + double m_dNorthAngle = 0.0; + int m_iStartDay = 1; + int m_iStartMonth = 6; + int m_iStartYear = 2010; + int m_iEndDay = 1; + int m_iEndMonth = 6; + int m_iEndYear = 2012; + int m_iStartHour = 6; + int m_iStartMinutes = 0; + int m_iStartSeconds = 0; + int m_iEndHour = 18; + int m_iEndMinutes = 0; + int m_iEndSeconds = 59; + int m_iDaysBetweenFrames = 30; + int m_iMinutesBetweenFrames = 30; + int m_iLightIndex = -1; + ON_wString m_sFolderName; + ON_ClassArray m_aImages; + ON_ClassArray m_aDates; + bool m_bRenderFull = false; + bool m_bRenderPreview = false; + +private: + unsigned char m_reserved1 = 0; + unsigned char m_reserved2 = 0; + ON__UINT32 m_reserved4 = 0; + ON__INT_PTR reserved = 0; +}; + +#endif diff --git a/opennurbs/Include/opennurbs_annotationbase.h b/opennurbs/Include/opennurbs_annotationbase.h new file mode 100644 index 0000000..120ade3 --- /dev/null +++ b/opennurbs/Include/opennurbs_annotationbase.h @@ -0,0 +1,1181 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_ANNOTATIONBASE_INC_) +#define OPENNURBS_ANNOTATIONBASE_INC_ + + + + +class ON_CLASS ON_Annotation : public ON_Geometry +{ + ON_OBJECT_DECLARE(ON_Annotation); + +protected: + ON_Annotation( ON::AnnotationType annotation_type ); + ON_Annotation( const ON_Annotation& src); + ~ON_Annotation(); + ON_Annotation& operator=(const ON_Annotation& src); + +public: + static ON_Annotation* CreateFromV2Annotation( + const class ON_OBSOLETE_V2_Annotation& V2_annotation, + const class ON_3dmAnnotationContext* annotation_context + ); + +public: + static ON_Annotation* CreateFromV5Annotation( + const class ON_OBSOLETE_V5_Annotation& V5_annotation, + const class ON_3dmAnnotationContext* annotation_context + ); + +protected: + void Internal_SetDimStyleFromV5Annotation( + const class ON_OBSOLETE_V5_Annotation& V5_annotation, + const class ON_3dmAnnotationContext* annotation_context + ); + + +private: + ON_Annotation() = delete; + +private: + void Internal_CopyFrom(const ON_Annotation& src); + void Internal_Destroy(); + +public: + /* + Returns: + An ON::AnnotationType value that indicates the + type of the annotation. + */ + ON::AnnotationType Type() const; + + ON::object_type ObjectType() const override; + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + virtual bool GetAnnotationBoundingBox( + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + double* boxmin, + double* boxmax, + bool bGrow = false + ) const = 0; + + /* + Parameters: + vp - [in] + nullptr or viewport where annotation object is displayed + dimstyle - [in] + &this->DimensionStyle(const ON_DimStyle& parent_dimstyle) + bApplyDimStyleDimScale - [in] + If true, dimsytyle->DimScale() is applied. + If vp is a page view, bApplyDimStyleDimScale is generally false. + If vp is a model view, bApplyDimStyleDimScale is generally + the value of a model property IsAnnotationScalingEnabled(). + from + bSingleStrokeFont - [in] + True if text uses a single font that is a single stroke font and returned contours + should be left open. + text_contours - [out] + */ + bool GetTextGlyphContours( + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + bool bApplyDimStyleDimScale, + bool bSingleStrokeFont, + ON_ClassArray< ON_ClassArray< ON_SimpleArray< ON_Curve* > > >& text_contours + ) const; + +protected: + + /* + Parameters: + vp - [in] + nullptr or viewport where annotation object is displayed + dimstyle - [in] + &this->DimensionStyle(const ON_DimStyle& parent_dimstyle) + */ + const ON_SHA1_Hash Internal_GetBBox_InputHash( + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + const ON_2dPoint& text_point, + unsigned int point_count, + const ON_2dPoint* points + ) const; + + /* + Parameters: + vp - [in] + nullptr or viewport where annotation object is displayed + dimstyle - [in] + &this->DimensionStyle(const ON_DimStyle& parent_dimstyle) + */ + bool Internal_GetBBox_TextGlyphBox( + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + ON_BoundingBox& text_glyph_box + ) const; + + /* + Returns: + True if a cached bounding box was found + and boxmin, boxmax are set. + */ + bool Internal_GetBBox_Begin( + const ON_SHA1_Hash& hash, + double* boxmin, + double* boxmax, + bool bGrow + ) const; + + /* + Returns: + True if a boxmin, boxmax is a valid bounding box + */ + bool Internal_GetBBox_End( + const ON_BoundingBox& bbox, + const ON_SHA1_Hash& hash, + double* boxmin, + double* boxmax, + bool bGrow + ) const; + +public: + virtual bool GetTextXform( + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + ON_Xform& text_xform_out + ) const = 0; + + bool GetTextXform( + const ON_Xform* model_xform, + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + ON_Xform& text_xform_out + ) const; + + void SetPlane(const ON_Plane& plane); + const ON_Plane& Plane() const; + + void SetHorizontalDirection(ON_2dVector); + const ON_2dVector HorizontalDirection() const; + + // Returns a 2d vector to use as annotation horizontal + // Use this function when you don't have a known horizontal direction + static ON_3dVector GetDefaultHorizontal(const ON_Plane& plane); + + + static void CalcTextFlip( + const ON_3dVector& text_xdir, const ON_3dVector& text_ydir, const ON_3dVector& text_zdir, + const ON_3dVector& view_xdir, const ON_3dVector& view_ydir, const ON_3dVector& view_zdir, + const ON_Xform* model_xform, + const double flip_tol, + bool& flip_x, + bool& flip_y); + + /* + Returns: + Rich text that can contain rich text formatting instructions. + */ + const ON_wString RichText() const; + + /* + Returns: + Text information with rich text formatting insturctions removed. + Fields are not evaluated. + */ + const ON_wString PlainText() const; + + /* + Returns: + Text information with rich text formatting insturctions removed. + The result string from evaluating fields is included + Field results may be cached from previous evaluation + */ + const ON_wString PlainTextWithFields() const; + + /* + Finds the positions and lengths of substrings in the string returned by PlainTextWithFields() + That string is the plain text (no rtf formatting) with field source unevaluated + Each 3dex in the array is + i: run index, + j: position in the string where text from run[i] starts, + k: length of text from run[i] + + Returns the same string that PlainTextWithFields() returns + */ + const ON_wString PlainTextWithFields(ON_SimpleArray* runmap) const; + + // Return the id of the main (parent) dimstyle used by this object. + // The style with this id should not be used directly if there is + // an override dimstyle present. + // Use this->DimensionStyle(parent_style) to get the effective + // dimstyle for this object. + ON_UUID DimensionStyleId() const; + + // Sets the id of the main (parent) dimstyle used by this annotation object + // Any override dimstyle on this object will be deleted when this is called, + // resetting any style overrides. + void SetDimensionStyleId(ON_UUID dimstyle_id); + + /* + Description: + Set the id of the main (parent) dimstyle used by this annotation object + and allow an expert user to control what happens to style override settings + in cases where id collisions occur and ids need to be changed. + Parameters: + bKeepOverrides - [in] + If you are not an expert oding something low level and complicated, then + call SetDimensionStyleId(dimstyle_id) or pass bKeepOverrides = false. + + If bKeepOverrides is true and dimstyle_id is not nil and this object has + valid overrides, those overrides are retained. In all other cases, any + existing overrides are deleted. + */ + void SetDimensionStyleIdForExperts( + ON_UUID dimstyle_id, + bool bKeepOverrides + ); + + /* + parameters: + dim_style - [in] + If dim_style.ParentId() is nil, then this function + calls SetDimensionStyleId(dim_style.Id()) and returns. + If dim_style.ParentId() is not nil, then this functions + calls SetDimensionStyleId(dim_style.ParentId()) and uses a copy + of dim_style as the override dimstyle. + */ + void SetDimensionStyleId( + const class ON_DimStyle& dim_style + ); + + // Get the proper dimension style, including overrides, to use for this + // annotation object. + // If there is an override in place, that dimstyle will be returned + // If there is no override, the parent style passed in will be returned + // If the content of the parent style has changed since the override was made, + // the override style will be updated with the non-overriden values from + // the parent before returning. + // If your annotation object has an override style and you call either of + // these functions with a dimstyle other than the correct parent style + // for this annotation, the override style will be removed. + const ON_DimStyle& DimensionStyle(const ON_DimStyle& parent_dimstyle) const; + const ON_DimStyle& DimensionStyle( + const ON_DimStyle& parent_dimstyle, + bool bForceOverrideUpdate + ) const; + + // Apply a dimstyle with overrides set to this annotation object. + // + // Use ON_Annotation::IsOverrideDimStyleCandidate() to determine if a non-nullptr + // override_style is a valid to be used to set overrides. + // + // The override dimstyle memory will be managed and deleted by the annotation object and + // must have been allocated using new. + // On return, if this function returns true, + // The dimstyle id of the annotation object must be set before this function is called. + // Calling SetOverrideDimensionStyle(nullptr) will remove all overrides for this object. + // override_dimstyle will be null. + // + // Returns: + // true if the override style was successfully set + // false if this->m_dimstyle_id is ON_nil_uuid causing failure + bool SetOverrideDimensionStyle(ON_DimStyle*& override_style) const; + + /* + Description: + Removes any override dimension style that is present. + */ + void ClearOverrideDimensionStyle(); + + /* + Description: + If this->IsOverrideDimStyleCandidate(override_style_candidate,bRequireSetOverrides) + is true, then a managed copy of override_style_candidate is set as an override. + Returns: + True if an override is set. + */ + bool SetOverrideDimensionStyle( + const ON_DimStyle* override_style_candidate, + bool bRequireSetOverrides + ); + + + /* + Description: + A valid override dimstyle candidate has all of the following properties. + override_style_candidate != nullptr. + IsDeleted() = false; + Id() = ON_nil_uuid; + Name() is empty. + Index() = ON_ModelComponent::Unset.Index() + bRequireSetOverrides is false or HasOverrides() returns true. + Parameters: + override_style_candidate -[in] + style candidate to evaluate. + bRequireSetOverrides - [in] + If bRequireSetOverrides is true, then override_style_candidate->HasOverrides() must be true for a valid candidate. + If bRequireSetOverrides is flase, then override_style_candidate->HasOverrides() can have any value. + Returns: + True if override_style could be successfully used as the parameter + to SetOverrideDimensionStyle. + */ + bool IsOverrideDimStyleCandidate( + const ON_DimStyle* override_style_candidate, + bool bRequireSetOverrides + ) const; + + + /* + Description: + Conceptually, calling this function applies ON_DimsStyle(scale) to the + dimstyle information used for this annotation. + + When an annotation object is in **layout/page space**, this is + the only way top get properties like TextHeight() to scale properly. + + When an annotation object is in **model space** and + **model space scaling is enabled**, + then calling this->SetDimScale(this->DimScale()*scale) + will work as well. + + Parameters: + parent_dimstyle - [in] + scale - [in] + */ + void ScaleOverrideDimstyle( + const ON_DimStyle* parent_dimstyle, + double scale + ); + +protected: + static bool Internal_IsOverrideDimStyleCandidate( + const ON_DimStyle* override_style_candidate, + ON_UUID parent_id, + bool bRequireSetOverrides, + bool bIssueErrorsAndWarnings + ); + + +public: + // Quickly check if this annotation object has style overrides applied. + bool HasDimensionStyleOverrides() const; + + const ON_TextContent* Text() const; + ON_TextContent* Text(); + void SetText(ON_TextContent*& text) const; + void ClearText() const; + + // return angle in radians between text plane and object plane + virtual double TextRotationRadians() const; + virtual void SetTextRotationRadians(double rotation); + + // return angle in degrees between text plane and object plane + virtual double TextRotationDegrees() const; + virtual void SetTextRotationDegrees(double rotation); + + //virtual bool Explode( + // const ON_DimStyle* dimstyle, + // ON_SimpleArray object_parts) const = 0; + + /* + Returns: + The value of ON_DimStyle.TextPositionPropertiesHash() from the dimension style used + to calculate the runtime text position (location, glyphs, and size). + */ + ON_SHA1_Hash DimStyleTextPositionPropertiesHash() const; + + /* + Returns: + True if this text position information used to create this text + is identical to the text position paramters on dimstyle. + */ + bool EqualTextPositionProperties( + const class ON_DimStyle* dimstyle + ) const; + + const wchar_t* RtfText() const; + + bool ReplaceTextString( + const wchar_t* RtfString, + const ON_DimStyle* dimstyle + ); + + bool RunReplaceString( + const ON_DimStyle* dimstyle, + const wchar_t* str, + int start_run_idx, + int start_run_pos, + int end_run_idx, + int end_run_pos); + + + // Deprecated - Use + // ON::TextVerticalAlignment ON_Annotation::TextVerticalAlignment(const ON_DimStyle* parent_style) const; + // void ON_Annotation::SetTextVerticalAlignment(const ON_DimStyle* parent_style, ON::TextVerticalAlignment style); + // ON::TextVerticalAlignment ON_Annotation::LeaderVerticalAlignment(const ON_DimStyle* parent_style) const; + // void ON_Annotation::SetLeaderVerticalAlignment(const ON_DimStyle* parent_style, ON::TextVerticalAlignment style); + void GetAlignment(ON::TextHorizontalAlignment& horz, ON::TextVerticalAlignment& vert) const; + void SetAlignment(ON::TextHorizontalAlignment horz, ON::TextVerticalAlignment vert); + + // FormattingRectangleWidth is a width set by text wrapping. It's in model units + double FormattingRectangleWidth() const; + void SetFormattingRectangleWidth(double width); + + // Get corners of the whole text object + // corners requires space for 4 points + bool GetText3dCorners(ON_3dPoint corners[4]) const; + + /* + Parameters: + ptr - [in] + pointer to test + Returns: + True if ptr is not nullptr and points to the override style mangaged by this + instance. + */ + bool IsOverrideStylePointer( + const ON_DimStyle* ptr + ) const; + + // These functions are being added to continue the V5 behavior of + // per-object text scaling. There is no user interface + // in V6 or V7 that shows this setting or that allows a user + // to change this setting. + // AllowTextScaling() = false means the effective dimstyle value + // of DimScale() (model space scale factor) is ignored (treated as if it were 1). + bool AllowTextScaling() const; + void SetAllowTextScaling(bool scale); + +protected: + ON::AnnotationType m_annotation_type = ON::AnnotationType::Unset; + bool m_allow_text_scaling = true; + unsigned char m_reserved2 = 0; + unsigned char m_reserved3 = 0; + unsigned int m_reserved4 = 0; + ON_UUID m_dimstyle_id = ON_DimStyle::Default.Id(); + ON_Plane m_plane = ON_Plane::World_xy; // plane origin used for alignment point + ON_2dVector m_horizontal_direction = ON_2dVector::XAxis; // direction used as horizontal to draw annotation, especially text + mutable ON_TextContent* m_text = nullptr; // Deleted by ~ON_Annotation() +private: + // Pointer to an override dimstyle when style properties are overridden for this annotation object + // If this pointer is null, use the style with id = m_dimstyle_id + // Copy and delete this dimstyle (not this pointer) with the object. + // This dimstyle should never be one held in a dimstyle table. It is owned by this object + mutable ON_DimStyle* m_override_dimstyle = nullptr; + mutable ON__UINT64 m_parent_dimstyle_content_version_number = 0; + void Internal_DeleteOverrideDimstyle() const; + + mutable ON_BoundingBoxCache m_bbox_cache; + +protected: + bool Internal_WriteAnnotation( + ON_BinaryArchive& archive + ) const; + + bool Internal_ReadAnnotation( + ON_BinaryArchive& archive + ); + +private: + ON_DimStyle* Internal_GetOverrideStyle(bool bCreateIfNull) const; + + /* + Description: + Gets the appropriate ON_DimStyle to query for a property value. + Parameters: + parent_style - [in] + parent style pased to the ON_Annotation query function + field_id - [in] + field being queried - this is used to select between using the override style or the parent style. + */ + + const ON_DimStyle& Internal_StyleForFieldQuery( + const ON_DimStyle* parent_style, + ON_DimStyle::field field_id + ) const; + +private: + static bool Internal_DimStyleDoubleChanged( + const double current_value, + double candidate_value + ); + +public: + void ClearFieldOverride(ON_DimStyle::field field); + + bool FieldIsOverridden(ON_DimStyle::field field) const; + + // These next several functions are to set overrides on individual annotation objects + + // Extension line extension + double ExtensionLineExtension(const ON_DimStyle* parent_style) const; + void SetExtensionLineExtension(const ON_DimStyle* parent_style, double d); + + // Extension line offset + double ExtensionLineOffset(const ON_DimStyle* parent_style) const; + void SetExtensionLineOffset(const ON_DimStyle* parent_style, double d); + + // Arrow size + double ArrowSize(const ON_DimStyle* parent_style) const; + void SetArrowSize(const ON_DimStyle* parent_style, double d); + + // Arrow size + double LeaderArrowSize(const ON_DimStyle* parent_style) const; + void SetLeaderArrowSize(const ON_DimStyle* parent_style, double d); + + // Centermark size + double CenterMarkSize(const ON_DimStyle* parent_style) const; + void SetCenterMarkSize(const ON_DimStyle* parent_style, double d); + + // Centermark style + ON_DimStyle::centermark_style CenterMarkStyle(const ON_DimStyle* parent_style) const; + void SetCenterMarkStyle(const ON_DimStyle* parent_style, ON_DimStyle::centermark_style style); + + // The location of text relative to the dimension line in linear, angular, and ordinate dimensions. + ON_DimStyle::TextLocation DimTextLocation(const ON_DimStyle* parent_style) const; + void SetDimTextLocation(const ON_DimStyle* parent_style, ON_DimStyle::TextLocation dim_text_location); + + // The location of text relative to the dimension line in radial dimensions. + ON_DimStyle::TextLocation DimRadialTextLocation(const ON_DimStyle* parent_style) const; + void SetDimRadialTextLocation(const ON_DimStyle* parent_style, ON_DimStyle::TextLocation dim_text_location); + + // Angle units - Degrees, Degrees-Minutes-Seconds, Radians + ON_DimStyle::angle_format AngleFormat(const ON_DimStyle* parent_style) const; + void SetAngleFormat(const ON_DimStyle* parent_style, ON_DimStyle::angle_format format); + + // Display resolution for distance measurements + int LengthResolution(const ON_DimStyle* parent_style) const; + void SetLengthResolution(const ON_DimStyle* parent_style, int r); + + // Display resolution for angle measurements + int AngleResolution(const ON_DimStyle* parent_style) const; + void SetAngleResolution(const ON_DimStyle* parent_style, int r); + + // Distance from dimension lines to text + double TextGap(const ON_DimStyle* parent_style) const; + void SetTextGap(const ON_DimStyle* parent_style, double gap); + + // Height of dimension text + double TextHeight(const ON_DimStyle* parent_style) const; + void SetTextHeight(const ON_DimStyle* parent_style, double height); + + // Scale factor for displayed distances + double LengthFactor(const ON_DimStyle* parent_style) const; + void SetLengthFactor(const ON_DimStyle* parent_style, double); + + // Additional measurement display toggle + bool Alternate(const ON_DimStyle* parent_style) const; + void SetAlternate(const ON_DimStyle* parent_style, bool); + + // Distance scale factor for alternate display + double AlternateLengthFactor(const ON_DimStyle* parent_style) const; + void SetAlternateLengthFactor(const ON_DimStyle* parent_style, double); + + // Display resolution for alternate length measurements + int AlternateLengthResolution(const ON_DimStyle* parent_style) const; + void SetAlternateLengthResolution(const ON_DimStyle* parent_style, int); + + // Dimension prefix text + const wchar_t* Prefix(const ON_DimStyle* parent_style) const; + void SetPrefix(const ON_DimStyle* parent_style, const wchar_t*); + + // Dimension suffix text + const wchar_t* Suffix(const ON_DimStyle* parent_style) const; + void SetSuffix(const ON_DimStyle* parent_style, const wchar_t*); + + // Dimension alternate prefix text + const wchar_t* AlternatePrefix(const ON_DimStyle* parent_style) const; + void SetAlternatePrefix(const ON_DimStyle* parent_style, const wchar_t*); + + // Dimension alternate suffix text + const wchar_t* AlternateSuffix(const ON_DimStyle* parent_style) const; + void SetAlternateSuffix(const ON_DimStyle* parent_style, const wchar_t*); + + // Suppress first dimension extension line + bool SuppressExtension1(const ON_DimStyle* parent_style) const; + void SetSuppressExtension1(const ON_DimStyle* parent_style, bool b); + + // Suppress second dimension extension line + bool SuppressExtension2(const ON_DimStyle* parent_style) const; + void SetSuppressExtension2(const ON_DimStyle* parent_style, bool b); + + // Extension of dimension line past extension lines + double DimExtension(const ON_DimStyle* parent_style) const; + void SetDimExtension(const ON_DimStyle* parent_style, const double e); + + ON_DimStyle::tolerance_format ToleranceFormat(const ON_DimStyle* parent_style) const; + void SetToleranceFormat(const ON_DimStyle* parent_style, ON_DimStyle::tolerance_format format); + + int ToleranceResolution(const ON_DimStyle* parent_style) const; + void SetToleranceResolution(const ON_DimStyle* parent_style, int resolution); + + double ToleranceUpperValue(const ON_DimStyle* parent_style) const; + void SetToleranceUpperValue(const ON_DimStyle* parent_style, double upper_value); + + double ToleranceLowerValue(const ON_DimStyle* parent_style) const; + void SetToleranceLowerValue(const ON_DimStyle* parent_style, double lower_value); + + double ToleranceHeightScale(const ON_DimStyle* parent_style) const; + void SetToleranceHeightScale(const ON_DimStyle* parent_style, double scale); + + double BaselineSpacing(const ON_DimStyle* parent_style) const; + void SetBaselineSpacing(const ON_DimStyle* parent_style, double spacing); + + // Determines whether or not to draw a Text Mask + bool DrawTextMask(const ON_DimStyle* parent_style) const; + void SetDrawTextMask(const ON_DimStyle* parent_style, bool bDraw); + + // Determines where to get the color to draw a Text Mask + ON_TextMask::MaskType MaskFillType(const ON_DimStyle* parent_style) const; + void SetMaskFillType(const ON_DimStyle* parent_style, ON_TextMask::MaskType source); + + // Determines whether to draw a frame around a text mask + ON_TextMask::MaskFrame MaskFrameType(const ON_DimStyle* parent_style) const; + void SetMaskFrameType(const ON_DimStyle* parent_style, ON_TextMask::MaskFrame source); + + ON_Color MaskColor(const ON_DimStyle* parent_style) const; // Only works right if MaskColorSource returns 1. + void SetMaskColor(const ON_DimStyle* parent_style, ON_Color color); // Does not return viewport background color + + // Offset for the border around text to the rectangle used to draw the mask + // This number is the offset on each side of the tight rectangle around the + // text characters to the mask rectangle. + double MaskBorder(const ON_DimStyle* parent_style) const; + void SetMaskBorder(const ON_DimStyle* parent_style, double offset); + + // The ON_TextMask class contains the property values for + // DrawTextMask() + // MaskColor() + // MaskFillType() + // MaskBorder() + // Use the + // DrawTextMask() + // MaskColor() + // MaskFillType() + // MaskBorder() + // functions to query individual text mask properties. + void SetTextMask(const ON_DimStyle* parent_style, const ON_TextMask& mask); + + double FixedExtensionLength(const ON_DimStyle* parent_style) const; + void SetFixedExtensionLength(const ON_DimStyle* parent_style, double l); + + bool FixedExtensionLengthOn(const ON_DimStyle* parent_style) const; + void SetFixedExtensionLengthOn(const ON_DimStyle* parent_style, bool on); + + int AlternateToleranceResolution(const ON_DimStyle* parent_style) const; + void SetAlternateToleranceResolution(const ON_DimStyle* parent_style, int r); + + bool SuppressArrow1(const ON_DimStyle* parent_style) const; + void SetSuppressArrow1(const ON_DimStyle* parent_style, bool s); + + bool SuppressArrow2(const ON_DimStyle* parent_style) const; + void SetSuppressArrow2(const ON_DimStyle* parent_style, bool s); + + int TextMoveLeader(const ON_DimStyle* parent_style) const; + void SetTextMoveLeader(const ON_DimStyle* parent_style, int m); + + int ArcLengthSymbol(const ON_DimStyle* parent_style) const; + void SetArcLengthSymbol(const ON_DimStyle* parent_style, int m); + + ON_DimStyle::stack_format StackFractionFormat(const ON_DimStyle* parent_style) const; + void SetStackFractionFormat(const ON_DimStyle* parent_style, ON_DimStyle::stack_format f); + + double StackHeightScale(const ON_DimStyle* parent_style) const; + void SetStackHeightScale(const ON_DimStyle* parent_style, double f); + + double RoundOff(const ON_DimStyle* parent_style) const; + void SetRoundOff(const ON_DimStyle* parent_style, double r); + + double AlternateRoundOff(const ON_DimStyle* parent_style) const; + void SetAlternateRoundOff(const ON_DimStyle* parent_style, double r); + + double AngleRoundOff(const ON_DimStyle* parent_style) const; + void SetAngleRoundOff(const ON_DimStyle* parent_style, double r); + + ON_DimStyle::suppress_zero ZeroSuppress(const ON_DimStyle* parent_style) const; + void SetZeroSuppress(const ON_DimStyle* parent_style, ON_DimStyle::suppress_zero s); + + ON_DimStyle::suppress_zero AlternateZeroSuppress(const ON_DimStyle* parent_style) const; + void SetAlternateZeroSuppress(const ON_DimStyle* parent_style, ON_DimStyle::suppress_zero s); + + // OBSOLETE - The ZeroSuppress() or AlternateZeroSuppress() property + // is used to format tolerance display. ToleranceZeroSuppress() is ignored. + ON_DimStyle::suppress_zero ToleranceZeroSuppress(const ON_DimStyle* parent_style) const; + + // OBSOLETE - The ZeroSuppress() or AlternateZeroSuppress() property + // is used to format tolerance display. ToleranceZeroSuppress() is ignored. + void SetToleranceZeroSuppress(const ON_DimStyle* parent_style, ON_DimStyle::suppress_zero s); + + ON_DimStyle::suppress_zero AngleZeroSuppress(const ON_DimStyle* parent_style) const; + void SetAngleZeroSuppress(const ON_DimStyle* parent_style, ON_DimStyle::suppress_zero s); + + bool AlternateBelow(const ON_DimStyle* parent_style) const; + void SetAlternateBelow(const ON_DimStyle* parent_style, bool below); + + ON_Arrowhead::arrow_type ArrowType1(const ON_DimStyle* parent_style) const; + void SetArrowType1(const ON_DimStyle* parent_style, ON_Arrowhead::arrow_type); + + ON_Arrowhead::arrow_type ArrowType2(const ON_DimStyle* parent_style) const; + void SetArrowType2(const ON_DimStyle* parent_style, ON_Arrowhead::arrow_type); + + void SetArrowType1And2(const ON_DimStyle* parent_style, ON_Arrowhead::arrow_type); + + ON_Arrowhead::arrow_type LeaderArrowType(const ON_DimStyle* parent_style) const; + void SetLeaderArrowType(const ON_DimStyle* parent_style, ON_Arrowhead::arrow_type); + + ON_UUID ArrowBlockId1(const ON_DimStyle* parent_style) const; + void SetArrowBlockId1(const ON_DimStyle* parent_style, ON_UUID id); + + ON_UUID ArrowBlockId2(const ON_DimStyle* parent_style) const; + void SetArrowBlockId2(const ON_DimStyle* parent_style, ON_UUID id); + + ON_UUID LeaderArrowBlockId(const ON_DimStyle* parent_style) const; + void SetLeaderArrowBlockId(const ON_DimStyle* parent_style, ON_UUID id); + + ON::TextVerticalAlignment TextVerticalAlignment(const ON_DimStyle* parent_style) const; + void SetTextVerticalAlignment(const ON_DimStyle* parent_style, ON::TextVerticalAlignment style); + + ON::TextVerticalAlignment LeaderTextVerticalAlignment(const ON_DimStyle* parent_style) const; + void SetLeaderTextVerticalAlignment(const ON_DimStyle* parent_style, ON::TextVerticalAlignment style); + + ON_DimStyle::ContentAngleStyle LeaderContentAngleStyle(const ON_DimStyle* parent_style) const; + void SetLeaderContentAngleStyle(const ON_DimStyle* parent_style, ON_DimStyle::ContentAngleStyle style); + + ON_DimStyle::leader_curve_type LeaderCurveType(const ON_DimStyle* parent_style) const; + void SetLeaderCurveType(const ON_DimStyle* parent_style, ON_DimStyle::leader_curve_type type); + + bool LeaderHasLanding(const ON_DimStyle* parent_style) const; + void SetLeaderHasLanding(const ON_DimStyle* parent_style, bool landing); + + double LeaderLandingLength(const ON_DimStyle* parent_style) const; + void SetLeaderLandingLength(const ON_DimStyle* parent_style, double length); + + double LeaderContentAngleRadians(const ON_DimStyle* parent_style) const; + void SetLeaderContentAngleRadians(const ON_DimStyle* parent_style, double angle_radians); + + double LeaderContentAngleDegrees(const ON_DimStyle* parent_style) const; + void SetLeaderContentAngleDegrees(const ON_DimStyle* parent_style, double angle_degrees); + + ON_DimStyle::ContentAngleStyle DimTextAngleStyle(const ON_DimStyle* parent_style) const; + void SetDimTextAngleStyle(const ON_DimStyle* parent_style, ON_DimStyle::ContentAngleStyle style); + + ON_DimStyle::ContentAngleStyle DimRadialTextAngleStyle(const ON_DimStyle* parent_style) const; + void SetDimRadialTextAngleStyle(const ON_DimStyle* parent_style, ON_DimStyle::ContentAngleStyle style); + + ON::TextHorizontalAlignment TextHorizontalAlignment(const ON_DimStyle* parent_style) const; + void SetTextHorizontalAlignment(const ON_DimStyle* parent_style, ON::TextHorizontalAlignment halign); + + ON::TextHorizontalAlignment LeaderTextHorizontalAlignment(const ON_DimStyle* parent_style) const; + void SetLeaderTextHorizontalAlignment(const ON_DimStyle* parent_style, ON::TextHorizontalAlignment halign); + + ON::TextOrientation TextOrientation(const ON_DimStyle* parent_style) const; + void SetTextOrientation(const ON_DimStyle* parent_style, ON::TextOrientation orientation); + + ON::TextOrientation LeaderTextOrientation(const ON_DimStyle* parent_style) const; + void SetLeaderTextOrientation(const ON_DimStyle* parent_style, ON::TextOrientation orientation); + + ON::TextOrientation DimTextOrientation(const ON_DimStyle* parent_style) const; + void SetDimTextOrientation(const ON_DimStyle* parent_style, ON::TextOrientation orientation); + + ON::TextOrientation DimRadialTextOrientation(const ON_DimStyle* parent_style) const; + void SetDimRadialTextOrientation(const ON_DimStyle* parent_style, ON::TextOrientation orientation); + + bool DrawForward(const ON_DimStyle* parent_style) const; + void SetDrawForward(const ON_DimStyle* parent_style, bool drawforward); + + bool TextUnderlined(const ON_DimStyle* parent_style) const; + void SetTextUnderlined(const ON_DimStyle* parent_style, bool underlined); + + bool SignedOrdinate(const ON_DimStyle* parent_style) const; + void SetSignedOrdinate(const ON_DimStyle* parent_style, bool allowsigned); + + double DimScale(const ON_DimStyle* parent_style) const; + void SetDimScale(const ON_DimStyle* parent_style, double scale); + + wchar_t DecimalSeparator(const ON_DimStyle* parent_style) const; + void SetDecimalSeparator(const ON_DimStyle* parent_style, wchar_t separator); + + ON_DimStyle::LengthDisplay DimensionLengthDisplay(const ON_DimStyle* parent_style) const; + void SetDimensionLengthDisplay(const ON_DimStyle* parent_style, ON_DimStyle::LengthDisplay length_display); + + ON_DimStyle::LengthDisplay AlternateDimensionLengthDisplay(const ON_DimStyle* parent_style) const; + void SetAlternateDimensionLengthDisplay(const ON_DimStyle* parent_style, ON_DimStyle::LengthDisplay length_display); + + /// + /// Parameters: + /// model_sn - 0, a model serial number, or ON_UNSET_UINT_INDEX to + /// use the dimstyle's ModelSerialNumber() value. + /// Returns + /// Unit system for dimension length display. + /// If DimensionLengthDisplay() == ON_DimStyle::LengthDisplay::ModelUnits + /// and model_sn > 0, then the value of ON::LengthUnitSystemFromModelSerialNumber(model_sn) + /// is returned. + /// If DimensionLengthDisplay() == ON_DimStyle::LengthDisplay::ModelUnits + /// and model_sn == 0, then ON::LengthUnitSystem::None is returned. + /// + ON::LengthUnitSystem DimensionLengthDisplayUnit( + const ON_DimStyle* parent_style, + unsigned int model_sn + ) const; + + /// + /// Parameters: + /// model_sn - 0, a model serial number, or ON_UNSET_UINT_INDEX to + /// use the dimstyle's ModelSerialNumber() value. + /// Returns + /// Unit system for dimension length display. + /// If DimensionLengthDisplay() == ON_DimStyle::LengthDisplay::ModelUnits + /// and model_sn > 0, then the value of ON::LengthUnitSystemFromModelSerialNumber(model_sn) + /// is returned. + /// If DimensionLengthDisplay() == ON_DimStyle::LengthDisplay::ModelUnits + /// and model_sn == 0, then ON::LengthUnitSystem::None is returned. + /// + ON::LengthUnitSystem AlternateDimensionLengthDisplayUnit( + const ON_DimStyle* parent_style, + unsigned int model_sn + ) const; + + /* + Description: + Set the font used to render text. + Parameters: + font_characteristics - [in] + This parameter does not have to be a managed font. + Remarks: + If the parameter is a managed font (font_characteristics.IsManagedFont() is true), + then the identical value is returned by ON_DimStyle.Font(). + If the parameter is not a managed font (font_characteristics.IsManagedFont() is false), + then the ON_Font::GetManagedFont(font_characteristics) will be returned by + ON_DimStyle.Font(). + */ + void SetFont(const ON_DimStyle* parent_style, const class ON_Font& font_characteristics); + + /* + Returns: + The managed font used to render text. + */ + const class ON_Font& Font(const ON_DimStyle* parent_style) const; + + /* + Returns: + A copy of the font_characteristics information. + Remarks: + You probably want to use Font(). This function is only useful + in isolated situations and is typically used to study font + substitutions when a model moves between computers or platforms. + */ + const class ON_Font& FontCharacteristics(const ON_DimStyle* parent_style) const; + + /* + Returns: + True if the font returned by Font() is a substitute + for the font passed to SetFont(). + Remarks: + Font substitution can occur when a model is moved between + computers that have different fonts installed. + */ + const bool FontSubstituted(const ON_DimStyle* parent_style) const; + + bool SetAnnotationBold(bool bold, const ON_DimStyle* dimstyle); + bool SetAnnotationItalic(bool italic, const ON_DimStyle* dimstyle); + bool SetAnnotationUnderline(bool underline, const ON_DimStyle* dimstyle); + bool SetAnnotationFacename(bool set_or_clear, const wchar_t* facename, const ON_DimStyle* parent_style); + bool SetAnnotationFont(const ON_Font* font, const ON_DimStyle* parent_style); + + static bool SetAnnotationTextFormat(ON_wString& rtf_in, const wchar_t* fmt_str_on, const wchar_t* fmt_str_off, bool set_on); + + static bool SetRtfFmt(ON_wString& rtf_in, const wchar_t* fmt_str); + static bool ClearRtfFmt(const wchar_t* fmt_str_on, const wchar_t* fmt_str_off, ON_wString& rtf_in); + static int FindRtfTable(ON_wString rtf_in, int startidx, const wchar_t* tablename); + + static bool FirstCharTextProperties(const wchar_t* rtf_in, bool& bold, bool& italic, bool& underline, ON_wString& facename); + + const ON_Font* FirstCharFont() const; + +private: + bool IsAllFormat(bool (ON_Font::*func)() const) const; + +public: + // true if all of the text is bold + bool IsAllBold() const; + + // true if all of the text is italic + bool IsAllItalic() const; + + // true if all of the text is underlined + bool IsAllUnderlined() const; + + friend class ON_Dimension; +}; + + +/* + A simple dot with text that doesn't rotate witn the world axes +*/ +class ON_CLASS ON_TextDot : public ON_Geometry +{ + ON_OBJECT_DECLARE(ON_TextDot); +public: + static const wchar_t* DefaultFontFace; // Arial + static const int DefaultHeightInPoints; // 14 points + static const int MinimumHeightInPoints; // 3 points + static const ON_TextDot Unset; + + ON_TextDot(); + ~ON_TextDot(); + ON_TextDot( const ON_TextDot& ) = default; + ON_TextDot& operator=( const ON_TextDot& ) = default; + + ON_TextDot( + ON_3dPoint center_point, + const wchar_t* primary_text, + const wchar_t* secondary_text + ); + + static ON_TextDot* CreateFromV2AnnotationTextDot( + const class ON_OBSOLETE_V2_TextDot& V2_text_dot, + const class ON_3dmAnnotationContext* annotation_context, + ON_TextDot* destination + ); + + void EmergencyDestroy(); + + //--------------------------- + // ON_Object overrides + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + /* + Description: Write data values to a text file for debugging + */ + void Dump( ON_TextLog& log) const override; + + /* + Description: Writes the object to a file + + Returns: + @untitled Table + true Success + false Failure + */ + bool Write( ON_BinaryArchive& ar) const override; + + /* + Description: Reads the object from a file + + Returns: + @untitled Table + true Success + false Failure + */ + bool Read( ON_BinaryArchive& ar) override; + + /* + Returns: The Object Type of this object + */ + ON::object_type ObjectType() const override; + + //--------------------------- + // ON_Geometry overrides + + /* + Returns the geometric dimension of the object ( usually 3) + */ + int Dimension() const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + /* + Description: + Transform the object by a 4x4 xform matrix + Parameters: + [in] xform - An ON_Xform with the transformation information + Returns: + true = Success + false = Failure + Remarks: + The object has been transformed when the function returns + */ + bool Transform( const ON_Xform& xform) override; + + // virtual ON_Geometry::IsDeformable() override + bool IsDeformable() const override; + + // virtual ON_Geometry::MakeDeformable() override + bool MakeDeformable() override; + + + ON_3dPoint CenterPoint() const; + void SetCenterPoint( + ON_3dPoint center_point + ); + + ON_DEPRECATED_MSG("use CenterPoint") + const ON_3dPoint& Point() const; + ON_DEPRECATED_MSG("use SetCenterPoint") + void SetPoint(const ON_3dPoint& point); + + /* + Returns: + Text height in "points". + Remarks: + Default height = 14; + */ + int HeightInPoints() const; + void SetHeightInPoints( + int height_in_points + ); + + /* + Returns: + Dot's primary text displayed in the model + Typically a short and terse string. + Default = empty string. + Remarks: + Additional information can be saved as secondary text. + + Never save the pointer value for future use. + Save a copy in ON_wString if the text is needed beyond the scope of + the call to Text(). + */ + const wchar_t* PrimaryText() const; + void SetPrimaryText( + const wchar_t* primary_dot_text + ); + + ON_DEPRECATED_MSG("use PrimaryText") + const wchar_t* TextString() const; + ON_DEPRECATED_MSG("use SetPrimaryText") + void SetTextString(const wchar_t* string); + /* + Returns: + Dot's secondary text displayed when a user interface event like cliking or hovering occurs. + Typically longer and more detailed than the primary text. + Default = empty string. + Remarks: + Never save the pointer value for future use. + Save a copy in ON_wString if the text is needed beyond the scope of + the call to Text(). + */ + const wchar_t* SecondaryText() const; + void SetSecondaryText( + const wchar_t* secondary_dot_text + ); + + + /* + Returns: + Primary text font face. + Default = "Arial Bold"; + Remarks: + Never save the pointer value for future use. + Save a copy in ON_wString if the text is needed beyond the scope of + the call to FontFace(). + */ + const wchar_t* FontFace() const; + void SetFontFace( + const wchar_t* font_face) + ; + + /* + Description: + Get or Set whether the dot is drawn "On Top" of other geometry + Parameters: + [in] bTop bool - It is or isn't on top + Returns: + @untitled table + true - on top + false - not on top + */ + void SetAlwaysOnTop( + bool bAlwaysOnTop + ); + bool AlwaysOnTop() const; + + /* + Description: + Get or Set whether the dot is drawn with a transparent background + Parameters: + [in] bTransparent bool - It is or isn't transparent + Returns: + @untitled table + true - transparent + false - not transparent + */ + void SetTransparent( + bool bTransparent + ); + bool Transparent() const; + + /* + Description: + Get or Set whether the dot is drawn with Bold text + Parameters: + [in] bBold bool - It is or isn't Bold + Returns: + @untitled table + true - Bold + false - not Bold + */ + void SetBold( + bool bBold + ); + bool Bold() const; + + /* + Description: + Get or Set whether the dot is drawn with Italic text + Parameters: + [in] bItalic bool - It is or isn't Italic + Returns: + @untitled table + true - Italic + false - not Italic + */ + void SetItalic( + bool bItalic + ); + bool Italic() const; + +private: + // Location of the center of the text dot. + ON_3dPoint m_center_point = ON_3dPoint::UnsetPoint; + +private: + ON_wString m_primary_text; // default is empty + +private: + ON_wString m_secondary_text; // default is empty + +private: + ON_wString m_font_face; // Empty means ON_TextDot::DefaultFontFace + +private: + unsigned int m_display_bits = 0; + +private: + int m_height_in_points = ON_TextDot::DefaultHeightInPoints; +}; + +#endif diff --git a/opennurbs/Include/opennurbs_apple_nsfont.h b/opennurbs/Include/opennurbs_apple_nsfont.h new file mode 100644 index 0000000..073e58f --- /dev/null +++ b/opennurbs/Include/opennurbs_apple_nsfont.h @@ -0,0 +1,45 @@ +/* +// +// Copyright (c) 1993-2018 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_APPLE_NSFONT_INC_) +#define OPENNURBS_APPLE_NSFONT_INC_ + +#if defined(ON_RUNTIME_APPLE_CORE_TEXT_AVAILABLE) + +ON_DECL +unsigned int ON_AppleFontGlyphIndex( + CTFontRef appleFont, + unsigned int unicode_code_point +); + +ON_DECL +bool ON_AppleFontGetGlyphMetrics( + CTFontRef appleFont, + unsigned int font_design_units_per_M, + unsigned int glyphIndex, + class ON_TextBox& glyph_metrics +); + +ON_DECL +bool ON_AppleFontGetGlyphOutline( + CTFontRef appleFont, + unsigned int font_design_units_per_M, + unsigned int glyphIndex, + ON_OutlineFigure::Type figure_type, + class ON_Outline& outline +); +#endif + +#endif diff --git a/opennurbs/Include/opennurbs_arc.h b/opennurbs/Include/opennurbs_arc.h new file mode 100644 index 0000000..5bd2826 --- /dev/null +++ b/opennurbs/Include/opennurbs_arc.h @@ -0,0 +1,602 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_ARC_INC_) +#define ON_ARC_INC_ + +/* +Description: + An ON_Arc is a subcurve of 3d circle. +Details: + The curve is parameterized by an angle expressed in radians. For an IsValid() arc + the total subtended angle AngleRadians() = Domain()(1) - Domain()(0) must satisfy + 0< AngleRadians() <2*Pi . + + The parameterization of the ON_Arc is inherited from the ON_Circle it is derived from. + In particular + t -> center + cos(t)*radius*xaxis + sin(t)*radius*yaxis + where xaxis and yaxis, (part of ON_Circle::m_plane) form an othonormal frame of the plane + containing the circle. +*/ +class ON_CLASS ON_Arc : public ON_Circle +{ +public: + // Create a radius one arc with angle = 2*pi + ON_Arc() = default; + ~ON_Arc() = default; + ON_Arc(const ON_Arc&) = default; + ON_Arc& operator=(const ON_Arc&) = default; + + ON_Arc& operator=( const ON_Circle& ); + + static const ON_Arc UnitCircle; // unit circle in the xy plane + + /* + Description: + Construct an arc from a circle and an angle in radians + Parameters: + circle - [in] + angle_in_radians - [in] + */ + ON_Arc( + const ON_Circle& circle, + double angle_in_radians + ); + + /* + Parameters: + circle - [in] + angle_interval_in_radians - [in] increasing angle interval + in radians with angle_interval_in_radians.Length() <= 2.0*ON_PI. + */ + ON_Arc( + const ON_Circle& circle, + ON_Interval angle_interval_in_radians + ); + + /* + Description: + Construct an arc from a plane, radius and an angle in radians. + The center of the arc is at the plane's origin. + Parameters: + plane - [in] + circle is in this plane with center at m_origin + center - [in] + circle's center point + radius - [in] + angle_in_radians - [in] + */ + ON_Arc( + const ON_Plane& plane, + double radius, + double angle_in_radians + ); + + /* + Description: + Construct an arc parallel to the world XY plane from a + center point, radius, and angle in radians. + The arc starts at center+(radius,0,0). + Parameters: + center - [in] + radius - [in] + angle_in_radians - [in] + */ + ON_Arc( + const ON_3dPoint& center, + double radius, + double angle_in_radians + ); + + /* + Description: + Construct an arc parallel to plane from a center point, + radius, and angle in radians. + The arc starts at center+radius*plane.xaxis. + Parameters: + plane - [in] + The plane x, y and z axis are used to defines the circle + plane's x, y and z axis. The plane origin is ignorned. + center - [in] + circle's center point + radius - [in] + angle_in_radians - [in] + */ + ON_Arc( + const ON_Plane& plane, + const ON_3dPoint& center, + double radius, + double angle_in_radians + ); + + /* + Description: + Construct an arc that passes through three 2d points. + Parameters: + start_point - [in] + interior_point - [in] + end_point - [in] + */ + ON_Arc( + const ON_2dPoint& start_point, + const ON_2dPoint& interior_point, + const ON_2dPoint& end_point + ); + + /* + Description: + Construct an arc that passes through three 3d points. + Parameters: + start_point - [in] + interior_point - [in] + end_point - [in] + */ + ON_Arc( + const ON_3dPoint& start_point, + const ON_3dPoint& interior_point, + const ON_3dPoint& end_point + ); + + /* + Description: + Create an arc from a circle and an angle in radians + Parameters: + circle - [in] + angle_in_radians - [in] + Returns: + true if input is valid and a valid arc is created. + */ + bool Create( + const ON_Circle& circle, + double angle_in_radians + ); + + /* + Description: + Create an arc from a circle and an increasing angle interval + Parameters: + circle - [in] + angle_interval_in_radians - [in] increasing angle interval in radians + with angle_interval_in_radians.Length() <= 2.0*ON_PI + Returns: + true if input is valid and a valid arc is created. + */ + bool Create( + const ON_Circle& circle, + ON_Interval angle_interval_in_radians + ); + + /* + Description: + Create an arc from a plane, radius and an angle in radians. + The center of the arc is at the plane's origin. + Parameters: + plane - [in] + circle is in this plane with center at m_origin + center - [in] + circle's center point + radius - [in] + angle_in_radians - [in] + */ + bool Create( + const ON_Plane& plane, + double radius, + double angle_in_radians + ); + + /* + Description: + Create an arc parallel to the world XY plane from a + center point, radius, and angle in radians. + The arc starts at center+(radius,0,0). + Parameters: + center - [in] + radius - [in] + angle_in_radians - [in] + */ + bool Create( + const ON_3dPoint& center, + double radius, + double angle_in_radians + ); + + /* + Description: + Create an arc parallel to plane from a center point, + radius, and angle in radians. + The arc starts at center+radius*plane.xaxis. + Parameters: + plane - [in] + The plane x, y and z axis are used to defines the circle + plane's x, y and z axis. The plane origin is ignorned. + center - [in] + circle's center point + radius - [in] + angle_in_radians - [in] + */ + bool Create( + const ON_Plane& plane, + const ON_3dPoint& center, + double radius, + double angle_in_radians + ); + + /* + Description: + Create an arc that passes through three 2d points. + Parameters: + start_point - [in] + interior_point - [in] + end_point - [in] + */ + bool Create( + const ON_2dPoint& start_point, + const ON_2dPoint& interior_point, + const ON_2dPoint& end_point + ); + + /* + Description: + Create an arc that passes through three 3d points. + Parameters: + start_point - [in] + interior_point - [in] + end_point - [in] + */ + bool Create( + const ON_3dPoint& start_point, + const ON_3dPoint& interior_point, + const ON_3dPoint& end_point + ); + + /* + Description: + Create an arc from a 2d start point, 2d start direction + and a 2d end point. + Parameters: + start_point - [in] + dir_at_start - [in] + end_point - [in] + */ + bool Create( + const ON_2dPoint& start_point, + const ON_2dVector& dir_at_start, + const ON_2dPoint& end_point + ); + + /* + Description: + Create an arc from a 3d start point, 3d start direction + and a 3d end point. + Parameters: + start_point - [in] + dir_at_start - [in] + end_point - [in] + */ + bool Create( + const ON_3dPoint& start_point, + const ON_3dVector& dir_at_start, + const ON_3dPoint& end_point + ); + + // Description: + // Creates a text dump of the arc listing the normal, center + // radius, start point, end point, and angle. + // Remarks: + // Dump() is intended for debugging and is not suitable + // for creating high quality text descriptions of an + // arc. + void Dump( ON_TextLog& dump ) const; + + // Description: + // Checks an arc to make sure it is valid. + // Detail: + // Radius>0 and 0. +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_GEOMETRY_CURVE_ARC_INC_) +#define ON_GEOMETRY_CURVE_ARC_INC_ + + +/* +Description: + ON_ArcCurve is used to represent arcs and circles. + ON_ArcCurve.IsCircle() returns true if the curve + is a complete circle. +Remarks: + - An ON_ArcCurve is a subcurve of a circle, with a + constant speed parameterization. The parameterization is + an affine linear reparameterzation of the underlying arc + m_arc onto the domain m_t. + - A valid ON_ArcCurve has Radius()>0 and 0 0 if curve locus is an arc between + // specified points + const ON_Plane* = nullptr, // if not nullptr, test is performed in this plane + ON_Arc* = nullptr, // if not nullptr and true is returned, then arc parameters + // are filled in + double = 0.0 // tolerance to use when checking + ) const override; + + bool IsPlanar( + ON_Plane* = nullptr, // if not nullptr and true is returned, then plane parameters + // are filled in + double = 0.0 // tolerance to use when checking + ) const override; + + bool IsInPlane( + const ON_Plane&, // plane to test + double = 0.0 // tolerance to use when checking + ) const override; + + bool IsClosed( // true if curve is closed (either curve has + void // clamped end knots and euclidean location of start + ) const override; // CV = euclidean location of end CV, or curve is + // periodic.) + + bool IsPeriodic( // true if curve is a single periodic segment + void + ) const override; + + bool IsContinuous( + ON::continuity c, + double t, + int* hint = nullptr, + double point_tolerance=ON_ZERO_TOLERANCE, + double d1_tolerance=ON_ZERO_TOLERANCE, + double d2_tolerance=ON_ZERO_TOLERANCE, + double cos_angle_tolerance=ON_DEFAULT_ANGLE_TOLERANCE_COSINE, + double curvature_tolerance=ON_SQRT_EPSILON + ) const override; + + bool Reverse() override; // reverse parameterizatrion + // Domain changes from [a,b] to [-b,-a] + + /* + Description: + Force the curve to start at a specified point. + Parameters: + start_point - [in] + Returns: + true if successful. + Remarks: + Some end points cannot be moved. Be sure to check return + code. + See Also: + ON_Curve::SetEndPoint + ON_Curve::PointAtStart + ON_Curve::PointAtEnd + */ + bool SetStartPoint( + ON_3dPoint start_point + ) override; + + /* + Description: + Force the curve to end at a specified point. + Parameters: + end_point - [in] + Returns: + true if successful. + Remarks: + Some end points cannot be moved. Be sure to check return + code. + See Also: + ON_Curve::SetStartPoint + ON_Curve::PointAtStart + ON_Curve::PointAtEnd + */ + bool SetEndPoint( + ON_3dPoint end_point + ) override; + + bool Evaluate( // returns false if unable to evaluate + double, // evaluation parameter + int, // number of derivatives (>=0) + int, // array stride (>=Dimension()) + double*, // array of length stride*(ndir+1) + int = 0, // optional - determines which side to evaluate from + // 0 = default + // < 0 to evaluate from below, + // > 0 to evaluate from above + int* = 0 // optional - evaluation hint (int) used to speed + // repeated evaluations + ) const override; + + bool Trim( const ON_Interval& ) override; + + // Description: + // Where possible, analytically extends curve to include domain. + // Parameters: + // domain - [in] if domain is not included in curve domain, + // curve will be extended so that its domain includes domain. + // Will not work if curve is closed. Original curve is identical + // to the restriction of the resulting curve to the original curve domain, + // Returns: + // true if successful. + bool Extend( + const ON_Interval& domain + ) override; + + /* + Description: + Splits (divides) the arc at the specified parameter. + The parameter must be in the interior of the arc's domain. + The ON_Curve pointers passed to ON_ArcCurve::Split must + either be nullptr or point to ON_ArcCurve objects. + If a pointer is nullptr, then an ON_ArcCurve will be created + in Split(). You may pass "this" as left_side or right_side. + Parameters: + t - [in] parameter to split the curve at in the + interval returned by Domain(). + left_side - [out] left portion of curve returned here. + If not nullptr, left_side must point to an ON_ArcCuve. + right_side - [out] right portion of curve returned here + If not nullptr, right_side must point to an ON_ArcCuve. + Remarks: + Overrides virtual ON_Curve::Split. + */ + bool Split( + double t, + ON_Curve*& left_side, + ON_Curve*& right_side + ) const override; + + + // virtual ON_Curve::GetNurbForm override + int GetNurbForm( // returns 0: unable to create NURBS representation + // with desired accuracy. + // 1: success - returned NURBS parameterization + // matches the curve's to wthe desired accuracy + // 2: success - returned NURBS point locus matches + // the curve's to the desired accuracy but, on + // the interior of the curve's domain, the + // curve's parameterization and the NURBS + // parameterization may not match to the + // desired accuracy. + ON_NurbsCurve&, + double = 0.0, + const ON_Interval* = nullptr // OPTIONAL subdomain of arc curve + ) const override; + + // virtual ON_Curve::HasNurbForm override + int HasNurbForm( // returns 0: unable to create NURBS representation + // with desired accuracy. + // 1: success - NURBS parameterization + // matches the curve's + // 2: success - returned NURBS point locus matches + // the curve'sbut, on + // the interior of the curve's domain, the + // curve's parameterization and the NURBS + // parameterization may not match to the + // desired accuracy. + ) const override; + + // virtual ON_Curve::GetCurveParameterFromNurbFormParameter override + bool GetCurveParameterFromNurbFormParameter( + double, // nurbs_t + double* // curve_t + ) const override; + + // virtual ON_Curve::GetNurbFormParameterFromCurveParameter override + bool GetNurbFormParameterFromCurveParameter( + double, // curve_t + double* // nurbs_t + ) const override; + + + /* + Description: + Returns true if this arc curve is a complete circle. + */ + bool IsCircle() const; + + // Returns: + // The arc's radius. + double Radius() const; + + // Returns: + // The arc's subtended angle in radians. + double AngleRadians() const; + + // Returns: + // The arc's subtended angle in degrees. + double AngleDegrees() const; + + + ///////////////////////////////////////////////////////////////// + + ON_Arc m_arc = ON_Arc::UnitCircle; // defualt = radius 1 circle in x-y plane + + ON_Interval m_t = ON_Interval::ZeroToTwoPi; + + // The dimension of a arc curve can be 2 or 3. + // (2 so ON_ArcCurve can be used as a trimming curve) + int m_dim = 3; +}; + + +#endif diff --git a/opennurbs/Include/opennurbs_archive.h b/opennurbs/Include/opennurbs_archive.h new file mode 100644 index 0000000..852a828 --- /dev/null +++ b/opennurbs/Include/opennurbs_archive.h @@ -0,0 +1,5814 @@ +/* +// +// Copyright (c) 1993-2016 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_ARCHIVE_INC_) +#define ON_ARCHIVE_INC_ + + +///////////////////////////////////////////////////////////////////// +// +// ON_Buffer +// + +typedef void (*ON_Buffer_ErrorHandler)(class ON_Buffer*); + +class ON_CLASS ON_Buffer +{ +public: + ON_Buffer(); + ~ON_Buffer(); + + ON_Buffer(const ON_Buffer& src); + ON_Buffer& operator=(const ON_Buffer& src); + + /* + Description: + Compare contents of buffers. + Paramters: + a - [in] + b - [in] + Returns: + -1: a < b + 0: a == b + 1: a > b + */ + static int Compare( const ON_Buffer& a, const ON_Buffer& b ); + + void Destroy(); + void EmergencyDestroy(); + + /* + Returns: + True if Size() == CurrentPosition(). + Remarks: + It is possible to seek beyond the end of the buffer. + In this case, the current position will be past the end + of the buffer and AtEnd() will return false. + */ + bool AtEnd() const; + + /* + Returns: + Number of bytes currently in the buffer. + Remarks: + It is possible to seek beyond the end of the buffer. + In this case, the current position will be past the end + of the buffer and CurrentPosition() will be greater than + Size(). + */ + ON__UINT64 Size() const; + + /* + Returns: + 32-bit CRC of the buffer contents. + Remarks: + + */ + ON__UINT32 CRC32( ON__UINT32 current_remainder ) const; + + + /* + Returns: + Current position in the buffer. + Remarks: + It is possible to seek beyond the end of the buffer. + In this case, the current position will be past the end + of the buffer and CurrentPosition() will be greater than + Size(). + */ + ON__UINT64 CurrentPosition() const; + + /* + Parameters: + size - [in] + number of bytes to write. + buffer - [in] + values to write. + Returns: + Number of bytes written buffer. + */ + ON__UINT64 Write( ON__UINT64 size, const void* buffer ); + + /* + Parameters: + size - [in] + number of bytes to read. + buffer - [out] + read values are returned in buffer. + Returns: + Number of bytes read into buffer. For example, + if CurrentPosition() <= Size() and + size > (Size() - CurrentPosition()) and + buffer is not null, then the value + (Size() - CurrentPosition()) is returned. + Remarks: + If the size parameter is zero, then nothing is done. + When CurrentPosition() <= Size(), attempts to read more + than (Size() - CurrentPosition()) bytes do not generate + an error. When CurrentPosition() > Size(), any attempt + to read generates an error. + */ + ON__UINT64 Read( ON__UINT64 size, void* buffer ); + + enum + { + seek_from_beginning_of_file = 0, + seek_from_current_position = 1, + seek_from_end_of_file = 2 + }; + + /* + Parameters: + offset - [in] + number of bytes to seek from origin + origin - [in] + initial position. + 0 (SEEK_SET) Seek from beginning of file. + 1 (SEEK_CUR) Seek from current position. + 2 (SEEK_END) Seek from end of file. + Returns: + True if successful. + False if the seek would result in a file position + before the beginning of the file. If false is + returned, the current position is not changed. + Remarks: + Seeking beyond the end of the buffer is succeeds. + Seeking before the beginning of the buffer fails. + */ + bool Seek( + ON__INT64 offset, + int origin + ); + + /* + Parameters: + offset - [in] (>= 0) + number of bytes to seek from the start of the buffer. + Returns: + True if successful. + False if the seek would result in a file position + before the beginning of the file. If false is + returned, the current position is not changed. + Remarks: + Seeking beyond the end of the buffer is succeeds. + Seeking before the beginning of the buffer fails. + */ + bool SeekFromStart( ON__INT64 offset ); + + /* + Parameters: + offset - [in] + number of bytes to seek from the current position. + Returns: + True if successful. + False if the seek would result in a file position + before the beginning of the file. If false is + returned, the current position is not changed. + Remarks: + Seeking beyond the end of the buffer is succeeds. + Seeking before the beginning of the buffer fails. + */ + bool SeekFromCurrentPosition( ON__INT64 offset ); + + /* + Parameters: + offset - [in] + number of bytes to seek from the end fo the buffer. + Returns: + True if successful. + False if the seek would result in a file position + before the beginning of the file. If false is + returned, the current position is not changed. + Remarks: + Seeking beyond the end of the buffer is succeeds. + Seeking before the beginning of the buffer fails. + */ + bool SeekFromEnd( ON__INT64 offset ); + + /* + Parameters: + buffer_size - [in] + new size of buffer. + Returns: + True if successful. + Remarks: + The current position is not changed and may be beyond the + end of the file. Use Seek to set the current position after + calling ChangeSize(). + */ + bool ChangeSize( ON__UINT64 buffer_size ); + + /* + Description: + Return unused memory to heap. + Remarks: + Call this function after creating an ON_Buffer that will persist for + and extended amount of time. There are never more than 16 pages of + unsued memory (16*4096 bytes on most computers) in an ON_Buffer. + Compact() can be called at any time, but calling Compact() the then + writing at the end of the buffer is not an efficient use of time + or memory. + */ + bool Compact(); + + /* + Returns + True if the ON_Buffer is valid. + */ + bool IsValid( const ON_TextLog* text_log ) const; + + /* + Returns: + Value that identifies most recent error. + 0: no error + 1: attempt to seek to a negative position + */ + ON__UINT32 LastError() const; + + void ClearLastError(); + + ON_Buffer_ErrorHandler ErrorHandler() const; + + void SetErrorHandler(ON_Buffer_ErrorHandler error_handler); + + /* + Description: + Use WriteToBinaryArchive() to save an entire ON_Buffer inside + a binary archive. Use ReadFromBinaryArchive() to retrieve + the ON_Buffer from the ON_BinaryArchive. + */ + bool WriteToBinaryArchive( ON_BinaryArchive& ) const; + + /* + Description: + Use ReadFromBinaryArchive() to retrieve an entire ON_Buffer + that was written using WriteToBinaryArchive(). + */ + bool ReadFromBinaryArchive( ON_BinaryArchive& ); + + /* + Description: + Compress this buffer + + Parameters: + compressed_buffer - [out] + (The reference can be *this) + + Example: + + // compress a buffer in place + ON_Buffer buffer; + buffer = ...; + if ( !buffer.Compress(buffer) ) + { + // compression failed + } + else + { + // buffer is now compressed + } + + Returns: + True if successful. False if failed. + */ + bool Compress( ON_Buffer& compressed_buffer ) const; + + /* + Description: + Uncompress this buffer which must have been compressed using + ON_Buffer::Compress(). + + Parameters: + uncompressed_buffer - [out] + (The reference can be *this) + + Example: + // silly example that compresses and then uncompresses a buffer in place + // to show how to call the functions. + ON_Buffer buffer; + buffer = ...; // buffer is in it uncompressed form + if ( buffer.Compress(buffer) ) + { + // buffer is now compressed + if ( buffer.Uncompress(buffer) ) + { + // buffer is uncompressed again. + } + } + + Returns: + True if successful. False if failed. + */ + bool Uncompress( ON_Buffer& uncompressed_buffer ) const; + +private: + + ON__UINT64 m_buffer_size; // total number of bytes in the buffer + ON__UINT64 m_current_position; + + struct ON_BUFFER_SEGMENT* m_first_segment; + struct ON_BUFFER_SEGMENT* m_last_segment; + struct ON_BUFFER_SEGMENT* m_current_segment; + bool SetCurrentSegment(bool); + void Copy( const ON_Buffer& ); + + ON_Buffer_ErrorHandler m_error_handler; + + ON__UINT32 m_last_error; + unsigned char m_reserved[12]; +}; + +///////////////////////////////////////////////////////////////////// +// +// ON_BinaryArchive +// virtual class for CPU independent serialization +// +// ON_BinaryFile +// simple class for CPU independent binary file I/O +// includes optional CRC support +// + +struct ON_3DM_CHUNK +{ + size_t m_offset; // In read or write_using_fseek mode, this is the + // file position of first byte after chunk's length. + // In write_using_buffer mode, this of the m_buffer[] + // position of first byte after chunk's length. + unsigned int m_typecode; + int m_value; + int m_do_length; // true if chunk is a long chunk with length + ON__UINT16 m_do_crc16; // 16 bit CRC using CCITT polynomial + ON__UINT16 m_crc16; + ON__UINT32 m_do_crc32; // 32 bit CRC + ON__UINT32 m_crc32; +}; + +class ON_CLASS ON_3DM_BIG_CHUNK +{ +public: + ON_3DM_BIG_CHUNK() = default; + ~ON_3DM_BIG_CHUNK() = default; + ON_3DM_BIG_CHUNK(const ON_3DM_BIG_CHUNK&) = default; + ON_3DM_BIG_CHUNK& operator=(const ON_3DM_BIG_CHUNK&) = default; + +public: + ON__UINT64 m_start_offset=0; // When reading or writing 3dm archives, this is the + // archive offset (file position) of first byte of + // chunk information conent. + + ON__UINT64 m_end_offset=0; // When writing 3dm archives, this is the archive + // offset (file position) of the byte immediately after + // the farthest successful write. + // When reading 3dm archives, this the archive offset + // of the first byte after the chunk's information content. + // When reading, a 16 bit or 32 bit CRC can follow the chunk + // information content. + // During ordinary reading and writing, valid seek target + // positions satisfy + // m_start_offset <= seek target pos <= m_end_offset. + + /* + Returns: + Number of bytes in the chunk, including bytes used to store CRC values. + 0 for short chunks. + 0 for chunks currently being written. + Remarks: + For chunks being read, + m_start_offset + Length() = m_end_offset + SizeofCRC(). + */ + ON__UINT64 Length() const; + + /* + Parameters: + current_position - [in] + Value of ON_BinaryArchive.CurrentPosition() + + Returns: + Number of bytes that can be read when ON_BinaryArchive ReadMode() is true. + */ + ON__UINT64 LengthRemaining( + ON__UINT64 current_position + ) const; + + /* + Returns: + 0: no CRC + 4: 32 bit CRC (4 bytes) + 2: 16 bit CRC (2 bytes) + */ + ON__UINT64 SizeofCRC() const; + + ON__INT64 m_big_value=0; + ON__UINT32 m_typecode=0; + ON__UINT8 m_bLongChunk=0; // true if chunk is a long chunk and m_big_value is a length. + +private: + ON__UINT8 m_reserved1=0; + ON__UINT8 m_reserved2=0; + ON__UINT8 m_reserved3=0; + +public: + // CRC settings + ON__UINT8 m_do_crc16=0; // true (1) if we are calculating 16 bit CRC + ON__UINT8 m_do_crc32=0; // true (1) if we are calculating 32 bit CRC + ON__UINT16 m_crc16=0; // current 16 bit CRC value + ON__UINT32 m_crc32=0; // current 32 bit CRC value +}; + +bool ON_IsLongChunkTypecode(ON__UINT32 typecode); + +bool ON_IsShortChunkTypecode(ON__UINT32 typecode); + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +#endif + +// Used int ON_3dmProperties::Read() to set ON_BinaryArchive.m_3dm_opennurbs_version +// Do not call directly. +void ON_SetBinaryArchiveOpenNURBSVersion(ON_BinaryArchive&,unsigned int); + +class ON_CLASS ON_UserDataItemFilter +{ +public: + ON_UserDataItemFilter(); + + ON_UserDataItemFilter( + ON_UUID application_id, + bool bSerialize + ); + + ON_UserDataItemFilter( + ON_UUID application_id, + ON_UUID item_id, + bool bSerialize + ); + + static int Compare( + const class ON_UserDataItemFilter*, + const class ON_UserDataItemFilter* + ); + + // The application id can be the id for a plug-in, Rhino or opennurbs + ON_UUID m_application_id; + + // The item id for object user data is the value of ON_UserData.m_userdata_uuid. + // The item id for user table is the application id. + // A nil item id indicates the setting is applied to all object user data + // and user table information for the specified application. + ON_UUID m_item_id; + + // If application id and item id match and m_bSerializeEnabled, + // does not match, then the ON_UserDataItemFilter with the + // largest value of m_precedence is used. + unsigned int m_precedence; + + // bSerializationEnabled is true if reading and writing are permitted. + // bSerializationEnabled is false if reading and writing are prevented. + bool m_bSerialize; +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +#endif + +class ON_CLASS ON_ComponentManifest +{ +public: + // The default constructor would work prfectly, + // except there is a bug in Apple's CLANG that + // requires either an explicitly implemented constructor + // or an explicitly implemented copy constructor together + // with a hack to initialize the static ON_ComponentManifest::Empty. + // Apple CLANG BUG // ON_ComponentManifest() = default; + ON_ComponentManifest() ON_NOEXCEPT; + + ~ON_ComponentManifest(); + + static const ON_ComponentManifest Empty; + + void Reset(); + + enum : int + { + UnsetComponentIndex = ON_UNSET_INT_INDEX + }; + +private: + ON_ComponentManifest(const ON_ComponentManifest&) = delete; + ON_ComponentManifest& operator=(const ON_ComponentManifest&) = delete; + +public: + + /* + Total number of items in the manifest, including items referencing system components and deleted items. + */ + unsigned int ItemCount() const; + + /* + Parameters: + component_type - [in] + If component_type is ON_ModelComponent::Type::Unset or ON_ModelComponent::Type::Mixed, + then the every explict component type is counted. + Returns: + Total number of model components of the specified type in this manifest. + Remarks: + The count includes active, deleted, and system components. + */ + unsigned int TotalComponentCount( + ON_ModelComponent::Type component_type + ) const; + + /* + Parameters: + component_type - [in] + If component_type is ON_ModelComponent::Type::Unset or ON_ModelComponent::Type::Mixed, + then the every explict component type is counted. + Returns: + Number of model components of the specified type in this manifest. + Remarks: + The count includes active and deleted components. + The count does not include system components (those added by calling AddSystemComponentToManifest()). + */ + unsigned int ActiveAndDeletedComponentCount( + ON_ModelComponent::Type component_type + ) const; + + /* + Parameters: + component_type - [in] + If component_type is ON_ModelComponent::Type::Unset or ON_ModelComponent::Type::Mixed, + then the every explict component type is counted. + Returns: + Number of active model components of the specified type in this manifest. + Remarks: + The count does not include deleted components (IsDeleted() = true). + The count does not include system components (those added by calling AddSystemComponentToManifest()). + */ + unsigned int ActiveComponentCount( + ON_ModelComponent::Type component_type + ) const; + + /* + Parameters: + component_type - [in] + If component_type is ON_ModelComponent::Type::Unset or ON_ModelComponent::Type::Mixed, + then the every explict component type is counted. + Returns: + Number of model components of the specified type in this manifest that have IsDeleted() = true. + Remarks: + System components cannot be deleted. + */ + unsigned int DeletedComponentCount( + ON_ModelComponent::Type component_type + ) const; + + unsigned int SystemComponentCount( + ON_ModelComponent::Type component_type + ) const; + + /* + Parameters: + component_type - [in] + Returns: + If the component type is indexed, then all current manifest indices + for the component_type are >= 0 and < ComponentIndexLimit(). + Otherwise 0 is returned. + */ + int ComponentIndexLimit( + ON_ModelComponent::Type component_type + ) const; + + /* + Description: + Add a component to this manifest. + If the id is not set or not unique, the component will not be added. + If a unique name is required and the name is not set or not unique, + the component will not be added. + Parameters: + component - [in] + If you want to update the component id, index and name values to + match the ones assigned in the manifest, then call + component.SetIdentification(manifest_item), + where manifest_item is the information returned by this function. + bResolveIdAndNameCollisions - [in] + If false, then the component parameter id must not be used in the + manifest and, when required, the name must be set and unique. + If true and a new id or name is required, one will be assigned. + Note that the component parameter is const and its id and name + are not modified. + assigned_name - [out] + If not null, the assigned name is returned here. + Returns: + If an item is added to this manifest, then the assigned + identification information is returned. + Otherwise ON_ComponentManifestItem::Unset is returned. + Note the manifest index is generally different from component.Index(). + Remarks: + Use + */ + const class ON_ComponentManifestItem& AddComponentToManifest( + const class ON_ModelComponent& component, + bool bResolveIdAndNameCollisions, + ON_wString* assigned_name + ); + + const class ON_ComponentManifestItem& AddSystemComponentToManifest( + const class ON_ModelComponent& component + ); + + + /* + Description: + Add a component to this manifest. + Parameters: + component_type - [in] + Type of component. + component_serial_number - [in] + 0 or the component's unique runtime serial number (ON_ModelComponent::RuntimeSerialNumber()). + component_id - [in] + component_name_hash - [in] + If the the component type requires a unique name and the name + is not valid or in use, the component will not be added. + Returns: + If an item is added to this manifest, then the identification + information is returned. + Otherwise ON_ComponentManifestItem::Unset is returned. + Note: + The manifest index is assigned to components that require an index. + */ + const class ON_ComponentManifestItem& AddComponentToManifest( + ON_ModelComponent::Type component_type, + ON__UINT64 component_serial_number, + ON_UUID component_id, + const ON_NameHash& component_name_hash + ); + + /* + Description: + Add a component to this manifest. + If the id is not set or in use, then a new one will be assigned. + If the component type requires a unique name and the name is not set or in use, + then a new one will be assigned. + Parameters: + component_type - [in] + Type of component. + component_serial_number - [in] + 0 or the component's unique runtime serial number (ON_ModelComponent::RuntimeSerialNumber()). + component_id - [in] + If the id is nil or in use, a new id will be assigned. + component_name_hash - [in] + If the the component type requires a unique name and the name + is not valid or in use, the component will not be added. + original_name - [in/out] + If a new name needs to be assigned, the input value will be used + as a candidate and then as the root. Passing in the current name + is a good choice. The output value is the final assigned name. + Returns: + If an item is added to this manifest, then the identification + information is returned. + Otherwise ON_ComponentManifestItem::Unset is returned. + */ + const class ON_ComponentManifestItem& AddComponentToManifest( + ON_ModelComponent::Type component_type, + ON__UINT64 component_serial_number, + ON_UUID component_parent_id, + ON_UUID component_id, + const ON_NameHash& component_name_hash, + const wchar_t* candidate_name, + ON_wString& assigned_name + ); + + const class ON_ComponentManifestItem& AddComponentToManifest( + ON_ModelComponent::Type component_type, + ON__UINT64 component_serial_number, + ON_UUID component_parent_id, + ON_UUID component_id, + const wchar_t* original_name, + ON_wString& assigned_name + ); + + + /* + Description: + Modify a manifest items's component name + Parameters: + item_id - [in] + Identifies the manifest item to modify. + component_parent_id - [in] + ON_ModelComponent.ParentId() value. + When ON_ModelComponent::UniqueNameIncludesParent(component_type) is true, + it is critical that component_parent_id be set correctly. + name - [in] + new name + Returns: + True if name was modified. + */ + const class ON_ComponentManifestItem& ChangeComponentName( + ON_UUID item_id, + ON_ModelComponent::Type component_type, + ON_UUID component_parent_id, + const wchar_t* component_name + ); + + /* + Description: + Modify a manifest items's component name + Parameters: + component - [in] + The component that is in the manifest with the new name set. + Returns: + True if name was modified. + */ + const class ON_ComponentManifestItem& ChangeComponentName( + const class ON_ModelComponent& component + ); + + /* + Description: + A function for expert users to directly set the + component's name hash. Generally, it is better + to use the ChangeComponentName() functions. + Parameters: + item_id - [in] + Identifies the manifest item to modify. + component_name_hash - [in] + new name hash + */ + const class ON_ComponentManifestItem& ChangeComponentNameHash( + ON_UUID item_id, + const ON_NameHash& component_name_hash + ); + + /* + Description: + Modify a manifest items's component m_component_runtime_serial_number, + m_original_index, m_original_id, and m_name_hash values. + Parameters: + manifest_id - [in] + identifies the manifest item to modify + component_runtime_serial_number - [in] + */ + const class ON_ComponentManifestItem& ChangeComponentRuntimeSerialNumber( + ON_UUID item_id, + ON__UINT64 component_runtime_serial_number + ); + + /* + Description: + Set a component's status to deleted. + */ + const class ON_ComponentManifestItem& DeleteComponent( + ON_UUID item_id + ); + + const class ON_ComponentManifestItem& DeleteComponent( + ON__UINT64 component_runtime_serial_number + ); + + /* + Description: + Undelete a previously deleted component. + */ + const class ON_ComponentManifestItem& UndeleteComponent( + ON_UUID item_id, + ON_UUID parent_id, + const wchar_t* candidate_name, + ON_wString& assigned_name + ); + + /* + Description: + Undelete a previously deleted component with the same id and + change the serial number to new_component_runtime_serial_number. + Remarks: + Often when an object is modified, the original and new + object have the same id but different serial numbers. The original is + deleted. When the item is undeleted for the object, the runtime + serial number needs to be udated. + */ + const class ON_ComponentManifestItem& UndeleteComponentAndChangeRuntimeSerialNumber( + ON_UUID item_id, + ON_UUID parent_id, + ON__UINT64 new_component_runtime_serial_number, + const wchar_t* candidate_name, + ON_wString& assigned_name + ); + + bool RemoveComponent( + const ON_ModelComponent& component + ); + + bool RemoveComponent( + ON__UINT64 component_runtime_serial_number + ); + + bool RemoveComponent( + ON_UUID item_id + ); + + bool RemoveIndexedComponent( + ON_ModelComponent::Type component_type, + int item_index + ); + + bool RemoveAllComponents( + ON_ModelComponent::Type component_type, + bool bResetManifestIndex + ); + + /* + Description: + Get a name that is currently not used in this manifest as either a component + or manifest name. + Parameters: + component_type - [in] + ON_ModelComponent::ComponentTypeIsValidAndNotMixed(component_type) must be true. + component_parent_id - [in] + If ON_ModelComponent::UniqueNameIncludesParent(component_type) is true and + candidate_name is not empty, then the component parent id must be accurate. + This is the case for ON_Layer names. + Otherwise, you may pass ON_nil_uuid. + candidate_name - [in] + If candidate_name is a valid and not it use, + then unused_component_name = candidate_name. + If ON_ModelComponent::UniqueNameIncludesParent(component_type) is true and + candidate_name is not empty, then component_parent_id must be accurate. + This is the case for ON_Layer names. + base_name - [in] + If base_name is empty or not valid, + then ON_ModelComponent::ComponentTypeToString(component_type) is used as base_name + suffix_separator - [in] + empty or the string to place between base_name and the suffix when searching for an + unsued name. + suffix0 - [in] + If a suffix needs to be appended, the search for a + unused name begins with the suffix values suffix0+1. + suffix_value - [out] + If nullptr != suffix_value, the value used to generate the + unique name suffix is returned. + Returns: + An component name that is not used in this manifest. + Remarks: + If candidate_name could not be used, then it has the form + base_name + suffix_separator + X, where X is an integer > suffix0. + */ + const ON_wString UnusedName( + ON_ModelComponent::Type component_type, + ON_UUID component_parent_id, + const wchar_t* candidate_name, + const wchar_t* base_name, + const wchar_t* suffix_separator, + unsigned int suffix0, + unsigned int* suffix_value + ) const; + + /* + Description: + Get a name that is currently not used in this manifest as either a component + or manifest name. + Parameters: + model_component - [in] + The component type, id, parent id, and candidate name parameters for the + more complicated version of UnusedName() are taken from this parameter. + Returns: + An component name that is not used in this manifest. + Remarks: + If candidate_name could not be used, then it has the form + base_name + suffix_separator + X, where X is an integer > suffix0. + */ + const ON_wString UnusedName( + const ON_ModelComponent& model_component + ) const; + + /* + Parameters: + component_type - [in] + ON_ModelComponent::ComponentTypeIsValidAndNotMixed(component_type) + must be true or false will be returned. + candidate_name_hash - [in] + candidate_name_hash.IsValidAndNotEmpty() + must be true or false will be returned. + Returns: + True if the candidate_name_hash a hash of a valid, non-empty name and the + name is currently not used as either a component or manifest name value. + */ + bool NameIsAvailable( + ON_ModelComponent::Type component_type, + const ON_NameHash& candidate_name_hash + ) const; + + /* + Description: + Get an id that is not currently used in this manifest + Parameters: + component_type - [in] + ON_ModelComponent::ComponentTypeIsValidAndNotMixed(component_type) must be true. + candidate_id + If candidate_id is valid component id and not in use, + then its value is returned. + Returns: + An id that is valid and currently not used in this ON_Manifest as + either a component or a manifest id value. + Remarks: + If candidate_id cannot be used, then ON_CreateId() is used to create a new id. + */ + ON_UUID UnusedId( + ON_UUID candidate_id + ) const; + + /* + Returns: + True if the id is valid and currently not used in this ON_Manifest as + either a component or a manifest id value. + */ + bool IdIsAvailable( + ON_UUID id + ) const; + + ////////////////////////////////////////////////////////////////// + // + // Query tools to get item identificaion information + // + // + const class ON_ComponentManifestItem& ItemFromId( + ON_UUID item_id + ) const; + + const class ON_ComponentManifestItem& ItemFromComponentRuntimeSerialNumber( + ON__UINT64 component_runtime_serial_number + ) const; + + /* + Description: + Returns the item if it has the required component type and id. + Remarks: + Every item has a unique manifest id. The component_type + parameter is provided if an additional check needs to be + made on component type. + */ + const class ON_ComponentManifestItem& ItemFromId( + ON_ModelComponent::Type component_type, + ON_UUID item_id + ) const; + + /* + Parameters: + component_type - [in] + model_component - [in] + The value of ON_ModelComponent::UniqueNameIgnoresCase(component_type) must be used + when creating the name hash (group names are case sensitive). + */ + const class ON_ComponentManifestItem& ItemFromName( + const class ON_ModelComponent* model_component + ) const; + + /* + Parameters: + component_type - [in] + parent_id - [in] + If ON_ModelComponent::UniqueNameIncludesParent(component_type) is true, + then the parent_id must be used to calculate the name hash + (layer names require parent ids). + */ + const class ON_ComponentManifestItem& ItemFromName( + ON_ModelComponent::Type component_type, + ON_UUID parent_id, + const wchar_t* name + ) const; + + /* + Parameters: + component_type - [in] + component_name_hash - [in] + The value of ON_ModelComponent::UniqueNameIgnoresCase(component_type) must be used + when creating the name hash (group names are case sensitive). + + If ON_ModelComponent::UniqueNameIncludesParent(component_type) is true, + then the parent_id must be used to calculate the name hash + (layer names require parent ids). + */ + const class ON_ComponentManifestItem& ItemFromNameHash( + ON_ModelComponent::Type component_type, + const ON_NameHash& component_name_hash + ) const; + + const class ON_ComponentManifestItem& ItemFromIndex( + ON_ModelComponent::Type component_type, + int item_index + ) const; + + const class ON_ComponentManifestItem& ItemFromUnsignedIndex( + ON_ModelComponent::Type component_type, + unsigned int unsigned_item_index + ) const; + + const class ON_ComponentManifestItem& SystemItemFromNameHash( + ON_ModelComponent::Type component_type, + const ON_NameHash& system_item_name_hash + ) const; + + const class ON_ComponentManifestItem& SystemItemFromIndex( + ON_ModelComponent::Type component_type, + int system_item_index + ) const; + + const class ON_ComponentManifestItem* FirstItem( + ON_ModelComponent::Type component_type + ) const; + + const class ON_ComponentManifestItem* LastItem( + ON_ModelComponent::Type component_type + ) const; + + /* + Returns: + Next item in the manifest with the same component type. + */ + const class ON_ComponentManifestItem* NextItem( + const class ON_ComponentManifestItem* item + ) const; + + /* + Returns: + Previous item in the manifest with the same component type. + */ + const class ON_ComponentManifestItem* PreviousItem( + const class ON_ComponentManifestItem* item + ) const; + + /* + Returns: + Next item in the manifest with the same component type. + */ + const class ON_ComponentManifestItem* NextItem( + ON_UUID manifest_item_id + ) const; + + /* + Returns: + Previous item in the manifest with the same component type. + */ + const class ON_ComponentManifestItem* PreviousItem( + ON_UUID manifest_item_id + ) const; + + /* + Description: + This number is incremented every time the manifest changes. + */ + ON__UINT64 ManifestContentVersionNumber() const; + +private: + const class ON_ComponentManifestItem* Internal_AddItem( + class ON_ComponentManifestItem& item, + ON_UUID component_parent_id, + bool bResolveIdAndNameCollisions, + const wchar_t* candidate_name, + ON_wString* assigned_name + ); + +private: + class ON_ComponentManifestImpl* Impl() const; + mutable class ON_ComponentManifestImpl* m_impl = nullptr; +}; + +class ON_CLASS ON_ComponentManifestItem +{ +public: + static const ON_ComponentManifestItem UnsetItem; + + static int CompareComponentType( + const ON_ComponentManifestItem* a, + const ON_ComponentManifestItem* b + ); + + static int CompareId( + const ON_ComponentManifestItem*const* a, + const ON_ComponentManifestItem*const* b + ); + + static int CompareNameHash( + const ON_ComponentManifestItem*const* a, + const ON_ComponentManifestItem*const* b + ); + + static int CompareIndex( + const ON_ComponentManifestItem*const* a, + const ON_ComponentManifestItem*const* b + ); + +public: + // Assigns component type, index, id and name hash + ON_ComponentManifestItem( + const class ON_ModelComponent& component + ); + + ON_ComponentManifestItem( + const class ON_ModelComponent& component, + const ON_UUID& manifest_id, + const class ON_NameHash& manifest_name_hash + ); + + ON_ComponentManifestItem( + ON_ModelComponent::Type component_type, + ON__UINT64 m_component_runtime_serial_number, + const ON_UUID& manifest_id, + const class ON_NameHash& manifest_name_hash + ); + + ON_ComponentManifestItem( + const class ON_ModelComponent& component, + int manifest_index, + const ON_UUID& manifest_id, + const class ON_NameHash& manifest_name_hash + ); + + ON_ComponentManifestItem( + ON_ModelComponent::Type component_type, + ON__UINT64 m_component_runtime_serial_number, + int manifest_index, + const ON_UUID& manifest_id, + const class ON_NameHash& manifest_name_hash + ); + + ON_ComponentManifestItem() = default; + ~ON_ComponentManifestItem() = default; + ON_ComponentManifestItem(const ON_ComponentManifestItem&) = default; + ON_ComponentManifestItem& operator=(const ON_ComponentManifestItem&) = default; + +public: + /* + Returns: + true if m_component_type is not ON_ModelComponent::Type::Unset + and the m_manifest_id is not nil. + */ + bool IsValid() const; + + /* + Returns: + true if m_component_type is ON_ModelComponent::Type::Unset + or the m_manifest_id is nil. + */ + bool IsUnset() const; + + /* + Returns: + true if the item is in a deleted state. + Name is erased. + The component can be found by component serial number, id, or index. + */ + bool IsDeleted() const; + + /* + Returns: + true if the item is a constant system component. + */ + bool IsSystemComponent() const; + +public: + /* + Return: + item component type. ON_ModelComponent::Type::Unset if it is not set. + */ + ON_ModelComponent::Type ComponentType() const; + + void SetComponentType( + ON_ModelComponent::Type component_type + ); + +public: + /* + Return: + item id. ON_nil_uuid if is not set. + */ + ON_UUID Id() const; + + void SetId( + ON_UUID id + ); + +public: + /* + Return: + item component runtime serial number. 0 if it is not set. + */ + ON__UINT64 ComponentRuntimeSerialNumber() const; + + void SetComponentRuntimeSerialNumber( + ON__UINT64 component_runtime_serial_number + ); + +public: + /* + Return: + item name hash. ON_NameHash::UnsetNameHash if is not set. + */ + const ON_NameHash& NameHash() const; + + void SetNameHash( + const ON_NameHash& name_hash + ); + +public: + /* + Return: + item index. ON_UNSET_INT_INDEX if it is not set. + */ + int Index() const; + + void SetIndex( + int index + ); + +private: + friend class ON_ComponentManifestImpl; + + void Internal_SetDeletedState( + bool bDeleted + ); + +private: + ON__UINT32 m_status_bits = 0; + ON_ModelComponent::Type m_component_type = ON_ModelComponent::Type::Unset; + ON__UINT8 m_reserved1 = 0; + ON__UINT16 m_reserved2 = 0; + ON__UINT32 m_reserved3 = 0; + int m_index = ON_UNSET_INT_INDEX; + ON__UINT64 m_component_runtime_serial_number = 0; + ON_UUID m_id = ON_nil_uuid; + ON_NameHash m_name_hash = ON_NameHash::UnsetNameHash; +}; + +class ON_CLASS ON_ManifestMapItem +{ +public: + ON_ManifestMapItem() = default; + ~ON_ManifestMapItem() = default; + ON_ManifestMapItem(const ON_ManifestMapItem&) = default; + ON_ManifestMapItem& operator=(const ON_ManifestMapItem&) = default; + +public: + static const ON_ManifestMapItem Unset; + + /* + Description: + Compares type, indices and ids. + */ + static int Compare( + const ON_ManifestMapItem& a, + const ON_ManifestMapItem& b + ); + + static int CompareTypeAndSourceId( + const ON_ManifestMapItem& a, + const ON_ManifestMapItem& b + ); + + static int CompareTypeAndDestinationId( + const ON_ManifestMapItem& a, + const ON_ManifestMapItem& b + ); + + static int CompareTypeAndSourceIdAndIndex( + const ON_ManifestMapItem& a, + const ON_ManifestMapItem& b + ); + + static int CompareTypeAndDestinationIdAndIndex( + const ON_ManifestMapItem& a, + const ON_ManifestMapItem& b + ); + + static int CompareTypeAndSourceIndex( + const ON_ManifestMapItem& a, + const ON_ManifestMapItem& b + ); + + static int CompareTypeAndDestinationIndex( + const ON_ManifestMapItem& a, + const ON_ManifestMapItem& b + ); + + /* + Description: + 32-bit hash for use in source id hash tables + */ + static ON__UINT32 SourceIdHash32( + const ON_UUID& source_component_id + ); + + /* + Description: + 32-bit hash for use in source index hash tables + */ + static ON__UINT32 SourceIndexHash32( + ON_ModelComponent::Type component_type, + int source_component_index + ); + + /* + Returns: + True if + m_component_type is not ON_ModelComponent::Type::Unset + and m_source_component_id is not nil + and m_destination_component_id is not nil + and no index is required or m_source_component_index and m_destination_component_index + are not ON_UNSET_INT_INDEX. + */ + bool SourceAndDestinationAreSet() const; + + bool SourceOrDestinationIsUnset() const; + + /* + Returns: + True if + m_component_type is not ON_ModelComponent::Type::Unset + and m_source_component_id is not nil + and no index is required or m_source_component_index is not ON_UNSET_INT_INDEX. + */ + bool SourceIsSet() const; + + bool SourceIsUnset() const; + + /* + Returns: + True if + m_component_type is not ON_ModelComponent::Type::Unset + and m_destination_component_id is not nil + and no index is required or m_destination_component_index is not ON_UNSET_INT_INDEX. + */ + bool DestinationIsSet() const; + + bool DestinationIsUnset() const; + + /* + Returns: + True if destination_manifest contains a manifest item that matches + m_component_type, m_destination_component_id, and m_destination_component_index. + */ + bool DestinationInManifest( + const ON_ComponentManifest& destination_manifest + ) const; + + /* + Returns: + True if destination_manifest contains a manifest item that matches + m_component_type, m_source_component_id, and m_source_component_index. + */ + bool SourceInManifest( + const ON_ComponentManifest& source_manifest + ) const; + + ON_ManifestMapItem SwapSourceAndDestiation() const; + + ON_ModelComponent::Type ComponentType() const; + const ON_UUID& SourceId() const; + const ON_UUID& DestinationId() const; + int SourceIndex() const; + int DestinationIndex() const; + + bool ClearSourceIdentification(); + + bool ClearDestinationIdentification(); + + /* + Description: + Set type and source identification. + Parameters: + component_type - [in] + source_id - [in] + source_index - [in] + Returns: + True if set. + False destination type is set and different from component_type. + */ + bool SetSourceIdentification( + ON_ModelComponent::Type component_type, + ON_UUID source_id, + int source_index + ); + + /* + Description: + Set type and destination identification. + Parameters: + component_type - [in] + source_id - [in] + source_index - [in] + Returns: + True if set. + False destination type is set and different from component_type. + */ + bool SetDestinationIdentification( + ON_ModelComponent::Type component_type, + ON_UUID destination_id, + int destination_index + ); + + /* + Description: + Set type and source identification to model_component identification. + Parameters: + model_component - [in] + Returns: + True if set. + False destination type is set and different from model_component->ComponentType(). + */ + bool SetSourceIdentification( + const class ON_ModelComponent* model_component + ); + + /* + Description: + Set type and destination identification to model_component identification. + Parameters: + model_component - [in] + Returns: + True if set. + False source type is set and different from model_component->ComponentType(). + */ + bool SetDestinationIdentification( + const class ON_ModelComponent* model_component + ); + + /* + Description: + Set type and source identification to manifest_item identification. + Parameters: + manifest_item - [in] + Returns: + True if set. + False destination type is set and different from manifest_item->ComponentType(). + */ + + bool SetSourceIdentification( + const class ON_ComponentManifestItem* manifest_item + ); + + /* + Description: + Set type and destination identification to manifest_item identification. + Parameters: + manifest_item - [in] + Returns: + True if set. + False source type is set and different from manifest_item->ComponentType(). + */ + bool SetDestinationIdentification( + const class ON_ComponentManifestItem* manifest_item + ); + + /* + Description: + Copy type and source identification from map_item. + Parameters: + map_item - [in] + Returns: + True if set. + False destination type is set and different from map_item->ComponentType(). + */ + bool SetSourceIdentification( + const class ON_ManifestMapItem* map_item + ); + + /* + Description: + Copy type and destination identification from map_item. + Parameters: + map_item - [in] + Returns: + True if set. + False source type is set and different from map_item->ComponentType(). + */ + bool SetDestinationIdentification( + const class ON_ManifestMapItem* map_item + ); + +private: + bool Internal_SetSourceOrDestinationIdentification( + unsigned int which_identification, // 0 = source, 1 = destination + ON_ModelComponent::Type component_type, + ON_UUID id, + int index + ); + +private: + ON_ModelComponent::Type m_component_type = ON_ModelComponent::Type::Unset; +private: + unsigned int m_reserved = 0; +private: + int m_source_index = ON_UNSET_INT_INDEX; + int m_destination_index = ON_UNSET_INT_INDEX; +private: + ON_UUID m_source_id = ON_nil_uuid; + ON_UUID m_destination_id = ON_nil_uuid; +}; + +ON_DECL +bool operator==(const ON_ManifestMapItem& lhs,const ON_ManifestMapItem& rhs); + +ON_DECL +bool operator!=(const ON_ManifestMapItem& lhs,const ON_ManifestMapItem& rhs); + + +/* +Description: + ON_ManifestIdentificationMap is used to record a map from + a source manifest to a destination manifest when the index or id + values change. This is common when reading and writing archives + and when merging models. +*/ +class ON_CLASS ON_ManifestMap +{ +public: + // The default constructor would work prfectly, + // except there is a bug in Apple's CLANG that + // requires either an explicitly implemented constructor + // or an explicitly implemented copy constructor together + // with a hack to initialize the static ON_ComponentManifest::Empty. + // Apple CLANG BUG // ON_ManifestMap() = default; + ON_ManifestMap() ON_NOEXCEPT; + + ~ON_ManifestMap(); + ON_ManifestMap(const ON_ManifestMap&); + ON_ManifestMap& operator=(const ON_ManifestMap&); + +public: + static const ON_ManifestMap Empty; + +public: + bool AddMapItem( + const class ON_ManifestMapItem& map_item + ); + + /* + Parameters: + map_item - [in] + The source settings must exacty match source settings of an existing map. + The destination settings are the new values to assign. + Return: + True if a mapping was successfully updated (even when the destation settings did not change). + */ + bool UpdatetMapItemDestination( + const class ON_ManifestMapItem& map_item + ); + + /* + Parameters: + map_item - [in] + The source settings must exacty match source settings of an existing map. + The destination settings are the new values to assign. + bIgnoreSourceIndex - [in] + If true, the value of map_item.SourceIndex() is ignored. + Otherwise, it must exactly match the source index setting of an existing map. + Return: + True if a mapping was successfully updated (even when the destation settings did not change). + */ + bool UpdatetMapItemDestination( + const class ON_ManifestMapItem& map_item, + bool bIgnoreSourceIndex + ); + + const class ON_ManifestMapItem& MapItemFromSourceId( + const ON_UUID& source_item_id + ) const; + + const class ON_ManifestMapItem& MapItemFromSourceIndex( + ON_ModelComponent::Type component_type, + int source_component_index + ) const; + + bool GetAndValidateDestinationIndex( + ON_ModelComponent::Type component_type, + int source_component_index, + const ON_ComponentManifest& destination_manifest, + int* destination_component_index + ) const; + + bool GetAndValidateDestinationIndex( + ON_ModelComponent::Type component_type, + const ON_UUID& source_component_id, + const ON_ComponentManifest& destination_manifest, + int* destination_component_index + ) const; + + bool GetAndValidateDestinationId( + ON_ModelComponent::Type component_type, + const ON_UUID& source_component_id, + const ON_ComponentManifest& destination_manifest, + ON_UUID* destination_component_id + ) const; + + /* + Returns: + True if there are no ON_ManifestMapItem elements. + */ + bool IsEmpty() const; + + /* + Returns: + True if there is at least one ON_ManifestMapItem element. + */ + bool IsNotEmpty() const; + + /* + Returns: + Number of map items. + Remarks: + Some of these items may not change id or index. + */ + unsigned int MapItemCount() const; + +private: + class ON_ManifestMapImpl* Impl(); + class ON_ManifestMapImpl* m_impl = nullptr; +}; + + +enum class ON_3dmArchiveTableType : unsigned int +{ + // The values of the table_type enums must increase in the order + // the corresponding tables appear in well formed 3dm archives + // and the bitwise or of distinct values must be zero because + // bitfield filters are used in some reading operations. + + Unset = 0, + + // First section in any 3dm archive. + start_section = 0x00000001U, + + properties_table = 0x00000002U, + settings_table = 0x00000004U, + bitmap_table = 0x00000008U, + texture_mapping_table = 0x00000010U, + material_table = 0x00000020U, + linetype_table = 0x00000040U, + layer_table = 0x00000080U, + group_table = 0x00000100U, + text_style_table = 0x00000200U, + leader_style_table = 0x00000400U, + dimension_style_table = 0x00000800U, + light_table = 0x00001000U, + hatchpattern_table = 0x00002000U, + instance_definition_table = 0x00004000U, + object_table = 0x00008000U, + historyrecord_table = 0x00010000U, + user_table = 0x00020000U, + + // Last section in any 3dm archive. + end_mark = 0x40000000U +}; + + +/* +Description: + Context for an annotation object. This context is required when + converting current annotation objects to and from formats used + in earlier versions and is typically used when reading and + writing 3dm archives. +*/ +class ON_CLASS ON_3dmAnnotationContext +{ +public: + ON_3dmAnnotationContext() = default; + ~ON_3dmAnnotationContext(); + ON_3dmAnnotationContext(const ON_3dmAnnotationContext&); + ON_3dmAnnotationContext& operator=(const ON_3dmAnnotationContext&); + +public: + static const ON_3dmAnnotationContext Default; + +public: + ON::active_space ViewContext() const; + + void SetViewContext( + ON::active_space + ); + + ON::LengthUnitSystem ModelLengthUnitSystem() const; + + void SetModelLengthUnitSystem( + ON::LengthUnitSystem model_length_unit_system + ); + + ON::LengthUnitSystem PageLengthUnitSystem() const; + + void SetPageLengthUnitSystem( + ON::LengthUnitSystem page_length_unit_system + ); + + const class ON_3dmAnnotationSettings& AnnotationSettings() const; + + /* + Parameters: + annotation_settings - [in] + Annotation settings that are externally managed and will exist + during the lifetime of the ON_3dmAnnotationContext class instance. + */ + void SetReferencedAnnotationSettings( + const class ON_3dmAnnotationSettings* annotation_settings + ); + + /* + Parameters: + annotation_settings - [in] + A copy of annotation_settings is stored and manged by the ON_3dmAnnotationContext class instance. + */ + void SetManagedAnnotationSettings( + const class ON_3dmAnnotationSettings& annotation_settings + ); + + /* + Returns: + True if the annotation settings have been explicitly set. + */ + bool AnnotationSettingsAreSet() const; + + /* + This is the dimstyle the annotation object is question is using. + It can be a "base" dimstyle from the dimstyle table or an + "override" style attached used by a single instance of an annnotation + object. + */ + const class ON_DimStyle& DimStyle() const; + + const class ON_DimStyle& ParentDimStyle() const; + + /* + Parameters: + dim_style - [in] + A dimension style that is externally managed and will exist + during the lifetime of the ON_3dmAnnotationContext class instance. + */ + void SetReferencedDimStyle( + const class ON_DimStyle* parent_dim_style, + const class ON_DimStyle* override_dim_style, + int V5_3dm_archive_index + ); + + /* + Parameters: + dim_style - [in] + A copy of a dim_style is stored and manged by the ON_3dmAnnotationContext class instance. + */ + void SetManagedDimStyle( + const class ON_DimStyle& parent_dim_style, + const class ON_DimStyle* override_dim_style, + int V5_3dm_archive_index + ); + + void UpdateReferencedDimStyle( + const class ON_DimStyle* old_pointer, + const class ON_DimStyle* new_pointer + ); + + /* + Returns: + True if the dimension style has been explicitly set. + */ + bool DimStyleIsSet() const; + + /* + Returns: + If the dimstyle is not set or it has a nil parent id, then DimStyleId() is returned. + Otherwise the parent id is returned. + */ + ON_UUID ParentDimStyleId() const; + + /* + Returns: + 3dm archive dimension style table index to use when writing a V5 3dm archive. + This is often different from DimStyle().Index(). + */ + int V5_ArchiveDimStyleIndex() const; + + /* + Parameters: + bRequireSetOverrides - [in] + true if explicit overrides are required. + Returns: + true if the context dim style is an override style (parent id is not nil) and + it has overrides or bRequireSetOverrides is false. + */ + bool IsOverrideDimStyle() const; + + const class ON_BinaryArchive* BinaryArchive() const; + + /* + Parameters: + binary_archive - [in] + Binary archive that is externally managed and will exist + during the lifetime of the ON_3dmAnnotationContext class instance. + */ + void SetReferencedBinaryArchive( + const class ON_BinaryArchive* binary_archive + ); + + /* + Returns: + True if the the target binary archive is set. + */ + bool BinaryArchiveIsSet() const; + +private: + const class ON_BinaryArchive* m_binary_archive = nullptr; + + // V6 table dimstyle. If an override dimstyle is in use, + // this is the "parent dimstyle" referenced by the override. + const class ON_DimStyle* m_parent_dim_style = nullptr; + class ON_DimStyle* m_managed_parent_dim_style = nullptr; + + const class ON_DimStyle* m_override_dim_style = nullptr; + class ON_DimStyle* m_managed_override_dim_style = nullptr; + + const class ON_3dmAnnotationSettings* m_annotation_settings = nullptr; + class ON_3dmAnnotationSettings* m_managed_annotation_settings = nullptr; + ON::active_space m_view_context = ON::active_space::no_space; + ON::LengthUnitSystem m_model_length_unit_system = ON::LengthUnitSystem::None; + ON::LengthUnitSystem m_page_length_unit_system = ON::LengthUnitSystem::None; + + // V5 archive dim style index + int m_V5_3dm_archive_dim_style_index = ON_UNSET_INT_INDEX; + +private: + void Internal_CopyFrom(const ON_3dmAnnotationContext& src); + void Internal_Destroy(); +}; + + +class ON_CLASS ON_3dmArchiveTableStatus +{ +public: + ON_3dmArchiveTableStatus() = default; + ~ON_3dmArchiveTableStatus() = default; + ON_3dmArchiveTableStatus(const ON_3dmArchiveTableStatus&) = default; + ON_3dmArchiveTableStatus& operator=(const ON_3dmArchiveTableStatus&) = default; + + static const ON_3dmArchiveTableStatus Unset; + + ON_3dmArchiveTableType m_table_type = ON_3dmArchiveTableType::Unset; + + // number of table items + unsigned int m_item_count = 0; + + // Number of crc errors found during archive reading. + // If > 0, then the archive is corrupt. See the table + // status information below to determine where the + // errors occured. + unsigned int m_crc_error_count = 0; + + // Number of other types of serious errors found during archive reading + // or writing. + // If > 0, then the archive is corrupt. See the table status information + // below to determine where the errors occured. + unsigned int m_critical_error_count = 0; + + // Number of other types of serious errors found during archive reading. + // If > 0, then the archive is corrupt. See the table status information + // below to determine where the errors occured. + unsigned int m_recoverable_error_count = 0; + + enum class TableState : unsigned int + { + Unset = 0U, + Started = 1U, // began to read the table + InProgress = 2U, + Finished = 3U, // finished reading the table + NotFound = 4U // the table could not be located during reading + }; + + ON_3dmArchiveTableStatus::TableState m_state = ON_3dmArchiveTableStatus::TableState::Unset; +}; + +class ON_CLASS ON_BinaryArchive // use for generic serialization of binary data +{ +public: + ON_BinaryArchive( ON::archive_mode ); + virtual ~ON_BinaryArchive(); + +protected: + virtual + ON__UINT64 Internal_CurrentPositionOverride( // current offset (in bytes) into archive ( like ftell() ) + ) const = 0; + + virtual + bool Internal_SeekFromCurrentPositionOverride( // seek from current position ( like fseek( ,SEEK_CUR) ) + int // byte offset ( >= -CurrentPostion() ) + ) = 0; + + virtual + bool Internal_SeekToStartOverride( // seek from current position ( like fseek(0 ,SEEK_SET) ) + ) = 0; + +public: + /* + Returns: + True if current position is at the end of the archive. + */ + virtual + bool AtEnd() const = 0; + +public: + /* + Returns: + Number of bytes from start of archive to the current position. + */ + ON__UINT64 CurrentPosition() const; + + /* + Description: + Set current position to bytes_from_start many bytes from the start of the archive. + Parameters: + bytes_from_start - [in] + Returns: + True: successful + False: failure + Remarks: + Similar to fseek( ,SEEK_SET) + */ + bool SeekFromStart( + ON__UINT64 bytes_from_start + ); + + /* + Description: + Increase the archive's current position to bytes_forward from the current position. + Parameters: + bytes_forward - [in] + Returns: + True: successful + False: failure + */ + bool SeekForward( + ON__UINT64 bytes_forward + ); + + /* + Description: + Reduce the archive's current position by bytes_backward from the current position. + Parameters: + bytes_backward - [in] + Returns: + True: successful + False: failure + */ + bool SeekBackward( + ON__UINT64 bytes_backward + ); + +private: + bool Internal_SeekCur( + bool bFowrard, + ON__UINT64 offset + ); + +public: + + /* + Description: + Tool for swapping bytes when doing I/O on + using big endian CPUs. + Remarks: + 3dm files are always saved with little endian byte order. + See Also: + ON_BinaryArchive::Endian + */ + static + bool ToggleByteOrder( + size_t, // number of elements + size_t, // size of element (2,4, or 8) + const void*, // source buffer + void* // destination buffer (can be same a source buffer) + ); + + static + const char* TypecodeName( unsigned int tcode ); + + static + char* ON_TypecodeParse( unsigned int tcode, char* typecode_name, size_t max_length ); + + /* + Returns: + Endian-ness of the cpu reading this file. + Remarks: + 3dm files are always saved with little endian byte order. + */ + ON::endian Endian() const; // endian-ness of cpu + + bool ReadByte( size_t, void* ); // must fail if mode is not read or readwrite + + bool WriteByte( size_t, const void* ); // must fail if mode is not write or readwrite + + /* + Description: + Expert user function that uses Read() to load a buffer. + Paramters: + sizeof_buffer - [in] number of bytes to attempt to read. + buffer - [out] read bytes are stored in this buffer + Returns: + Number of bytes actually read, which may be less than + sizeof_buffer if the end of file is encountered. + */ + ON__UINT64 ReadBuffer( ON__UINT64 sizeof_buffer, void* buffer ); + + /* + Description: + Expert user function to control CRC calculation while reading and writing. + Typically this is used when seeking around and reading/writing information + in non-serial order. + Parameters: + bEnable - [in] + Returns: + Current state of CRC calculation. Use the returned value to restore the + CRC calculation setting after you are finished doing your fancy pants + expert IO. + */ + bool EnableCRCCalculation( bool bEnable ); + + // ReadCompressedBuffer()/WriteCompressedBuffer() use zlib 1.1.3 + // to inflate/deflate the data buffer. + // Care must be used to get an endian independent file. + // See ON_Mesh::Read()/ON_Mesh::Write() for an example of an endian + // independent use of compression. See also ToggleByteOrder() and Endian(). + // + // To read data archived by WriteCompressedBuffer( sizeof_buffer, buffer ) + // do something like: + // + // size_t sizeof_buffer = 0; + // ReadCompressedBufferSize(&sizeof_buffer); + // buffer = something with sizeof_buffer bytes. + // int bFailedCRC = false; + // bool ok = ReadCompressedBuffer( sizeof_buffer, buffer, &bFailedCRC ); + // + + + /* + Description: + Red the size of a compressed buffer. + Parameters: + sizeof__outbuffer - [out] size of the uncompressed buffer in bytes + Returns: + True if read was successful. + */ + bool ReadCompressedBufferSize( size_t* sizeof__outbuffer ); + + /* + Description: + Read compressed information from an archive and uncompress it. + Parameters: + sizeof__outbuffer - [in] size of the uncompressed buffer in bytes + outbuffer - [out] uncompressed buffer returned here + bFailedCRC - [out] true if cyclic redundancy check fails + on uncompressed buffer + + Example: + + size_t sizeof_buffer = 0; + ReadCompressedBufferSize(&sizeof_buffer); + buffer = ...; // something with sizeof_buffer bytes. + int bFailedCRC = false; + bool ok = ReadCompressedBuffer( sizeof_buffer, buffer, &bFailedCRC ); + + Returns: + True if read was successful. You need to check the value + of bFailedCRC to see if the information that was read is valid. + Remarks: + Write your archive write/read code as if compression is always enabled. + Do not vary what get written or read based on the value of UseBufferCompression(). + */ + bool ReadCompressedBuffer( + size_t sizeof__outbuffer, + void* outbuffer, + bool* bFailedCRC + ); + + /* + Description: + Compress buffer and write the compressed information to the archive. + Parameters: + sizeof__inbuffer - [in] size of the uncompressed buffer in bytes + inbuffer - [in] uncompressed buffer + Returns: + True if write was successful. + Remarks: + Write your archive write/read code as if compression is always enabled. + Do not vary what get written or read based on the value of UseBufferCompression(). + */ + bool WriteCompressedBuffer( + size_t sizeof__inbuffer, + const void* inbuffer + ); + + bool ReadBool( bool* ); + + bool ReadChar( // Read an array of 8 bit chars + size_t, // number of chars to read + char* + ); + bool ReadChar( // Read an array of 8 bit unsigned chars + size_t, // number of unsigned chars to read + unsigned char* + ); + bool ReadChar( // Read a single 8 bit char + char* + ); + bool ReadChar( // Read a single 8 bit unsigned char + unsigned char* + ); + + bool ReadShort( // Read an array of 16 bit shorts + size_t, // number of shorts to read + short* + ); + bool ReadShort( // Read an array of 16 bit unsigned shorts + size_t, // number of shorts to read + unsigned short* + ); + bool ReadShort( // Read a single 16 bit short + short* + ); + bool ReadShort( // Read a single 16 bit unsigned short + unsigned short* + ); + + bool ReadInt( // Read an array of 32 bit integers + size_t, // number of ints to read + int* + ); + bool ReadInt( // Read an array of 32 bit integers + size_t, // number of ints to read + unsigned int* + ); + bool ReadInt( // Read a single 32 bit integer + int* + ); + bool ReadInt( // Read a single 32 bit unsigned integer + unsigned int* + ); + + bool ReadBigInt( // Read an array of 64 bit integers + size_t, // number of ints to read + ON__INT64* + ); + bool ReadBigInt( // Read an array of 64 bit integers + size_t, // number of ints to read + ON__UINT64* + ); + bool ReadBigInt( // Read a single 64 bit integer + ON__INT64* + ); + bool ReadBigInt( // Read a single 64 bit unsigned integer + ON__UINT64* + ); + + bool ReadLong( // Read an array of 32 bit integers + size_t, // number of ints to read + long* + ); + bool ReadLong( // Read an array of 32 bit integers + size_t, // number of ints to read + unsigned long* + ); + bool ReadLong( // Read a single 32 bit integer + long* + ); + bool ReadLong( // Read a single 32 bit unsigned integer + unsigned long* + ); + bool ReadSize( // Read a single size_t + size_t* + ); + + bool ReadBigSize( size_t* ); // 64 bits + + bool ReadBigTime( time_t* ); // UCT seconds since 1 January 1970 (64 bits) + + + bool ReadFloat( // Read an array of floats + size_t, // number of floats + float* + ); + bool ReadFloat( // Read a single float + float* + ); + bool ReadDouble( // Read an array of IEEE doubles + size_t, // number of doubles + double* + ); + bool ReadDouble( // Read a single double + double* + ); + + bool ReadColor( + ON_Color& + ); + + bool ReadColor( + ON_4fColor& + ); + + bool ReadPoint ( + ON_2dPoint& + ); + bool ReadPoint ( + ON_3dPoint& + ); + bool ReadPoint ( + ON_4dPoint& + ); + bool ReadVector ( + ON_2dVector& + ); + bool ReadVector ( + ON_3dVector& + ); + + bool ReadBoundingBox(ON_BoundingBox&); + + bool ReadXform(ON_Xform&); + + bool ReadPlaneEquation(ON_PlaneEquation&); + + bool ReadPlane(ON_Plane&); + + bool ReadLine(ON_Line&); + + bool ReadArc(ON_Arc&); + + bool ReadCircle(ON_Circle&); + + bool ReadInterval( ON_Interval& ); + + bool ReadUuid( ON_UUID& ); + + bool ReadDisplayMaterialRef( ON_DisplayMaterialRef& ); + + bool ReadLinetypeSegment( ON_LinetypeSegment& ); + + // All times are stored in coordinated universal time + // ( a.k.a GMT, UTC ). Use ANSI C time() and gmtime() calls. + bool ReadTime( struct tm& ); + + /* + Parameters: + str_array_count - [out] + Number of elements in the string array. All ON_BinaryArchive string + WriteString() functions write a null terminator to the file and + the null terminator is included in the count. This means that + if a string has a non-zero element, then str_array_count >= 2. + Remarks: + Modify your code to use ReadStringUTF8ElementCount() when reading + UTF-8 encoded strings and ReadStringUTF16ElementCount() + when reading UTF-16 encoded strings. + */ + ON_DEPRECATED_MSG("Use either ReadStringUTF8ElementCount() or ReadStringUTF16ElementCount()") + bool ReadStringSize( + size_t* str_array_count + ); + + /* + Parameters: + string_utf8_element_count - [out] + Number of bytes in the string array. All ON_BinaryArchive string + WriteString() functions write a null terminator to the file and + the null terminator is included in string_element_count. This means + that if opennurbs wrote the string, either string_element_count = 0 + or string_element_count >= 2. + */ + bool ReadStringUTF8ElementCount( + size_t* string_utf8_element_count + ); + + /* + Parameters: + string_utf16_element_count - [out] + Number of elements in the string array. All ON_BinaryArchive string + WriteString() functions write a null terminator to the file and + the null terminator is included in string_element_count. This means + that if opennurbs wrote the string, either string_element_count = 0 + or string_element_count >= 2. + */ + bool ReadStringUTF16ElementCount( + size_t* string_utf16_element_count + ); + + + /* + Parameters: + str_array_count - [in] + Number of char elements in str_array[], including the null + terminator. The value of str_array_count is returned by + ReadCharStringElementCount(). + str_array - [in/out] + Pass in an array with at least str_array_count elements. + If true is returned and str_array_count > 0, + then str_array[str_array_count-1] = 0. All strings with + char elements written by Rhino are UTF-8 encoded + unicode strings. + */ + bool ReadString( + size_t str_array_count, + char* str_array + ); + + /* + Parameters: + str_array_count - [in] + Number of unsignd char elements in str_array[], including + the null terminator. The value of str_array_count is returned + by ReadCharStringElementCount(). + str_array - [in/out] + Pass in an array with at least str_array_count elements. + If true is returned and str_array_count > 0, + then str_array[str_array_count-1] = 0. All strings with + unsigned char elements written by Rhino are UTF-8 encoded + unicode strings. + */ + bool ReadString( + size_t str_array_count, + unsigned char* str_array + ); + + /* + Parameters: + str_array_count - [in] + Number of unsigned short elements in str_array[], + including the null terminator. The value of + str_array_count is returned by ReadWideCharStringElementCount(). + str_array - [in/out] + Pass in an array with at least str_array_count elements. + If true is returned and str_array_count > 0, + then str_array[str_array_count-1] = 0. All strings with + unsigned short elements written by Rhino are UTF-16 encoded + unicode strings. + */ + bool ReadString( + size_t str_array_count, + unsigned short* str_array + ); + + bool ReadString( ON_String& sUTF8 ); + + bool ReadString( ON_wString& s ); + + bool ReadComponentIndex( ON_COMPONENT_INDEX& ); + + bool ReadArray( ON_SimpleArray& ); + bool ReadArray(ON_SimpleArray&); + bool ReadArray(ON_SimpleArray&); + bool ReadArray(ON_SimpleArray&); + bool ReadArray(ON_SimpleArray&); + bool ReadArray(ON_SimpleArray&); + bool ReadArray(ON_SimpleArray&); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_ClassArray& ); + bool ReadArray( ON_ClassArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_ClassArray& ); + bool ReadArray( ON_ClassArray& ); + bool ReadArray( ON_ClassArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_SimpleArray& ); + bool ReadArray( ON_ObjectArray& ); + bool ReadArray( ON_SimpleArray& ); + + bool WriteBool( bool ); + +#if defined(ON_COMPILER_MSC) && defined(NDEBUG) + // Work around Release build optimization bug in Visual Studio 2017. + __declspec(noinline) +#endif + bool WriteBoolTrue(); + +#if defined(ON_COMPILER_MSC) && defined(NDEBUG) + // Work around Release build optimization bug in Visual Studio 2017. + __declspec(noinline) +#endif + bool WriteBoolFalse(); + + bool WriteChar( // Write an array of 8 bit chars + size_t, // number of chars to write + const char* + ); + bool WriteChar( // Write an array of 8 bit unsigned chars + size_t, // number of unsigned chars to write + const unsigned char* + ); + bool WriteChar( // Write a single 8 bit char + char + ); + bool WriteChar( // Write a single 8 bit unsigned char + unsigned char + ); + + bool WriteShort( // Write an array of 16 bit shorts + size_t, // number of shorts to write + const short* + ); + bool WriteShort( // Write an array of 16 bit unsigned shorts + size_t, // number of shorts to write + const unsigned short* + ); + bool WriteShort( // Write a single 16 bit short + short + ); + bool WriteShort( // Write a single 16 bit unsigned short + unsigned short + ); + + bool WriteInt( // Write an array of 32 bit integers + size_t, // number of ints to write + const int* + ); + bool WriteInt( // Write an array of 32 bit integers + size_t, // number of ints to write + const unsigned int* + ); + bool WriteInt( // Write a single 32 bit integer + int + ); + bool WriteInt( // Write a single 32 bit unsigned integer + unsigned int + ); + + bool WriteBigInt( // Write an array of 64 bit integers + size_t, // number of ints to write + const ON__INT64* + ); + bool WriteBigInt( // Write an array of 64 bit integers + size_t, // number of ints to write + const ON__UINT64* + ); + bool WriteBigInt( // Write a single 64 bit integer + ON__INT64 + ); + bool WriteBigInt( // Write a single 64 bit unsigned integer + ON__UINT64 + ); + + bool WriteLong( // Write an array of 32 bit integers + size_t, // number of ints to write + const long* + ); + bool WriteLong( // Write an array of 32 bit integers + size_t, // number of ints to write + const unsigned long* + ); + bool WriteLong( // Write a single 32 bit integer + long + ); + bool WriteLong( // Write a single 32 bit unsigned integer + unsigned long + ); + bool WriteSize( // Write a single size_t + size_t + ); + + bool WriteBigSize( size_t ); // 64 bits + + bool WriteBigTime( time_t ); // UCT seconds since 1 January 1970 (64 bits) + + bool WriteFloat( // Write a number of IEEE floats + size_t, // number of doubles + const float* + ); + bool WriteFloat( // Write a single float + float + ); + bool WriteDouble( // Write a single double + size_t, + const double* + ); + bool WriteDouble( // Write a single double + double + ); + + bool WriteColor ( + const ON_Color& + ); + + bool WriteColor( + const ON_4fColor& + ); + + bool WritePoint ( + const ON_2dPoint& + ); + bool WritePoint ( + const ON_3dPoint& + ); + bool WritePoint ( + const ON_4dPoint& + ); + bool WriteVector ( + const ON_2dVector& + ); + bool WriteVector ( + const ON_3dVector& + ); + + bool WriteBoundingBox(const ON_BoundingBox&); + + bool WriteXform(const ON_Xform&); + + bool WritePlaneEquation(const ON_PlaneEquation&); + + bool WritePlane(const ON_Plane&); + + bool WriteLine(const ON_Line&); + + bool WriteArc(const ON_Arc&); + + bool WriteCircle(const ON_Circle&); + + bool WriteInterval( const ON_Interval& ); + + bool WriteUuid( const ON_UUID& ); + + bool WriteDisplayMaterialRef( const ON_DisplayMaterialRef& ); + + bool WriteLinetypeSegment( const ON_LinetypeSegment& ); + + // All times are stored in universal coordinated time + // ( a.k.a GMT, UCT ). Use ANSI C time() and gmtime() calls. + bool WriteTime( const struct tm& ); + + /* + Parameters: + sUTF8 - [in] + A null terminated UTF-8 encoded unicode string. + Remarks: + To read a string written with WriteString(const char*), + call ReadStringUTF8ElementCount(&string_utf8_element_count) + to get the number of char elements written in the file, + obtain a buffer with at least string_utf8_element_count + char elements and then call + ReadString(string_utf8_element_count,buffer) to read the + char elements. + + If 0 == sUTF8 or 0 == SUTF8[0], a 4 byte int with + value = 0 is written, otherwise a 4 byte int with + value = strlen + 1 is written, followed by the string, + followed by the null terminator. + */ + bool WriteString( + const char* sUTF8 + ); + + /* + Parameters: + sUTF8 - [in] + A null terminated UTF-8 encoded unicode string. + Remarks: + To read a string written with WriteString(const unsigned char*), + call ReadStringUTF8ElementCount(&string_utf8_element_count) to + get the number of unsigned char elements written in the file, + obtain a buffer with at least string_utf8_element_count + unsigned char elements and then call + ReadString(string_utf8_element_count,buffer) to read the + unsigned charelements. + + If 0 == sUTF8 or 0 == SUTF8[0], a 4 byte int with + value = 0 is written, otherwise a 4 byte int with + value = strlen + 1 is written, followed by the string, + followed by the null terminator. + */ + bool WriteString( + const unsigned char* sUTF8 + ); + + /* + Parameters: + sUTF16 - [in] + A null terminated UTF-16 encoded unicode string. + Remarks: + To read a string written with WriteString(const unsigned short*), + call ReadStringUTF16ElementCount(&string_utf16_element_count) to + get the number of unsigned short elements written in the file, + obtain a buffer with at least string_utf16_element_count + unsigned short elements and then call + ReadString(string_utf16_element_count,buffer) to read the + unsigned short elements. + + If 0 == sUTF8 or 0 == SUTF8[0], a 4 byte int with + value = 0 is written, otherwise a 4 byte int with + value = strlen + 1 is written, followed by the string, + followed by the null terminator. + */ + bool WriteUTF16String( + const unsigned short* sUTF16 + ); + + /* + Description: + Write a wide string as a UTF-8 encoded string. + */ + bool WriteWideString( + const wchar_t* sWideChar, + int sWideChar_count + ); + + /* + Description: + Write a wide string as a UTF-8 encoded string. + */ + bool WriteWideString( + const ON_wString& wide_string + ); + + /* + Description: + Read a wide string written with the WriteWideString() function. + */ + bool ReadWideString( + ON_wString& wide_string + ); + + bool WriteString( const ON_String& sUTF8 ); + + bool WriteString( const ON_wString& s); + + bool WriteComponentIndex( const ON_COMPONENT_INDEX& ); + + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + + bool WriteArray(const ON_SimpleArray&); + bool WriteArray(const ON_SimpleArray&); + bool WriteArray(const ON_SimpleArray&); + + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + + bool WriteArray( const ON_SimpleArray& ); + + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_ClassArray& ); + bool WriteArray( const ON_ClassArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_ClassArray& ); + bool WriteArray( const ON_ClassArray& ); + bool WriteArray( const ON_ClassArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( const ON_SimpleArray& ); + bool WriteArray( int count, const class ON_Layer* ); + bool WriteArray( int count, const class ON_Layer*const* ); + + ///////////////////////////////////////////////////// + // + // Read/Write classes derived from ON_Object + // + + /* + Description: + Reads and object from a 3dm archive; + Parameters: + ppObject - [out] object is allocated and a pointer to the + allocated object is returned as *ppObject; + Returns: + 0: failure - unable to read object because of file IO problems + 1: success + 3: unable to read object because it's UUID is not registered + this could happen in cases where old code is attempting to read + new objects. + */ + int ReadObject( + ON_Object** ppObject + ); + + + /* + Description: + Reads and object from a 3dm archive. + Parameters: + object - [in] The value of object.ON_ClassId()->Uuid() must + exactly match the class uuid in of the next + object in the archive. + Returns: + 0: failure - unable to read object because of file IO problems. + 1: success + 2: unable to read object because the class id in the archive + did not match pObject->ClassId. + */ + int ReadObject( + ON_Object& object + ); + + bool WriteObject( const ON_Object* ); // writes object definition + bool WriteObject( const ON_Object& ); // writes object definition + +private: + bool Internal_WriteObject( + const ON_Object& model_object + ); + bool Internal_WriteV5AnnotationObject( + const class ON_Annotation& V6_annotation, + const class ON_3dmAnnotationContext* annotation_context + ); + bool Internal_WriteV2AnnotationObject( + const class ON_OBSOLETE_V5_Annotation& V5_annotation, + const class ON_3dmAnnotationContext* annotation_context + ); +public: + + + /////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // + // 3DM Interface - ignore if not reading/writing a 3DM file + // this is here so that the infrastructure + // for writing 3dm archives is available for + // any type of serialization device. + // + + /* + Description: + Specify which types of objects (ON_Brep, ON_Extrusion, ON_SubD, ...) + save render meshes in the 3dm file. + + Parameters: + object_type_flags - [in] + The bits in object_type_flags correspond to ON::object_type values + and identify the object types the setting will be applied to. + + Remarks: + Saving render meshes increases file size, sometimes dramatically. + + Creating ON_Brep analysis meshes is often slow. + Disable saving ON_Brep analysis meshes when IO speed or file size is + a critical issue, the time expense of recreating the ON_Brep meshes + when the file is read is acceptable, and the file will be read by Rhino. + Enable when the file size is not an issue or the file will be used by other + applications that may not be able to create meshes. + + Creating ON_Extrusion meshes is fast. Disable when IO speed or file size + is an issue and the file will be read by Rhino. Enable when the file + will be used by other applications that may not be able to create meshes. + + Creating ON_SubD meshes is fast. Disable when IO speed or file size + is an issue and the file will be read by Rhino. Enable when the file + will be used by other applications that may not be able to create meshes. + */ + void EnableSave3dmRenderMeshes( + unsigned int object_type_flags, + bool bSave3dmRenderMeshes + ); + + /* + Description: + Specify which types of objects (ON_Brep, ON_Extrusion, ON_SubD, ...) + save render meshes in the 3dm file. + Returns: + The bits in the return value correspond to ON::object_type values + and identify the object types save analysis meshes in the 3dm file. + */ + unsigned int Save3dmRenderMeshObjectTypeFlags() const; + + /* + Parameters: + object_type - [in] + Returns: + true if render meshes for the specified object type will be + saved in the .3dm file. + */ + bool Save3dmRenderMesh( + ON::object_type object_type + ) const; + + /* + Description: + Specify which types of objects (ON_Brep, ON_Extrusion, ON_SubD, ...) + save analysis meshes in the 3dm file. + + Parameters: + object_type_flags - [in] + The bits in object_type_flags correspond to ON::object_type values + and identify the object types the setting will be applied to. + + Remarks: + Saving analysis meshes increases file size, sometimes dramatically. + + Creating ON_Brep analysis meshes is often slow. + Disable saving ON_Brep analysis meshes when IO speed or file size is + a critical issue, the time expense of recreating the ON_Brep meshes + when the file is read is acceptable, and the file will be read by Rhino. + Enable when the file size is not an issue or the file will be used by other + applications that may not be able to create meshes. + + Creating ON_Extrusion meshes is fast. Disable when IO speed or file size + is an issue and the file will be read by Rhino. Enable when the file + will be used by other applications that may not be able to create meshes. + + Creating ON_SubD meshes is fast. Disable when IO speed or file size + is an issue and the file will be read by Rhino. Enable when the file + will be used by other applications that may not be able to create meshes. + */ + void EnableSave3dmAnalysisMeshes( + unsigned int object_type_flags, + bool bSave3dmAnalysisMeshes + ); + + void SetSave3dmPreviewImage( + bool bSave3dmPreviewImage + ); + + /* + Returns: + true: (default) + If a preview image is included in the ON_3dmProperties information, it will be saved. + false: + A preview imae, if it exists, will not be saved in the 3dm archive. + This reduces archive size. + When Save3dmPreviewImage() is false, generating a preview image can be skipped. + */ + bool Save3dmPreviewImage() const; + + /* + Description: + Control when some information, like preview images and mesh information, is + compressed when writing 3dm archives. The default is true. + In special situations when the storage media is extremely fast and large file size + is not a concern, disabling buffer compression can reduce file write time. + Parameters: + bUseBufferCompression - [in] + Remarks: + The default is true. + */ + void SetUseBufferCompression( + bool bUseBufferCompression + ); + + /* + Returns: + true: (default) + Some information, including preview images and mesh information is compressed when + writing 3dm archives. This reduces, sometimes dramatically, the size + of the 3dm archive. + false: + No compression is performed. This increases, sometimes dramatically, the size + of the 3dm archive. + In special situations when the storage media is extremely fast and large file size + is not a concern, disabling buffer compression can reduce file write time. + */ + bool UseBufferCompression() const; + + + /* + Description: + Specify which types of objects (ON_Brep, ON_Extrusion, ON_SubD, ...) + save analysis meshes in the 3dm file. + Returns: + The bits in the return value correspond to ON::object_type values + and identify the object types save analysis meshes in the 3dm file. + */ + unsigned int Save3dmAnalysisMeshObjectTypeFlags() const; + + /* + Parameters: + object_type - [in] + Returns: + true if analysis meshes for the specified object type will be + saved in the .3dm file. + */ + bool Save3dmAnalysisMesh( + ON::object_type object_type + ) const; + + + /* + Returns: + True if all user data and user tables should be read or written. + False if some or no user data or user tables should be read or written. + Remarks: + AllUserDataSerializationIsEnabled() = (false == ShouldSerializeNoUserData() && false == ShouldSerializeSomeUserData()) + */ + bool ShouldSerializeAllUserData() const; + + /* + Returns: + True if no user data and user tables should be read or written. + False if some or all user data or user tables should be read or written. + Remarks: + SerializeNoUserData() = (false == ShouldSerializeAllUserData() && false == ShouldSerializeSomeUserData()) + */ + bool ShouldSerializeNoUserData() const; + + /* + Returns: + True if some but not all user data or user tables should be + read or written. + False if all user data or no user data should be read or written. + Remarks: + SerializeSomeUserData() = (false == ShouldSerializeAllUserData() && false == ShouldSerializeNoUserData()) + + Use ShouldSerializeUserDataItem(application_id,item_id) to + determine if a specific object user data or user table should + be read or written. + */ + bool ShouldSerializeSomeUserData() const; + + /* + Description: + Determine if an application's (plug-in's) object user data + or user table should be read or written. + Parameters: + application_id - [in] + The application id (often a plug-in id) for the object user data + or user table. + item_id - [in] + item_id identifies which user data items should be read or written. + - To determine if a specific type of object user data should + be read or written, pass the value of ON_UserData.m_userdata_uuid. + - To determine if the user table for the application should + be read or written, pass application_id. + - To determine if all object user data and the user table + for the application should be read or written, pass nil. + Returns: + True if the identified user data or user table should be read or written. + */ + bool ShouldSerializeUserDataItem( + ON_UUID application_id, + ON_UUID item_id + ) const; + + /* + Description: + Specify the serialization option for object user data and user tables + that are not explicity set by SetShouldSerializeUserDataItem(). + Parameters: + bSerialize - [in] + Remarks: + If no setting is specified, all user data is read and written. + */ + bool SetShouldSerializeUserDataDefault( + bool bSerialize + ); + + bool ShouldSerializeUserDataDefault() const; + + + /* + Description: + Specify if an application's (plug-in's) object user data + or user table should be read or written. + Parameters: + application_id - [in] + The application id (often a plug-in id) for the object user data + or user table. + item_id - [in] + item_id identifies which user data items should be read or written. + - To determine if a specific type of object user data should + be read or written, pass the value of ON_UserData.m_userdata_uuid. + - To determine if the user table for the application should + be read or written, pass application_id. + - To determine if all object user data and the user table + for the application should be read or written, pass nil. + bSerializeUserDataItem - [in] + True to enable reading and writing of the specified item. + False to disable reading and writing of the specified item. + Returns: + True if the input was valid and the setting was applied. + This function will not apply any settings after reading + or writing begins. + */ + bool SetShouldSerializeUserDataItem( + ON_UUID application_id, + ON_UUID item_id, + bool bSerializeUserDataItem + ); + + /* + Description: + Determine if an object has user data that should be written. + Parameters: + object - [in] + Returns: + True if object has user data that should be written. + */ + bool ObjectHasUserDataToWrite( + const class ON_Object* object + ) const; + + bool ShouldWriteUserDataItem( + const class ON_Object* object, + const class ON_UserData* object_user_data + ) const; + + /* + Remarks: + In a stable commercially released Rhino version N, CurrentArchiveVersion() = 10*N. + In "early" Rhino N WIP, CurrentArchiveVersion() = 10*(N-1). + In "later" Rhino N WIP, CurrentArchiveVersion() = 10*N. + Returns: + The current 3dm archive version that is saved by Rhino. + */ + static int CurrentArchiveVersion(); + + /* + Description: + As time passes, more tables have been added to 3dm archives. + Parameters: + table - [in] + Returns: + True if this archive has the specified table + */ + bool ArchiveContains3dmTable( + ON_3dmArchiveTableType table + ) const; + + /* + Parameters: + archive_3dm_version - [in] + 1,2,3,4,5,50,60,70,... + opennurbs_library_version - [in] + a number > 100000000 + */ + static bool ArchiveContains3dmTable( + ON_3dmArchiveTableType table, + unsigned int archive_3dm_version, + unsigned int opennurbs_library_version + ); + + bool WriteModelComponentName( + const ON_ModelComponent& model_component + ); + + /////////////////////////////////////////////////////////////////// + // Step 1: REQUIRED - Write/Read Start Section + // + + + /* + Description: + In rare cases, experts testing handling of corrupt 3dm files need to + write a 3dm archive that is corrupt. In this rare testing situation, + those experts should call IntentionallyWriteCorrupt3dmStartSectionForExpertTesting() + exactly one time before they begin writing the file. The 32 byte idendifier will + replace the 1st 3 spaces with a capital X to mimic a file that became corrupt + whle residing on storage media. + */ + void IntentionallyWriteCorrupt3dmStartSectionForExpertTesting(); + + /* + Parameters: + version - [in] + 0, 2, 3, 4, 5, 50 or 60 (5 is treated as 50) + + If version is 0, then the value of ON_BinaryArchive::CurrentArchiveVersion() + is used. + + Use either 0 or the value of ON_BinaryArchive::CurrentArchiveVersion() + for the version parameter when you want your code to write the most + up to date file version. + + sStartSectionComment - [in] + nullptr or a UTF-8 encoded string with application name, et cetera. + This information is primarily used when debugging files + that contain problems. McNeel and Associates stores + application name, application version, compile date, + and the OS in use when file was written. + */ + bool Write3dmStartSection( + int version, + const char* sStartSectionComment + ); + + /* + Parameters: + version - [out] + .3dm file version (2, 3, 4, 5, 50, 60) + sStartSectionComment - [out] + UTF-8 encoded string passed to Write3dmStartSection() + destination_manifest - [in] + manifest of the destination model + */ + bool Read3dmStartSection( + int* version, + ON_String& sStartSectionComment + ); + + /* + Returns: + A copy of the start section comment written to or read from the archive. + If this function is called before Write3dmStartSection() or Read3dmStartSection(), + it returns ON_String:EmptyString; + */ + const ON_String& Archive3dmStartSectionComment() const; + + /////////////////////////////////////////////////////////////////// + // Step 2: REQUIRED - Write/Read properties table + // + bool Write3dmProperties( + const class ON_3dmProperties& + ); + bool Read3dmProperties( + class ON_3dmProperties& + ); + + /* + Returns: + A copy of the ON_3dmProperties information written to or read from the archive. + If this function is called before Write3dmProperties() or Read3dmProperties(), + it returns ON_3dmProperties:Empty; + */ + const class ON_3dmProperties& Archive3dmProperties() const; + + /////////////////////////////////////////////////////////////////// + // Step 3: REQUIRED - Write/Read settings table + // + bool Write3dmSettings( + const class ON_3dmSettings& + ); + bool Read3dmSettings( + class ON_3dmSettings& + ); + + /* + Returns: + A copy of the ON_3dmSettings information written to or read from the archive. + If this function is called before Write3dmSettings() or Read3dmSettings(), + it returns ON_3dmSettings:Default; + */ + const class ON_3dmSettings& Archive3dmSettings() const; + + /////////////////////////////////////////////////////////////////// + // Step 4: REQUIRED - Write/Read bitmap table (it can be empty) + // + bool BeginWrite3dmBitmapTable(); + bool Write3dmImageComponent( + const class ON_ModelComponentReference& model_component_reference + ); + bool Write3dmImageComponent( + const class ON_ModelComponent* model_component + ); + bool Write3dmBitmap( const class ON_Bitmap& ); + bool EndWrite3dmBitmapTable(); + + bool BeginRead3dmBitmapTable(); + int Read3dmBitmap( // returns 0 at end of bitmap table + // 1 bitmap successfully read + class ON_Bitmap** // bitmap returned here + ); + bool EndRead3dmBitmapTable(); + + /////////////////////////////////////////////////////////////////// + // Step 5: REQUIRED - Write/Read texture mapping table (it can be empty) + // + bool BeginWrite3dmTextureMappingTable(); + bool Write3dmTextureMappingComponent( + const class ON_ModelComponentReference& model_component_reference + ); + bool Write3dmTextureMappingComponent( + const class ON_ModelComponent* model_component + ); + bool Write3dmTextureMapping( const class ON_TextureMapping& ); + bool EndWrite3dmTextureMappingTable(); + + bool BeginRead3dmTextureMappingTable(); + int Read3dmTextureMapping( // returns 0 at end of table + class ON_TextureMapping** // testuremapping returned here + ); + bool EndRead3dmTextureMappingTable(); + + /////////////////////////////////////////////////////////////////// + // Step 6: REQUIRED - Write/Read render material table (it can be empty) + // + bool BeginWrite3dmMaterialTable(); + bool Write3dmMaterialComponent( + const class ON_ModelComponentReference& model_component_reference + ); + bool Write3dmMaterialComponent( + const class ON_ModelComponent* model_component + ); + bool Write3dmMaterial( const class ON_Material& ); + bool EndWrite3dmMaterialTable(); + + bool BeginRead3dmMaterialTable(); + int Read3dmMaterial( // returns 0 at end of table + class ON_Material** // material returned here + ); + bool EndRead3dmMaterialTable(); + + /////////////////////////////////////////////////////////////////// + // Step 7: REQUIRED - Write/Read linetype table (it can be empty) + // + bool BeginWrite3dmLinetypeTable(); + bool Write3dmLinePatternComponent( + const class ON_ModelComponentReference& model_component_reference + ); + bool Write3dmLinePatternComponent( + const class ON_ModelComponent* model_component + ); + bool Write3dmLinetype( + const class ON_Linetype& line_pattern + ); + bool EndWrite3dmLinetypeTable(); + + bool BeginRead3dmLinetypeTable(); + int Read3dmLinetype( + class ON_Linetype** + ); + bool EndRead3dmLinetypeTable(); + + /////////////////////////////////////////////////////////////////// + // Step 8: REQUIRED - Write/Read layer table (it can be empty) + // + bool BeginWrite3dmLayerTable(); + bool Write3dmLayerComponent( + const class ON_ModelComponentReference& model_component_reference + ); + bool Write3dmLayerComponent( + const class ON_ModelComponent* model_component + ); + bool Write3dmLayer( const ON_Layer& ); + bool EndWrite3dmLayerTable(); + + bool BeginRead3dmLayerTable(); + int Read3dmLayer( // returns 0 at end of table + ON_Layer** // layer returned here + ); + bool EndRead3dmLayerTable(); + + /////////////////////////////////////////////////////////////////// + // Step 9: REQUIRED - Write/Read group table (it can be empty) + // + bool BeginWrite3dmGroupTable(); + bool Write3dmGroupComponent( + const class ON_ModelComponentReference& model_component_reference + ); + bool Write3dmGroupComponent( + const class ON_ModelComponent* model_component + ); + bool Write3dmGroup( const class ON_Group& ); + bool EndWrite3dmGroupTable(); + + bool BeginRead3dmGroupTable(); + + // Description: + // Reads groups from group table. If the group definition is + // read, a group is created by calling new ON_Group(), + // initialized with values stored in the archive, and + // returned. + // + // Parameters: + // ppGroup - If the group definition is + // read, a group is created by calling new ON_Group(), + // initialized with values stored in the archive, and + // a pointer to the new group is returned in *ppGroup. + // + // Returns: + // + // @untitled table + // 0 at the end of the group table + // 1 group definition was successfully read + // -1 archive is corrupt at this point + // + // Example: + // Calls to Read3dmGroup need to be bracketed by calls + // to BeginRead3dmGroupTable() / EndRead3dmGroupTable(). + // + // archive.BeginRead3dmGroupTable(); + // ON_Group* pGroup; + // int rc = 1; + // while(rc==1) + // { // + // pGroup = 0; + // archive.Read3dmGroup(&pGroup); + // if ( pGroup ) + // do something with pGroup + // } // + // archive.EndRead3dmGroupTable(); + // + int Read3dmGroup( + class ON_Group** // ppGroup + ); + + bool EndRead3dmGroupTable(); + + + /////////////////////////////////////////////////////////////////////// + ////// Step 10: REQUIRED - Write/Read text_style table (it can be empty) + ////// + ////ON_DEPRECATED_MSG("remove call. Text style information is now part of ON_DimStyle.") + ////bool BeginWrite3dmTextStyleTable(); + ////////bool Write3dmTextStyleComponent( + //////// const class ON_ModelComponentReference& model_component_reference + //////// ); + ////////bool Write3dmTextStyleComponent( + //////// const class ON_ModelComponent* model_component + //////// ); + ////ON_DEPRECATED_MSG("remove call. Text style information is now part of ON_DimStyle.") + ////bool Write3dmTextStyle( + //// const class ON_TextStyle& + //// ); + ////ON_DEPRECATED_MSG("remove call. Text style information is now part of ON_DimStyle.") + ////bool EndWrite3dmTextStyleTable(); + +private: + ////bool Internal_BeginWrite3dmTextStyleTable(); + bool Internal_Write3dmTextStyle( + const class ON_TextStyle& + ); + /////bool Internal_EndWrite3dmTextStyleTable(); + +public: + + //////ON_DEPRECATED_MSG("remove call. Text style information is now part of ON_DimStyle.") + //////bool BeginRead3dmTextStyleTable(); + + //////ON_DEPRECATED_MSG("remove call. Text style information is now part of ON_DimStyle.") + //////int Read3dmTextStyle( + ////// class ON_TextStyle** // ppTextStyle + ////// ); + + //////ON_DEPRECATED_MSG("remove call. Text style information is now part of ON_DimStyle.") + //////bool EndRead3dmTextStyleTable(); + +private: + int Internal_Read3dmTextStyle( + class ON_TextStyle** // ppTextStyle + ); +public: + + /////////////////////////////////////////////////////////////////// + // Step 11: REQUIRED - Write/Read dimstyle table (it can be empty) + // + bool BeginWrite3dmDimStyleTable(); + + bool Write3dmDimStyleComponent( + const class ON_ModelComponentReference& model_component_reference + ); + bool Write3dmDimStyleComponent( + const class ON_ModelComponent* model_component + ); + bool Write3dmDimStyle( const class ON_DimStyle& ); + + bool EndWrite3dmDimStyleTable(); + +private: + bool Internal_Write3dmDimStyle( const class ON_DimStyle&, bool bUpdateManifest ); +public: + + bool BeginRead3dmDimStyleTable(); + + // Description: + // Reads annotation dimension styles from dimension style table. + // If the dimension style definition is read, + // a dimension style is created by calling new ON_DimStyle(), + // initialized with values stored in the archive, and + // returned. + // + // Parameters: + // ppDimStyle - If the dimstyle definition is + // read, a dimstyle is created by calling new ON_DimStyle(), + // initialized with values stored in the archive, and + // a pointer to the new dimstyle is returned in *ppDimStyle. + // + // Returns: + // + // @untitled table + // 0 at the end of the dimension style table + // 1 dimension style definition was successfully read + // -1 archive is corrupt at this point + // + // Example: + // Calls to Read3dmDimStyle need to be bracketed by calls + // to BeginRead3dmDimStyleTable() / EndRead3dmDimStyleTable(). + // + // archive.BeginRead3dmDimStyleTable(); + // int rc = 1; + // ON_DimStyle* pDimStyle; + // while(rc==1) + // { // + // pDimStyle = 0; + // archive.Read3dmDimStyle(&pDimStyle); + // if ( pDimStyle ) + // do something with pDimStyle + // } // + // archive.EndRead3dmDimStyleTable(); + // + int Read3dmDimStyle( + class ON_DimStyle** ppDimStyle + ); + +private: + int Internal_Read3dmDimStyle( + class ON_DimStyle** ppDimStyle + ); + + void Internal_ConvertTextStylesToDimStyles(); + + double Internal_ArchiveModelSpaceTextScale() const; + + const ON_DimStyle* Internal_ArchiveCurrentDimStyle(); + +public: + bool EndRead3dmDimStyleTable(); + + /* + Internal_Read3dmDimStyleOverrides() is a public function on ON_BinaryArchive because + it must be called from ON_Annotation::Internal_ReadAnnotation(). + There is no other reason to call this function. + */ +public: + bool Internal_Read3dmDimStyleOverrides( + class ON_Annotation& annotation, + bool bFromDimStyleTable + ); + + /* + Internal_Write3dmDimStyleOverrides() is a public function on ON_BinaryArchive because + it must be called from ON_Annotation::Internal_WriteAnnotation(). + There is no other reason to call this function. + */ +public: + bool Internal_Write3dmDimStyleOverrides( + const class ON_Annotation& annotation, + const class ON_DimStyle* dim_style_overrides + ); + +public: + /////////////////////////////////////////////////////////////////// + // Step 12: REQUIRED - Write/Read render light table (it can be empty) + // + bool BeginWrite3dmLightTable(); + bool Write3dmModelLightComponent( + const class ON_ModelComponentReference& model_component_reference + ); + bool Write3dmModelLightComponent( + const class ON_ModelGeometryComponent* model_light + ); + bool Write3dmLight( + const class ON_Light&, + const class ON_3dmObjectAttributes* // can be nullptr + ); + bool EndWrite3dmLightTable(); + + bool BeginRead3dmLightTable(); + + // Call either Read3dmModelLight or Read3dmLight + /* + Parameters: + model_light - [out] + ON_ModelGeometryComponent returned here. + nullptr returned at end of the table. + object_filter - [in] + optional filter made by setting ON::object_type bits + Returns: + 0 at end of object table + 1 if object is read + 2 if object is skipped because it does not match filter + -1 if file is corrupt + */ + int Read3dmModelLight( + class ON_ModelGeometryComponent** model_light + ); + + int Read3dmLight( + class ON_Light** light, + class ON_3dmObjectAttributes* attributes + ); + + bool EndRead3dmLightTable(); + + + /////////////////////////////////////////////////////////////////// + // Step 13: REQUIRED - Write/Read hatch pattern table (it can be empty) + // + bool BeginWrite3dmHatchPatternTable(); + bool Write3dmHatchPatternComponent( + const class ON_ModelComponentReference& model_component_reference + ); + bool Write3dmHatchPatternComponent( + const class ON_ModelComponent* model_component + ); + bool Write3dmHatchPattern( const class ON_HatchPattern&); + bool EndWrite3dmHatchPatternTable(); + + bool BeginRead3dmHatchPatternTable(); + int Read3dmHatchPattern(class ON_HatchPattern**); + bool EndRead3dmHatchPatternTable(); + + /////////////////////////////////////////////////////////////////// + // Step 14: REQUIRED - Write/Read instance definition table (it can be empty) + // + bool BeginWrite3dmInstanceDefinitionTable(); + bool Write3dmInstanceDefinitionComponent( + const class ON_ModelComponentReference& model_component_reference + ); + bool Write3dmInstanceDefinitionComponent( + const class ON_ModelComponent* model_component + ); + bool Write3dmInstanceDefinition( const class ON_InstanceDefinition& ); + bool EndWrite3dmInstanceDefinitionTable(); + + bool BeginRead3dmInstanceDefinitionTable(); + + /* + Description: + Reads instance definitions from instance defintion table. + + Parameters: + ppInstanceDefinition - If an instance defintion is + read, an instance defintion is created by calling new + ON_InstanceDefinition(), initialized with values stored + in the archive, and a pointer to the new instance defintion + is returned in *ppInstanceDefinition. + + Returns: + + @untitled table + 0 at the end of the instance defintion table + 1 instance defintion was successfully read + -1 archive is corrupt at this point + + Example: + Calls to Read3dmInstanceDefinition need to be bracketed by calls + to BeginRead3dmInstanceDefinitionTable() / EndRead3dmInstanceDefinitionTable(). + + archive.BeginRead3dmInstanceDefinitionTable(); + int rc = 1; + ON_InstanceDefinition* pInstanceDefinition; + while(rc==1) + { + pInstanceDefinition = 0; + archive.Read3dmInstanceDefinition(&pInstanceDefinition); + if ( pInstanceDefinition ) + do something with pInstanceDefinition + } + archive.EndRead3dmInstanceDefinitionTable(); + */ + int Read3dmInstanceDefinition( + class ON_InstanceDefinition** // ppInstanceDefinition + ); + + bool EndRead3dmInstanceDefinitionTable(); + + /////////////////////////////////////////////////////////////////// + // Step 15: REQUIRED - Write/Read geometry and annotation table (it can be empty) + // + bool BeginWrite3dmObjectTable(); + bool Write3dmModelGeometryComponent( + const class ON_ModelComponentReference& model_component_reference + ); + bool Write3dmModelGeometryComponent( + const class ON_ModelGeometryComponent* model_geometry + ); + bool Write3dmObject( + const ON_Object&, + const ON_3dmObjectAttributes* // optional + ); + bool EndWrite3dmObjectTable(); + + bool BeginRead3dmObjectTable(); + + // Call either Read3dmModelGeometry or Read3dmObject + /* + Parameters: + model_geometry - [out] + ON_ModelGeometryComponent returned here. + nullptr returned at end of the table. + object_filter - [in] + optional filter made by setting ON::object_type bits + Returns: + 0 at end of object table + 1 if object is read + 2 if object is skipped because it does not match filter + -1 if file is corrupt + */ + int Read3dmModelGeometry( + class ON_ModelGeometryComponent** model_geometry, + unsigned int object_filter = 0 + ); + + /* + Parameters: + bManageGeometry - [in] + true: model_geometry will reference count and delete the ON_Geometry pointer. + false: The caller must delete the ON_Geometry pointer. + bManageAttributes - [in] + true: model_geometry will reference count and delete the ON_3dmObjectAttributes pointer. + false: The caller must delete the ON_3dmObjectAttributes pointer. + model_geometry - [out] + ON_ModelGeometryComponent returned here. + nullptr returned at end of the table. + object_filter - [in] + optional filter made by setting ON::object_type bits + 0 = no filter. + Returns: + 0 at end of object table + 1 if object is read + 2 if object is skipped because it does not match filter + -1 if file is corrupt + */ + int Read3dmModelGeometryForExperts( + bool bManageGeometry, + bool bManageAttributes, + class ON_ModelGeometryComponent** model_geometry, + unsigned int object_filter + ); + + /* + Parameters: + model_object - [out] + nullptr returned at end of the table. + attributes - [out] + If not nullptr, then attributes are returned here + object_filter - [in] + optional filter made by setting ON::object_type bits + Returns: + 0 at end of object table + 1 if object is read + 2 if object is skipped because it does not match filter + -1 if file is corrupt + */ + int Read3dmObject( + ON_Object** model_object, + ON_3dmObjectAttributes* attributes, + unsigned int object_filter = 0 + ); + +private: + /* + Description: + In rare cases one object must be converted into another. + Examples include reading obsolete objects and converting them into their + current counterpart, converting WIP objects into a proxy for a commercial build, + and converting a proxy object into a WIP object for a WIP build. + */ + ON_Object* Internal_ConvertObject( + const ON_Object* archive_object, + const ON_3dmObjectAttributes* attributes + ) const; + +public: + + bool EndRead3dmObjectTable(); + + /////////////////////////////////////////////////////////////////// + // Step 16: REQUIRED - Write/Read history record table (it can be empty) + // + bool BeginWrite3dmHistoryRecordTable(); + bool Write3dmHistoryRecordComponent( + const class ON_ModelComponentReference& model_component_reference + ); + bool Write3dmHistoryRecordComponent( + const class ON_ModelComponent* model_component + ); + bool Write3dmHistoryRecord( + const class ON_HistoryRecord& + ); + bool EndWrite3dmHistoryRecordTable(); + + bool BeginRead3dmHistoryRecordTable(); + + /* + Returns: + 0 at end of object table + 1 if object is read + -1 if file is corrupt + */ + int Read3dmHistoryRecord( + class ON_HistoryRecord*& + ); + bool EndRead3dmHistoryRecordTable(); + + /////////////////////////////////////////////////////////////////// + // Step 17: OPTIONAL - Write/Read 0 or more user tables + // + + /* + Description: + Write the user table header information that must precede + the user table information written by a plug-in. + Parameters: + plugin_id - [in] + bSavingGoo - [in] + Set to false if a plug-in will be used to write + the user table. Set to true if a user table written by + a missing plug-in is being resaved. In this case, + goo_3dm_version and goo_opennurbs_version must also be + set. In practice, you should use Write3dmAnonymousUserTableRecord() + to handle writing "goo" and use this function only when + the plug-in in present. + goo_3dm_version - [in] + If bSavingGoo is false, this parameter must be zero and + ON_BinaryArchive::Archive3dmVersion() will be used. + If bSavingGoo is true, this parameter must be the version of + the 3dm archive (1,2,3,4,5,50,...) the plug-in code used to + write the user table. + goo_opennurbs_version - [in] + If bSavingGoo is false, this parameter must be zero and + ON_BinaryArchive::ArchiveOpenNURBSVersion() will be used. + If bSavingGoo is true, this parameter must be the version + of the opennurbs the plug-in code used to write the + user table. + Returns: + True if the the user information can be written. + False if user informtion should not be written. + */ + bool BeginWrite3dmUserTable( + ON_UUID plugin_id, + bool bSavingGoo, + int goo_3dm_version, + unsigned int goo_opennurbs_version + ); + + bool EndWrite3dmUserTable(); + + /* + Description: + If Read3dmAnaonymousUserTable() was used to read ON_3dmGoo because a + plug-in was not present, then use Write3dmAnonymousUserTableRecord() + to put than information back into the archive. + Write3dmAnonymousUserTableRecord() writes the entire record. + Do NOT call BeginWrite3dmUserTable() / EndWrite3dmUserTable() when + using Write3dmAnonymousUserTableRecord(). + Parameters: + plugin_id - [in] + goo_version - [in] + The version of the archive (1,2,3,4,5,50,...) that was used when + the plug-in wrote the user table. + goo_opennurbs_version - [in] + The version of opennurbs ( YYYMMDDN ) that was used when the + plug-in wrote the user table. + goo - [in] + Returns: + True if the goo was written. + False if skipped because it could not be robustly saved. + */ + bool Write3dmAnonymousUserTableRecord( + ON_UUID plugin_id, + int goo_3dm_version, + unsigned int goo_opennurbs_version, + const class ON_3dmGoo& goo + ); + + ON_DEPRECATED_MSG("use BeginWrite3dmUserTable(plugin_id, bSavingGoo, 3dm_version, opennurbs_version)") + bool BeginWrite3dmUserTable( const ON_UUID& ); + + ON_DEPRECATED_MSG("use Write3dmAnonymousUserTableRecord(plugin_id, ..., goo)") + bool Write3dmAnonymousUserTable( const class ON_3dmGoo& ); + + /* + Parameters: + plugin_id - [out] + id of plug-in that wrote the user table + bLastSavedAsGoo - [out] + True if this table was saved into this archive as goo because + the plug-in was not present at the time of the save. + archive_3dm_version - [out] + Version of the archive the plug-in wrote to. When bLastSavedAsGoo + is true, this number can be different from Archive3dmVersion(). + archive_opennurbs_version - [out] + Version of opennurbs the plug-in used to write the archive. + When bLastSavedAsGoo is true, this number can be different + from ArchiveOpenNURBSVersion(). + Returns: + False when there are no more user tables or an IO error occurs. + */ + bool BeginRead3dmUserTable( + ON_UUID& plugin_id, + bool* bLastSavedAsGoo, + int* archive_3dm_version, + unsigned int* archive_opennurbs_version + ); + + /* + Description: + If the plug-in that wrote the user table is not present and you need + to read and resave the user table, then use Read3dmAnonymousUserTable() + to load the information into "goo". + If you do not need to resave the information, then simply call EndRead3dmUserTable() + to skip over this table. + */ + bool Read3dmAnonymousUserTable( + int archive_3dm_version, + unsigned int archive_opennurbs_version, + ON_3dmGoo& goo + ); + + bool EndRead3dmUserTable(); + + /////////////////////////////////////////////////////////////////// + // Step 18: REQUIRED when writing / OPTIONAL when reading + // Write end of file marker. This information is primarily + // used when debugging files to make sure the end of the file + // hasn't been cut off. + // + + // Description: + // Writes a TCODE_ENDOFFILE chunk that contains the number + // of bytes in the archive. + // + // Returns: + // true if successful, false if unable to write to archive. + bool Write3dmEndMark(); + + // Description: + // Checks for a TCODE_ENDOFFILE chunk at the current position. + // If it finds one, it reads it and returns the number + // of bytes in the archive. Comparing this number with + // the current file position can help detect files that + // have been damaged by loosing sections. + // + // Parameters: + // sizeof_archive - [out] number of bytes written to archive + // + // Returns: + // true if successful, false if unable to find or read + // a TCODE_ENDOFFILE chunk. + bool Read3dmEndMark( + size_t* // sizeof_archive + ); + + /////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // Low level tools to Write/Read chunks. See opennurbs_3dm.h for details + // about the structure of chunks. Every chunk must begin with a + // call to BeginWrite/ReadChunk(). + // If BeginWriteChunk()/BeginReadChunk() returns true, then + // you must call EndWrite/ReadChunk() or cease using the archive. + + // Description: + // Writes a chunk header containing 4 byte typecode and value. + // + // Parameters: + // typecode - [in] a TCODE_* number from opennurbs_3dm.h + // value - [in] if (typecode&TCODE_SHORT) is nonzero, then + // this is the value to be saved. Othewise, pass + // a zero and the EndWrite3dmChunk() call will + // store the length of the chunk. + // + // Returns: + // true if write was successful. + bool BeginWrite3dmChunk( + unsigned int, // typecode + int // value + ); + + bool BeginWrite3dmBigChunk( + ON__UINT32 typecode, + ON__INT64 value + ); + + /* + Description: + Begins writing a chunk. + Parameters: + tcode - [in] chunk's typecode from opennurbs_3dm.h. This cannot be a short tcode. + major_version - [in] ( >= 1) + minor_version - [in] ( >= 0 ) + Returns: + True if input was valid and chunk was started. In this case + You must call EndWrite3dmChunk(), even if something goes wrong + while you attempt to write the contents of the chunk. + False if input was not valid or the write failed. + */ + bool BeginWrite3dmChunk( + unsigned int tcode, + int major_version, + int minor_version + ); + + /* + Description: + If version >= 0, calls BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,version). + */ + bool BeginWrite3dmAnonymousChunk( + int version + ); + + + // updates length in chunk header + bool EndWrite3dmChunk(); + + bool Write3dmGoo( const ON_3dmGoo& ); // call to write "goo" + + //ON_DEPRECATED_MSG("use BeginRead3dmBigChunk") + //bool BeginRead3dmChunk( + // unsigned int*, // typecode from opennurbs_3dm.h + // int* // value + // ); + + // When the end of the 3dm file is reached, BeginReadChunk() will + // return true with a typecode of TCODE_ENDOFFILE. + bool BeginRead3dmBigChunk( + unsigned int*, // typecode from opennurbs_3dm.h + ON__INT64* // value + ); + /* + Description: + Begins reading a chunk that must be in the archive at this location. + Parameters: + expected_tcode - [in] chunk's typecode from opennurbs_3dm.h + major_version - [out] + minor_version - [out] + Returns: + True if beginning of the chunk was read. In this case + You must call EndRead3dmChunk(), even if something goes wrong + while you attempt to read the interior of the chunk. + False if the chunk did not exist at the current location in the file. + */ + bool BeginRead3dmChunk( + unsigned int expected_tcode, + int* major_version, + int* minor_version + ); + + /* + Description: + Calls BeginWRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version), + checks that 1 == major_version, minor_version >= 0 and returns the value + of minor_version as version. + Parameters: + version - [out] + */ + bool BeginRead3dmAnonymousChunk( + int* version + ); + + /* + Description: + Calling this will skip rest of stuff in chunk if it was only partially read. + Parameters: + bSupressPartiallyReadChunkWarning - [in] + Generally, a call to ON_WARNING is made when a chunk is partially + read. If bSupressPartiallyReadChunkWarning is true, then + no warning is issued for partially read chunks. + */ + bool EndRead3dmChunk(); + bool EndRead3dmChunk(bool bSupressPartiallyReadChunkWarning); + + + /////////////////////////////////////////////////////////////////// + // + // Tools for dictionary IO (used in .NET) + // + + /* + Description: + Begins writing a dictionary. + Parameters: + dictionary_id - [in] + version - [in] + It is suggested that you use ON_VersionNumberConstruct() to create + a version number. + dictionary_name - [in] + You may pass nullptr. + Remarks: + Begins a new chunk with tcode TCODE_DICTIONARY and then writes + a TCODE_DICTIONARY_ID chunk containing the id, version and name. + After calling this function, you may either write entries by + calling + BeginWriteDictionaryEntry(); + write entry definition... + EndWriteDictionaryEntry(); + or you may finish writing the dictionay by calling + EndWriteDictionary(); + */ + bool BeginWriteDictionary( + ON_UUID dictionary_id, + unsigned int version, + const wchar_t* dictionary_name + ); + /* + Description: + Begins writing a dictionary entry. + Parameters: + de_type - [in] + entry_name - [in] + Returns: + true + Entry header was written and you must call EndWriteDictionary() + after writing the entry data. + false + Failed to write entry header. Do not call EndWriteDictionary(). + Remarks: + Begins a new chunk with tcode TCODE_DICTIONARY_ENTRY, + then writes the int, and then writes the string. + */ + bool EndWriteDictionary(); + + /* + Description: + Begins writing a dictionary entry. + Parameters: + de_type - [in] + entry_name - [in] + Returns: + true + Entry header was written and you must call EndWriteDictionary() + after writing the entry data. + false + Failed to write entry header. Do not call EndWriteDictionary(). + Remarks: + Begins a new chunk with tcode TCODE_DICTIONARY_ENTRY, + then writes the int, and then writes the string. + */ + bool BeginWriteDictionaryEntry( + int de_type, + const wchar_t* entry_name + ); + bool EndWriteDictionaryEntry(); + + bool BeginReadDictionary( + ON_UUID* dictionary_id, + unsigned int* version, + ON_wString& dictionary_name + ); + bool EndReadDictionary(); + + /* + Description: + Begin reading a dictionary entry. + Parameters: + de_type - [out] + entry_name - [out] + Returns: + 0: serious IO error + 1: success + read information and then call EndReadDictionaryEntry() + 2: at end of dictionary + */ + int BeginReadDictionaryEntry( + int* de_type, + ON_wString& entry_name + ); + bool EndReadDictionaryEntry(); + + bool Read3dmGoo( ON_3dmGoo& ); // Call to read "goo" + + ON_DEPRECATED_MSG("use PeekAt3dmBigChunkType") + bool PeekAt3dmChunkType( // does not change file position + unsigned int*, // typecode from opennurbs_3dm.h + int* // value + ); + + bool PeekAt3dmBigChunkType( // does not change file position + ON__UINT32* typecode, + ON__INT64* big_value + ); + + bool Seek3dmChunkFromStart( + // beginning at the start of the active chunk, search portion of + // archive included in active chunk for the start of a subchunk + // with the specified type. + // if true is returned, then the position is set so the next call to + // BeginRead3dmChunk() will read a chunk with the specified typecode + unsigned int // typecode from opennurbs_3dm.h + ); + bool Seek3dmChunkFromCurrentPosition( + // beginning at the current position, search portion of archive + // included in active chunk for the start of a subchunk with the + // specified type. + // if true is returned, then the position is set so the next call to + // BeginRead3dmChunk() will read a chunk with the specified typecode + unsigned int // typecode from opennurbs_3dm.h + ); + + // A chunk version is a single byte that encodes a major.minor + // version number. Useful when creating I/O code for 3dm chunks + // that may change in the future. Increment the minor version + // number if new information is added to the end of the chunk. + // Increment the major version if the format of the chunk changes + // in some other way. + bool Write3dmChunkVersion( + int, // major // 0 to 15 + int // minor // 0 to 16 + ); + bool Read3dmChunkVersion( + int*, // major // 0 to 15 + int* // minor // 0 to 16 + ); + + /* + Description: + Low level tool to writes user data attached to the + object. This function should never be called + directly. + Parameters: + object - [in] + Returns: + True if successful. + */ + bool WriteObjectUserData( const ON_Object& object ); + + /* + Description: + Low level tool to read user data and attach it to + the object. This function should never be called + directly. + Parameters: + object - [in/out] + Returns: + True if successful. + */ + bool ReadObjectUserData( ON_Object& object ); + + /* + Description: + If a 3dm archive is being read or written, then this is the + version of the 3dm archive format (1, 2, 3, 4, 5, 50, 60, ...). + Returns: + @untitle table + 0 a 3dm archive is not being read/written + 1 a version 1 3dm archive is being read/written + 2 a version 2 3dm archive is being read/written + 3 a version 3 3dm archive is being read/written + 4 a version 4 3dm archive is being read/written + 5 an old version 5 3dm archive is being read + 50 a version 5 3dm archive is being read/written + 60 a version 6 3dm archive is being read/written + 70 a version 7 3dm archive is being read/written + ... + See Also: + ON_BinaryArchive::ArchiveOpenNURBSVersion + */ + int Archive3dmVersion() const; + + /* + Description: + If a 3dm archive is being read, then this is the version + of openNURBS that was used to write the archive. This value + is only available after ON_BinaryArchive::Read3dmProperties + is called. + See Also: + ON_BinaryArchive::Archive3dmVersion + ON_BinaryArchive::Read3dmProperties + Returns: + Version of openNURBS used to write the archive. The openNURBS + version is the value returned by ON::Version. + See Also: + ON::Version + ON_BinaryArchive::Read3dmProperties + ON_BinaryArchive::Archive3dmVersion + Remarks: + This value is rarely needed. You probably want to + use ON_BinaryArchive::Archive3dmVersion. + */ + unsigned int ArchiveOpenNURBSVersion() const; + + /* + Returns: + The runtime environment where the archive was created. + Remarks: + When reading an archive, compare the values of + ON_BinaryArchive::ArchiveRuntimeEnvironment() + and + ON::CurrentRuntimeEnvironment() + to determine if adjustments need to be made to resources provided + by runtime enviroments, like fonts. + */ + ON::RuntimeEnvironment ArchiveRuntimeEnvironment() const; + + const ON_DimStyle& ArchiveCurrentDimStyle() const; + const int ArchiveCurrentDimStyleIndex() const; + const ON_UUID ArchiveCurrentDimStyleId() const; + + /* + Description: + If a 3dm archive is being written to a version 2,3,4 or 50 format, + then new format opennurbs version numbers need to be saved in the + old YYYYMMDDN format. This function returns the value that should + be written in the file. + Parameters: + archive_3dm_version - [in] + Version of the file that is being written (2, 3, 4, 50, 60, ...) + opennurbs_version - [in] + opennurbs version number + Returns: + Value to save in the file. + */ + static unsigned int ArchiveOpenNURBSVersionToWrite( + unsigned int archive_3dm_version, + unsigned int opennurbs_version + ); + + /* + Description: + When a 3dm archive is saved from an MFC application that + supports Windows linking/embedding, the first 5kb to 1mb + of the file contains information that is put there by MFC. + ArchiveStartOffset() returns the offset into the file where + the 3dm archive actually begins. The call to + ON_BinaryArchive::Read3dmStartSection() calculates this + offset and stores the value in m_3dm_start_section_offset. + Returns: + Offset into the binary "file" where the actual 3dm archive + begins. + Remarks: + Generally, this value can be ignored. This function is + a diagnostice tool that is used to analyzed damaged files. + */ + size_t ArchiveStartOffset() const; + + /* + Description: + Expert user function for reading damaged files. + Parameters: + chunk - [out] current chunk. + Returns: + Level of the chunk or 0 if there is no current + chunk. + */ + int GetCurrentChunk(ON_3DM_CHUNK& chunk) const; + int GetCurrentChunk(ON_3DM_BIG_CHUNK& big_chunk) const; + + /* + Description: + Expert user function for reading damaged files. The search starts + at the beginning of the file. + Parameters: + tcode_table - [in] typecode of the table + tcode_record - [in] typecode of the record + class_uuid - [in] id of the opennurbs class in the record + min_length_data - [in] minimum size of the opennurbs class data + Returns: + True if the table start is found. In this case the current + position of the archive is at the start of the table and + the standared BeginRead3dm...Table() function can be used. + False if the table start is not found. + */ + bool FindTableInDamagedArchive( + unsigned int tcode_table, + unsigned int tcode_record, + ON_UUID class_uuid, + int min_length_data + ); + + /* + Description: + Expert user function for studying contents of a file. + The primary use is as an aid to help dig through files + that have been damaged (bad disks, transmission errors, etc.) + If an error is found, a line that begins with the word + "ERROR" is printed. + Parameters: + text_log - [in] place to print informtion + recursion_depth - [in] simply a counter + to aid in debugging. + Returns: + 0 if something went wrong, otherwise the typecode + of the chunk that was just studied. + */ + unsigned int + Dump3dmChunk( + ON_TextLog& text_log, + int recursion_depth = 0 + ); + + enum class eStorageDeviceError : unsigned int + { + None = 0, + + // values from 1 through 0xFFFFFFF0 are used for IO device + // specific exceptions that terminate reading or writing. + + WriteFailed = 0xFFFFFFF1, // writing to device failed + SeekFailedDuringWriting = 0xFFFFFFF2, // virtual Seek() failed during writing + ReadFailed = 0xFFFFFFF8, // reading from device failed + SeekFailedDuringReading = 0xFFFFFFF9, // virtual Seek() failed during reading + UnknownDeviceError = 0xFFFFFFFFU + }; + + static ON_BinaryArchive::eStorageDeviceError StorageDeviceErrorFromUnsigned( + unsigned int storage_device_error_as_unsigned + ); + + /* + Description: + An error terminated reading or writing + Returns: + 0: no error terminiated reading or writing + !=0: See the ON_BinaryArchive::DeviceErrorType for values + */ + unsigned int StorageDeviceError() const; + +private: + /* + Description: + Works like the C runtrim fread(). + Returns: + actual number of bytes read (like fread()) + */ + size_t Read(size_t, void*); + +protected: + /* + Remarks: + In some unusual situations when reading old or damaged files, a read may fail. + Call MaskReadError( ON__UINT64 sizeof_request, ON__UINT64 sizeof_read ) + before calling ON_ERROR(). + */ + virtual size_t Internal_ReadOverride( size_t, void* ) = 0; + +private: + /* + Description: + Works like the C runtrim fwrite(). + Returns: + actual number of bytes written (like fwrite()) + */ + size_t Write( size_t, const void* ); +protected: + virtual size_t Internal_WriteOverride( size_t, const void* ) = 0; + +public: + /* + Description: + Force Write() to flush any buffered data to physical archive. + Returns: + True if succesful or if there is nothing to flush. False if + information could not be flushed. + */ + virtual bool Flush() = 0; + + /* + Description: + When ON_BinaryArchive::ReadObject() encounters userdata and + the user data class id is not present, LoadUserDataApplication + is called to load the application that created user data. + Returns: + 0 - could not load the application + 1 - successfully loaded the application + 2 - the application was already loaded + */ + virtual + int LoadUserDataApplication( + ON_UUID application_id + ); + + bool SetArchive3dmVersion(int); + + /* + Description: + A non-zero storage device error terminates reading or writing. + See the ON_BinaryArchive::eStorageDeviceError for values. + Parameter: + storage_device_error - [in] + A non-zero code that identifies an error the terminates + reading or writing. + See ON_BinaryArchive::CriticalErrorCodes for values + Remarks: + Once set, the storage_device_error value cannot be changed. + */ + void SetStorageDeviceError( + ON_BinaryArchive::eStorageDeviceError storage_device_error + ); + void SetStorageDeviceError( + unsigned int storage_device_error + ); + +private: + // 16 bit integer IO + bool WriteInt8( size_t, const ON__INT8* ); + bool ReadInt8( size_t, ON__INT8* ); + + // 16 bit integer IO + bool WriteInt16( size_t, const ON__INT16* ); + bool ReadInt16( size_t, ON__INT16* ); + + // 32 bit integer IO + bool WriteInt32( size_t, const ON__INT32* ); + bool ReadInt32( size_t, ON__INT32* ); + + // 64 bit integer IO + bool WriteInt64( size_t, const ON__INT64* ); + bool ReadInt64( size_t, ON__INT64* ); + + bool BeginWrite3dmTable( + unsigned int // tcode + ); + bool EndWrite3dmTable( + unsigned int // tcode + ); + bool BeginRead3dmTable( + unsigned int // tcode + ); + bool EndRead3dmTable( + unsigned int // tcode + ); + + bool Read3dmV1Layer( ON_Layer*& ); + int Read3dmV1Light( // returns 0 at end of light table + // 1 light successfully read + // -1 if file is corrupt + ON_Light**, // light returned here + ON_3dmObjectAttributes* // optional - if NOT nullptr, object attributes are + // returned here + ); + int Read3dmV1Material( ON_Material** ); + int Read3dmV1Object( // returns 0 at end of object table + // 1 if object is read + // 2 if object is skipped because it does not match filter + // -1 if file is corrupt + ON_Object**, // object returned here (nullptr if skipped) + ON_3dmObjectAttributes*, // optional - if NOT nullptr, object attributes are + // returned here + unsigned int = 0 // optional filter made by setting ON::object_type bits + ); // returns nullptr at end of object table + + bool Read3dmV1AttributesOrMaterial( + ON_3dmObjectAttributes*, // attributes, + ON_Material*, // material, + bool&, // bHaveMat + unsigned int, // end_mark_tcode + class ON__3dmV1_XDATA* = 0 // v1 "xdata" + ); + bool Read3dmV1String( ON_String& ); + int Read3dmV1LayerIndex( const char* ) const; + +public: + // helpers for reading V1 objects + bool ReadV1_TCODE_RH_POINT(ON_Object**,ON_3dmObjectAttributes*); + bool ReadV1_TCODE_MESH_OBJECT(ON_Object**,ON_3dmObjectAttributes*); + bool ReadV1_TCODE_LEGACY_CRV(ON_Object**,ON_3dmObjectAttributes*); + bool ReadV1_TCODE_LEGACY_FAC(ON_Object**,ON_3dmObjectAttributes*); + bool ReadV1_TCODE_LEGACY_SHL(ON_Object**,ON_3dmObjectAttributes*); + bool ReadV1_TCODE_RHINOIO_OBJECT_NURBS_CURVE(ON_Object**,ON_3dmObjectAttributes*); + bool ReadV1_TCODE_RHINOIO_OBJECT_NURBS_SURFACE(ON_Object**,ON_3dmObjectAttributes*); + bool ReadV1_TCODE_RHINOIO_OBJECT_BREP(ON_Object**,ON_3dmObjectAttributes*); + bool ReadV1_TCODE_ANNOTATION(unsigned int,ON_Object**,ON_3dmObjectAttributes*); + +private: + void UpdateCRC( size_t, const void* ); + int ReadObjectHelper(ON_Object**); + + int m_3dm_version = 0; // 1,2,3,4,5 (obsolete 32-bit chunk sizes) + // 50,60,70,... (64-bit chunk sizes) + + int m_3dm_v1_layer_index = 0; + int m_3dm_v1_material_index = 0; + + + + +protected: + unsigned int ErrorMessageMask() const; + /* + Paramters: + sizeof_request - [in] + value of count parameter passed to virtual Read() function. + sizeof_read - [in] + number of bytes actually read by the virtual Read() function. + Returns: + True if a call to Read() is permitted to ask for more bytes + than are left in the file. This value varies as the file + is read and must be checked at each failure. + */ + bool MaskReadError( ON__UINT64 sizeof_request, ON__UINT64 sizeof_read ) const; + +private: + + + // When a 3DM archive is read, m_3dm_opennurbs_version records the version of + // OpenNURBS used to create the archive. Otherwise, m_3dm_opennurbs_version + // is zero. + // + // Read3dmProperties() sets this to the version of OpenNURBS that was + // used to write file file. If the file was created using a version + // of OpenNURBS before 200012210, this number will be zero. + // + // Write3dmProperties() stores the value returned by ON::Version() in + // the archive's properties table. + friend void ON_SetBinaryArchiveOpenNURBSVersion(ON_BinaryArchive&,unsigned int); + unsigned int m_3dm_opennurbs_version = 0; + + ON::RuntimeEnvironment m_archive_runtime_environment = ON::RuntimeEnvironment::Unset; + + // When a 3dm archive is saved from an MFC application that supports + // Windows linking/embedding, the first 5kb to 1mb of the file contains + // information that is put there by MFC. m_3dm_start_section_offset + // records the offset into the file where the 3dm archive actually begins. + size_t m_3dm_start_section_offset = 0; + + /*Read3dmTableRecordBegin + m_3dm_previous_table = 3dm archive table that was most recently read/written. + m_3dm_active_table = 3dm archive table currently being read/written + */ + ON_3dmArchiveTableType m_3dm_previous_table = ON_3dmArchiveTableType::Unset; + ON_3dmArchiveTableType m_3dm_active_table = ON_3dmArchiveTableType::Unset; + // If reading/writing a table fails, m_3dm_failed_table identifies the first failure. + ON_3dmArchiveTableType m_3dm_first_failed_table = ON_3dmArchiveTableType::Unset; + + int m_user_data_depth = 0; // > 0 when user data is being read or written + + // 3dm archive status information + class ON_3dmTableStatusLink* m_3dm_table_status_list = nullptr; + +private: + bool Internal_Write3dmUpdateManifest( + const ON_ModelComponent& model_component + ); + bool Internal_Write3dmLightOrGeometryUpdateManifest( + ON_ModelComponent::Type component_type, + ON_UUID component_id, + int component_index, + const ON_wString & component_name + ); + bool Internal_Read3dmUpdateManifest( + ON_ModelComponent& model_component + ); + bool Internal_Read3dmLightOrGeometryUpdateManifest( + ON_ModelComponent::Type component_type, + ON_UUID component_id, + int component_index, + const ON_wString & component_name + ); + +private: + bool Internal_IncrementCurrentPosition( + ON__UINT64 delta + ); + bool Internal_DecrementCurrentPosition( + ON__UINT64 delta + ); + ON__UINT64 m_current_positionX = 0; + + /* + Description: + Increments m_crc_error_count and active table m_crc_error_count. + */ + void Internal_ReportCRCError(); + + unsigned int m_crc_error_count = 0; // number of chunks that have a bad crc + + /* + Description: + Increments m_critical_error_count and active table m_critical_error_count. + */ + void Internal_ReportCriticalError(); + + // Number of critical errors. These errors are more serious than a CRC error. + // If a critical error occurs, the information being read or written is + // so corrupted that chunk accounting is failing or the calling code is deeply flawed. + unsigned int m_critical_error_count = 0; + + // ON_BinaryArchive::eStorageDeviceError values are used to set + // m_storage_device_error. + // ON_BinaryArchive::StorageDeviceError() returns the value. + unsigned int m_storage_device_error = 0; + + // The bits in m_error_message_mask are used to mask errors + // when we know we are doing something that may generate an + // error. + // + // bit 0x00000001 + // Setting this bit masks an error when attempting to read 4 bytes + // at the end of a file. + // V1 files do not have a table structure and are read using + // multiple passes and there are valid situations where a + // 4 byte read is attempted at the end of a file. + // This situation also occurs when a damaged file is missing a table + // or contains tables in the wrong order and the table must be searched + // for by typecode. + // + // bit 0x00000002 + // Some v1 files do not have an end mark. When reading + // these v1 files bit 0x02 is set. + // + // bit 0x00000004 + // Requested read may go beyond end of file. + // One situation where this happens is when a table is not at the + // expected location in a file, + unsigned int m_error_message_mask = 0; + + + + ON__UINT64 m_3dm_end_mark_length = 0; + + bool Begin3dmTable( + ON::archive_mode expected_mode, + ON_3dmArchiveTableType table + ); + bool End3dmTable( + ON_3dmArchiveTableType table, + bool bSuccess + ); + void Internal_Increment3dmTableItemCount(); + bool Read3dmTableRecord( + ON_3dmArchiveTableType table, + void** ptr + ); + bool Internal_Begin3dmTableRecord( + ON_3dmArchiveTableType table + ); + +public: + /* + Returns: + Archive read/write mode + */ + ON::archive_mode Mode() const; + + /* + Returns: + True if Mode() is an archive reading mode. + */ + bool ReadMode() const; + + /* + Returns: + True if Mode() is an archive writing mode. + */ + bool WriteMode() const; + + /* + Returns: + True if Mode() is not set to a valid read or write mode. + */ + bool UnsetMode() const; + + /* + Returns: + If a 3dm archive is being read or written, the value of the archive + section (table) being read is returned. + ON_3dmArchiveTableType::Unset is returned if a table is + not actively being read or written. + Remarks: + Use ON_BinaryArchive::Mode() to determine if a binary archive is being + read or written. + Use ON_BinaryArchive::Previous3dmTable() to determine the most recent + table that was successfully read and finished. + */ + ON_3dmArchiveTableType Active3dmTable() const; + + static ON_ModelComponent::Type TableComponentType( + ON_3dmArchiveTableType table_type + ); + + /* + Returns: + If a 3dm archive is being read or written, the value of the most + recently read or written archive section (table) is returned. + Remarks: + Use ON_BinaryArchive::Mode() to determine if a binary archive is being + read or written. + */ + ON_3dmArchiveTableType Previous3dmTable() const; + + /* + Returns: + If a 3dm archive is being read or written and a failure occurs, + the first archive section (table) that failed to read or write + is returned. + */ + ON_3dmArchiveTableType FirstFailed3dmTable() const; + + /* + Returns: + Number of chunks read with a bad CRC + */ + unsigned int BadCRCCount() const; + + /* + Returns: + Number of critical errors + */ + unsigned int CriticalErrorCount() const; + + const ON_3dmArchiveTableStatus Archive3dmTableStatus( + ON_3dmArchiveTableType table_type + ); + +private: + + ON_3dmArchiveTableType TableTypeFromTypecode( unsigned int ); // table type from tcode + + ON_SimpleArray m_chunk; + + // stack of chunks + bool PushBigChunk( ON__UINT32 typecode, ON__INT64 value ); + + bool WriteChunkTypecode( ON__UINT32 ); + bool ReadChunkTypecode( ON__UINT32* ); + bool WriteChunkValue( ON__UINT32 typecode, ON__INT64 ); + bool WriteChunkLength( ON__UINT64 ); + bool ReadChunkValue( ON__UINT32 typecode, ON__INT64* value64 ); + bool FindMisplacedTable( + ON__UINT64 filelength, + const ON__UINT32 table_tocde, + const ON__UINT32 table_record_record, + const ON_UUID class_uuid, + const ON__UINT64 min_length_data + ); + + bool ReadObjectUserDataAnonymousChunk( + const ON__UINT64 length_TCODE_ANONYMOUS_CHUNK, + const int archive_3dm_version, + const unsigned int archive_opennurbs_version, + class ON_UserData* ud ); + +public: + size_t SizeofChunkLength() const; + +private: + bool WriteEOFSizeOfFile( ON__UINT64 ); + bool ReadEOFSizeOfFile( ON__UINT64* ); + + bool m_bDoChunkCRC = false; // true if active chunk crc status should be checked + // and updated. + bool m_bChunkBoundaryCheck = false; + +public: + /* + Returns: + true: + All read, write, and seek operations check to make sure they stay within + the current chunk boundary. + */ + bool ChunkBoundaryCheck() const; + + /* + Parameters: + bChunkBoundaryCheck - [in] + true: + All read, write, and seek operations check to make sure they stay within + the current chunk boundary. + */ + void SetChunkBoundaryCheck( + bool bChunkBoundaryCheck + ); + + +private: + class ON_CompressorImplementation* m_compressor = nullptr; + class ON_CompressorImplementation& Compressor(); + + // returns number of bytes written + size_t WriteDeflate( + size_t, // sizeof uncompressed input data + const void* // uncompressed input data + ); + bool ReadInflate( + size_t, // sizeof uncompressed input data + void* // buffer to hold uncompressed data + ); + bool CompressionInit(); + void CompressionEnd(); + +private: + // endian-ness of the cpu reading this file. + // 3dm files are always saved with little endian byte order. + const ON::endian m_endian = ON::Endian(); + + const ON::archive_mode m_mode = ON::archive_mode::unset_archive_mode; + + // user data and user table reading and writing filter + // If m_user_data_filter is empty, then all user data and user tables are read/written. + // If m_user_data_filter is not empty, then the first element has both ids=nil, precedence=0, + // and m_bSerialize = default setting. If there are any elements after the first element, + // the must have m_application_id != nil and the value of m_bSerialize overrides the + // default setting. If there are multiple elements with the same application and item id, + // the most recently added element is used. + ON_SimpleArray< ON_UserDataItemFilter > m_user_data_filter; + + /* + Description: + Sorts m_user_data_filter so items are ordered by + application id (nil is first) and precedence (low to high) + */ + void SortUserDataFilter(); + +private: + // 3dm write options + + // bits corresponed to ON::object_type flags. + // If the bit is set, then the mesh will be saved in the 3dm file. + // (RhinoCommon: if default is changed, sync with File3dmWriteOptions.RenderMeshesFlags) + ON__UINT32 m_save_3dm_render_mesh_flags = 0xFFFFFFFFU; + ON__UINT32 m_save_3dm_analysis_mesh_flags = 0xFFFFFFFFU; + + bool m_bSave3dmPreviewImage = true; + + bool m_bUseBufferCompression = true; + + bool m_bReservedA = false; + bool m_bReservedB = false; + bool m_bReservedC = false; + bool m_bReservedD = false; + bool m_bReservedE = false; + bool m_bReservedF = false; + +public: + /* + Description: + Specify model serial number attributes to assign to ON_ModelComponent + classes when they are read. + */ + void SetModelSerialNumber( + unsigned int model_serial_number, + unsigned int reference_model_serial_number, + unsigned int instance_definition_model_serial_number + ); + + /* + Description: + Clear() information set by SetModelSerialNumber() do not modify + ON_ModelComponent model serial number information when the classes + are read. + */ + void ClearModelSerialNumber(); + + /* + Parameters: + bCheckForRemappedIds - [in] + true if the archive is reading in a situation where component ids may get remapped. + */ + void SetCheckForRemappedIds( + bool bCheckForRemappedIds + ); + + /* + Returns: + True if the archive is reading in a situation where component ids may get remapped. + */ + bool CheckForRemappedIds() const; + + unsigned int ModelSerialNumber() const; + unsigned int ReferenceModelSerialNumber() const; + unsigned int InstanceDefinitionModelSerialNumber() const; + + /* + Description: + Writes the attributes identified by the component_filter parameter. + Parameters: + model_component - [in] + attributes_filter - [in] + A bitfield that determines which attributes will be written. + Returns: + false: critical failure. + true: writing can continue. + */ + bool WriteModelComponentAttributes( + const class ON_ModelComponent& model_component, + unsigned int attributes_filter + ); + + /* + Description: + Reads the attributes the Write() function writes. + Parameters: + model_component - [in/out] + component_filter - [out] + A bitfield that reports which attributes were read. + If the corresponding component on model_component is locked, + the read value is discared. + Returns: + false: critical failure. + true: reading can continue. + Remarks: + If locked attributes are read, thire values are ignored. + */ + bool ReadModelComponentAttributes( + ON_ModelComponent& model_component, + unsigned int* attributes_filter + ); + + /* + Description: + When writing archives, the index of the component in the model is + often different than the index of the component in the archive. + WriteComponentIndex converts the model id or index into + an archive index and writes the archive index value. + Remarks: + During writing, the m_manifest member stores + the model id and index as the "Component" value and + the 3dm archive id index as the "Manifest" value. + */ + bool Write3dmReferencedComponentIndex( + ON_ModelComponent::Type component_type, + int model_component_index + ); + + /* + Description: + When writing archives, the index of the component in the model is + often different than the index of the component in the archive. + WriteComponentIndex converts the model id or index into + an archive index and writes the archive index value. + Remarks: + During writing, the m_manifest member stores + the model id and index as the "Component" value and + the 3dm archive id index as the "Manifest" value. + */ + bool Write3dmReferencedComponentIndex( + ON_ModelComponent::Type component_type, + ON_UUID model_component_id + ); + + /* + Description: + When writing archives, the index of the component in the model is + often different than the index of the component in the archive. + WriteComponentIndex converts the model id or index into + an archive index and writes the archive index value. + Remarks: + During writing, the m_manifest member stores + the model id and index as the "Component" value and + the 3dm archive id index as the "Manifest" value. + */ + bool Write3dmReferencedComponentIndex( + const ON_ModelComponent& model_component + ); + + /* + Description: + When reading 3dm archives, model component indexes in the archive and + in the destination model are typically different. + This function basically reads and reverses the steps that WriteArchiveComponentIndex() + uses to adjust and write a model component index. + Parameters: + component_type - [in] + Type of the referenced component. + component_index - [out] + component reference index + Returns: + false - catestrophic read failure. + */ + bool Read3dmReferencedComponentIndex( + ON_ModelComponent::Type component_type, + int* component_index + ); + + bool Read3dmReferencedComponentIndexArray( + ON_ModelComponent::Type component_type, + ON_SimpleArray& component_index_array + ); + + /* + Returns: + True: (default state) + Read3dmReferencedComponentIndex() and Write3dmReferencedComponentIndex() will automatically + adjust compoents index references so they are valid. + False: (uncommon) + Read3dmReferencedComponentIndex() and Write3dmReferencedComponentIndex() will not + adjust compoents index references so they are valid. + */ + bool ReferencedComponentIndexMapping() const; + + /* + Description: + Set the archive's ReferencedComponentIndexMapping() state. + Parameters: + bEnableReferenceComponentIndexMapping - [in] + True: (default state) + Read3dmReferencedComponentIndex() and Write3dmReferencedComponentIndex() will automatically + adjust compoents index references so they are valid. + False: (uncommon) + Read3dmReferencedComponentIndex() and Write3dmReferencedComponentIndex() will not + adjust compoents index references so they are valid. This is only used with the + component being read or written is not the model but is a copy of one + in a different model (linked instance definitions being the common situation). + */ + void SetReferencedComponentIndexMapping( + bool bEnableReferenceComponentIndexMapping + ); + + /* + Description: + WriteComponentId converts the model ID into + an archive ID and writes the archive Id value. + Generally, the ID of the component in the model is + identical to the ID of the component in the archive. + In rare situations this is not the case. + Remarks: + During writing, the m_manifest member stores + the model ID as the "Component" value and + the 3dm archive ID as the "Manifest" value. + */ + bool Write3dmReferencedComponentId( + ON_ModelComponent::Type component_type, + ON_UUID model_component_id + ); + + bool Write3dmReferencedComponentId( + const ON_ModelComponent& model_component + ); + + /* + Description: + When reading 3dm archives, the model component ID in the archive + and in the destination model are often identical, but sometimes + different. For example, the when the same template is used + to create multiple models and files and the models from those files + are merged into a single file, there will be ID collisions. + For components that are identified by name, like layers and dimension styles, + this is not a problem. For components like instance definitions that have + a more complicated set of merging rules, it is critical that + references to instance definition ids be updated from values in the arcive + to values in the model. + uses to adjust and write a model component Id. + Parameters: + component_type - [in] + Type of the referenced component. + component_id - [out] + component reference ID + Returns: + false - catestrophic read failure. + */ + bool Read3dmReferencedComponentId( + ON_ModelComponent::Type component_type, + ON_UUID* component_id + ); + + /* + Returns: + True: (default state) + Read3dmReferencedComponentId() and Write3dmReferencedComponentId() will automatically + adjust compoents Id references so they are valid. + False: (uncommon) + Read3dmReferencedComponentId() and Write3dmReferencedComponentId() will not + adjust compoents Id references so they are valid. + */ + bool ReferencedComponentIdMapping() const; + + /* + Description: + Set the archive's ReferencedComponentIdMapping() state. + Parameters: + bEnableReferenceComponentIdMapping - [in] + True: (default state) + Read3dmReferencedComponentId() and Write3dmReferencedComponentId() will automatically + adjust compoents Id references so they are valid. + False: (uncommon) + Read3dmReferencedComponentId() and Write3dmReferencedComponentId() will not + adjust compoents Id references so they are valid. This is only used with the + component being read or written is not the model but is a copy of one + in a different model (linked instance definitions being the common situation). + */ + void SetReferencedComponentIdMapping( + bool bEnableReferenceComponentIdMapping + ); + + +public: + // Reading and writing operations fill in the manifest. + // ON_ComponentManifest query tools can be used to look up + // model and archive index and id information. + // + // The component and manifest id values are always identical + // during reading and writing. + // + // When writing, the component indices are model indices + // and the manifest indices are the archive indices that + // were written in the file. + // + // When reading, the component indices are "index" values read + // from the archive and the manifest indices are the order they + // were read. When files are valid, these indices are the same. + // + // After reading is complete, the application can use + // ON_ComponentManifest::UpdateManifestItem() to convert + // the component index and id values to model index and + // id values. + const class ON_ComponentManifest& Manifest() const; + const class ON_ManifestMap& ManifestMap() const; + bool AddManifestMapItem( + const class ON_ManifestMapItem& map_item + ); + + /* + Description: + When an application is reading an archive and changes the + index or id of a model component as it is added to the model, + then it needs to update the manifest map item destination settings. + Parameters: + map_item - [in] + The source type, index and id match what was read from the 3dm archive. + The destination index and id are the values assigned by the + application reading the 3dm archive. + */ + bool UpdateManifestMapItemDestination( + const class ON_ManifestMapItem& map_item + ); + +private: + // Reading: + // m_manifest is a list of what has been read from the 3dm archive. + // m_manifest_map is a map from the 3dm archive index and id to the + // model index and id. The map is maintained by the application + // reading the file calling AddManifestMapItem() when read items + // are added to the model. + // Writing: + // m_manifest is a list of what has been written to the 3dm archive. + // m_manifest_map maps model index and id to 3dm archive index and id. + // m_manifest_map is automatically maintained by the ON_BinaryArchive + // writing code because the index and id changes happen internally + // in 3dm archive writing functions. + ON_ComponentManifest m_manifest; + ON_ManifestMap m_manifest_map; + + // True: (default state) + // Read3dmReferencedComponentIndex() and Write3dmReferencedComponentIndex() will automatically + // adjust component index references so they are valid. + // False: (uncommon) + // Read3dmReferencedComponentIndex() and Write3dmReferencedComponentIndex() will not + // adjust component index references so they are valid. + bool m_bReferencedComponentIndexMapping = true; + + // True: (default state) + // Read3dmReferencedComponentId() and Write3dmReferencedComponentId() will automatically + // adjust component id references so they are valid. + // False: (uncommon) + // Read3dmReferencedComponentId() and Write3dmReferencedComponentId() will not + // adjust component id references so they are valid. + bool m_bReferencedComponentIdMapping = true; + +private: + // If the archive is a file system item (file), then + // these strings specify the name of the file + ON_wString m_archive_file_name; + ON_wString m_archive_directory_name; + ON_wString m_archive_full_path; // = archive_directory_name + path separator + archive_file_name + + // If the archive is being read, this is the name + // of the file where it was written. + // If false = ON_wString::EqualPath(m_archive_full_path,m_archive_saved_as_full_path), + // then file has been moved or copied since it was saved. + // When reading a file, this value is set by ON_BinaryArchive::Read3dmProperties() + // When writing a file, this value is set by SetArchiveFullPath(). + ON_wString m_archive_saved_as_full_path; + + /* + ON_BinaryArchive::Read3dmProperties() sets m_bArchiveMoved to true if + the 3dm archive being read is not in the same file system location as where + it was written. This piece of information is useful when attempting to find + referenced files that are not where they were when the 3dm archive was saved. + */ + bool m_b3dmArchiveMoved = false; + +public: + const ON_wString& ArchiveFileName() const; + const ON_wString& ArchiveDirectoryName() const; + const ON_wString& ArchiveFullPath() const; + const ON_wString& ArchiveSavedAsFullPath() const; + + const wchar_t* ArchiveFileNameAsPointer() const; + const wchar_t* ArchiveDirectoryNameAsPointer() const; + const wchar_t* ArchiveFullPathAsPointer() const; + const wchar_t* ArchiveSavedAsFullPathPointer() const; + + /* + Returns: + true if the 3dm archive being read is not in the same file system + location as where is was saved. + */ + bool ArchiveFileMoved() const; + + /* + Parameters: + archive_full_path - [in] + full path to file being read or written + */ + void SetArchiveFullPath( + const wchar_t* archive_full_path + ); + + /* + Parameters: + archive_directory_name - [in] + full path file being written + archive_file_name - [in] + name of file being written + */ + void SetArchiveFullPath( + const wchar_t* archive_directory_name, + const wchar_t* archive_file_name + ); + +private: + bool m_SetModelComponentSerialNumbers = false; + bool m_bCheckForRemappedIds = false; + // Expert testers who need to create a corrupt 3dm file + // call IntentionallyWriteCorrupt3dmStartSectionForExpertTesting() before writing + // the 3dm file. + unsigned char m_IntentionallyWriteCorrupt3dmStartSection = 0; + bool m_reservedB = false; + unsigned int m_model_serial_number = 0; + unsigned int m_reference_model_serial_number = 0; + unsigned int m_instance_definition_model_serial_number = 0; + unsigned int m_reserved1 = 0; + ON__UINT_PTR m_reserved2 = 0; + +private: + // ids of plug-ins that support saving older (V3) versions + // of user data. This information is filled in from the + // list of plug-ins passed in whenteh settings are saved. + ON_SimpleArray m_V3_plugin_id_list; + + struct ON__3dmV1LayerIndex* m_V1_layer_list = nullptr; + +private: + // m_archive_text_style_table and m_archive_dim_style_table are private and not used by inline functions. + // No DLL interface is required. + + mutable ON_3dmAnnotationContext m_annotation_context; + +#pragma ON_PRAGMA_WARNING_PUSH +#pragma ON_PRAGMA_WARNING_DISABLE_MSC( 4251 ) + // The m_archive_text_style_table[] array is used when reading archives. + // It contains the text styles read from the archive + ON_SimpleArray< ON_TextStyle* > m_archive_text_style_table; + + // The m_dim_style_index_text_style_index[] is used when reading archives. + // ON_2dex.i = text style archive index. + // ON_2dex.j = dimension style archive index. + ON_SimpleArray< ON_2dex > m_text_style_to_dim_style_archive_index_map; + + // This m_archive_dim_style_table[] array is used when reading + // and writing archives. This information is required when reading + // and writing archives from previous versions. + // - When writing, the dimstyles are copies of the model dimstyles + // and have model ids and indices. + // - When reading, the dimstyles are copies of the archive dimstyles + // and have archive ids and indices. + ON_SimpleArray< ON_DimStyle* > m_archive_dim_style_table; + ON_SimpleArray< ON_DimStyle* > m_DELETE_ME_archive_dim_style_overrides; + bool m_bLegacyOverrideDimStylesInArchive = false; + + const ON_DimStyle* m_archive_current_dim_style = nullptr; + + // m_archive_dim_style_table_status values: + // READING: + // 0 = not started + // 1 = BeginWrite3dmDimStyle() has been called, + // m_archive_text_style_table[] is valid, + // and Read3dmDimStyle() can be called. + // 2 = All entries of m_archive_text_style_table[] have been read by Read3dmDimStyle(). + // 3 = EndRead3dmDimStyle() has been called. + // WRITING: + // 0 = not started + // 1 = BeginWrite3dmDimStyle() has been called and Write3dmDimStyle() can be called. + // 2 = Write3dmDimStyle() has saved at least one dimstyle + // 3 = EndWrite3dmDimStyle() has been called. + unsigned int m_archive_dim_style_table_status = 0; + + // index in m_archive_text_style_table[] where Read3dmDimStyle() should + // begin searching for the next dimstyle to "read". + unsigned int m_archive_dim_style_table_read_index = ON_UNSET_UINT_INDEX; + +#pragma ON_PRAGMA_WARNING_POP + +public: + /* + Description: + When reading version 5 and earlier files that contain a text style + table, this function can be used to get the archive text style from + the archive text style index. This function is used when reading + V5 and pre August 2016 V6 ON_DimStyle information. + */ + const ON_TextStyle* ArchiveTextStyleFromArchiveTextStyleIndex( + int archive_text_style_index + ) const; + +private: + ON_String m_archive_3dm_start_section_comment = ON_String::EmptyString; + class ON_3dmProperties* m_archive_3dm_properties = nullptr; + class ON_3dmSettings* m_archive_3dm_settings = nullptr; + +private: + // prohibit default construction, copy construction, and operator= + ON_BinaryArchive() = delete; + ON_BinaryArchive( const ON_BinaryArchive& ) = delete; // no implementation + ON_BinaryArchive& operator=( const ON_BinaryArchive& ) = delete; // no implementation +}; + +class ON_CLASS ON_3dmGoo +{ + // used to store goo +public: + ON_3dmGoo(); + ~ON_3dmGoo(); + ON_3dmGoo( const ON_3dmGoo& ); + ON_3dmGoo& operator=( const ON_3dmGoo& ); + + void Dump(ON_TextLog&) const; + + unsigned int m_typecode; + int m_value; + unsigned char* m_goo; + ON_3dmGoo* m_next_goo; + ON_3dmGoo* m_prev_goo; +}; + + +class ON_CLASS ON_BinaryFile : public ON_BinaryArchive +{ +public: + ON_BinaryFile( + ON::archive_mode archive_mode + ); + + /* + Description: + Create an ON_BinaryArchive that reads/writes from an ordinary file. + Parameters: + archive_mode - [in] + fp - [in] + If a file is being read, fp is the pointer returned + from ON_FileStream::Open(...,"rb"). + If a file is being written, fp is the pointer returned + from ON_FileStream::Open(...,"wb"). + */ + ON_BinaryFile( + ON::archive_mode archive_mode, + FILE* fp + ); + + /* + Description: + Create an ON_BinaryArchive that reads/writes from an ordinary file. + Parameters: + archive_mode - [in] + file_system_path - [in] + path to file being read or written. + */ + ON_BinaryFile( + ON::archive_mode archive_mode, + const wchar_t* file_system_path + ); + + /* + Description: + Create an ON_BinaryArchive that reads/writes from an ordinary file. + Parameters: + archive_mode - [in] + file_system_path - [in] + path to file being read or written. + */ + ON_BinaryFile( + ON::archive_mode archive_mode, + const char* file_system_path + ); + + ~ON_BinaryFile(); + +protected: + // ON_BinaryArchive overrides + ON__UINT64 Internal_CurrentPositionOverride() const override; + bool Internal_SeekFromCurrentPositionOverride(int byte_offset) override; + bool Internal_SeekToStartOverride() override; + +public: + // ON_BinaryArchive overrides + bool AtEnd() const override; + +protected: + // ON_BinaryArchive overrides + size_t Internal_ReadOverride( size_t, void* ) override; // return actual number of bytes read (like fread()) + size_t Internal_WriteOverride( size_t, const void* ) override; + bool Flush() override; + +public: + + //// fseek from end (since the file has an end) + //bool SeekFromEnd( int ); + + ////////// + // To use custom memory buffering instead of relying + // on fread()/fwrite()'s build in buffering, call + // EnableMemoryBuffer() with the buffer size immediately + // after constructing the ON_BinaryFile. There appear + // to be enough bugs in existing Windows NT/2000 NETWORK + // I/O that using this hack will speed up I/O by factors + // of 10 to 100. + void EnableMemoryBuffer( + int=16384 // capacity of memory buffer + ); + + /* + Returns: + True if a file stream is open (nullptr != m_fp). + */ + bool FileIsOpen() const; + + void CloseFile(); + +private: + // Implementation + FILE* m_fp = nullptr; + bool m_bCloseFileInDestructor = false; + + // if m_memory_buffer_capacity is zero, then Write() uses + // fwrite() directly. If m_memory_buffer_capacity is + // greater than zero, then Write() buffers its results + // into m_memory_buffer. This is provided to work around + // bugs in some networks that result in extremely slow + // performance when seeking is used. + size_t m_memory_buffer_capacity = 0; + size_t m_memory_buffer_size = 0; + size_t m_memory_buffer_ptr = 0; + unsigned char* m_memory_buffer = nullptr; + +private: + // prohibit default construction, copy construction, and operator= + ON_BinaryFile() = delete; + ON_BinaryFile(const ON_BinaryFile&) = delete; + ON_BinaryFile& operator=(const ON_BinaryFile&) = delete; +}; + +class ON_CLASS ON_BinaryArchiveBuffer : public ON_BinaryArchive +{ +public: + /* + Description: + Create an ON_BinaryArchive that reads/writes from an ON_Buffer. + Parameters: + mode - [in] + buffer - [in] + Remarks: + If a non-null buffer is specifed, then do not call SetBuffer() + */ + ON_BinaryArchiveBuffer( ON::archive_mode, ON_Buffer* buffer ); + + virtual ~ON_BinaryArchiveBuffer(); + + /* + Description: + If the ON_BinaryArchiveBuffer class is created with the constructor + that has a single "mode" parameter, then use SetBuffer() + to specify the buffer to read/write from before using + the ON_BinaryArchiveBuffer. + Parameters: + buffer - [in] + Returns: + True if the buffer is set. Once the buffer is set it + cannot be changed. + */ + bool SetBuffer( ON_Buffer* buffer ); + + /* + Returns: + Buffer being read/written. + */ + ON_Buffer* Buffer() const; + +protected: + // ON_BinaryArchive overrides + ON__UINT64 Internal_CurrentPositionOverride() const override; + bool Internal_SeekFromCurrentPositionOverride(int byte_offset) override; + bool Internal_SeekToStartOverride() override; + +public: + // ON_BinaryArchive overrides + bool AtEnd() const override; + +protected: + // ON_BinaryArchive overrides + size_t Internal_ReadOverride( size_t, void* ) override; // return actual number of bytes read (like fread()) + size_t Internal_WriteOverride( size_t, const void* ) override; + bool Flush() override; + +private: + // Buffer being read/written. + ON_Buffer* m_buffer; + +private: + // prohibit use - you should specify a buffer. + ON_BinaryArchiveBuffer( ON::archive_mode ); +private: + // prohibit default construction, copy construction, and operator= + ON_BinaryArchiveBuffer( ); // no implementation + ON_BinaryArchiveBuffer( const ON_BinaryArchiveBuffer& ); // no implementation + ON_BinaryArchiveBuffer& operator=( const ON_BinaryArchiveBuffer& ); // no implementation +}; + + +class ON_CLASS ON_Read3dmBufferArchive : public ON_BinaryArchive +{ +public: + + /* + Description: + Construct an ON_BinaryArchive for reading information from a memory buffer. + Parameters: + sizeof_buffer - [in] size of buffer in bytes (>0) + buffer - [in] memory buffer containing binary archive + bCopyBuffer - [in] + true - copy the input buffer. + Useful when the buffer may be destroyed while this class is still in use. + false - Do not copy the input buffer. + In this case you are responsible for making certain the input buffer + is valid while this class is in use. + archive_3dm_version - [in] (1,2,3,4,5,50,60,70,...) + archive_opennurbs_version - [in] + */ + ON_Read3dmBufferArchive( + size_t sizeof_buffer, + const void* buffer, + bool bCopyBuffer, + int archive_3dm_version, + unsigned int archive_opennurbs_version + ); + + ~ON_Read3dmBufferArchive(); + + /* + Returns: + value of m_sizeof_buffer + */ + size_t SizeOfBuffer() const; + + /* + Returns: + value of m_buffer + */ + const void* Buffer() const; + +protected: + // ON_BinaryArchive overrides + ON__UINT64 Internal_CurrentPositionOverride() const override; + bool Internal_SeekFromCurrentPositionOverride(int byte_offset) override; + bool Internal_SeekToStartOverride() override; + +public: + // ON_BinaryArchive overrides + bool AtEnd() const override; + +protected: + // ON_BinaryArchive overrides + size_t Internal_ReadOverride( size_t, void* ) override; // return actual number of bytes read (like fread()) + size_t Internal_WriteOverride( size_t, const void* ) override; + bool Flush() override; + +private: + void* m_p; + const unsigned char* m_buffer; + size_t m_sizeof_buffer; + size_t m_buffer_position; + ON__INT_PTR m_reserved1; + ON__INT_PTR m_reserved2; + ON__INT_PTR m_reserved3; + ON__INT_PTR m_reserved4; + +private: + // prohibit use - no implementation + ON_Read3dmBufferArchive(); + ON_Read3dmBufferArchive( const ON_Read3dmBufferArchive& ); + ON_Read3dmBufferArchive& operator=(const ON_Read3dmBufferArchive&); +}; + +class ON_CLASS ON_Write3dmBufferArchive : public ON_BinaryArchive +{ +public: + + /* + Description: + Construct an ON_BinaryArchive for writing information to a memory buffer. + Parameters: + initial_sizeof_buffer - [in] + initial size of buffer in bytes (>=0) + If you are unable to estimate the size you will need, pass in zero. + max_sizeof_buffer - [in] + maximum size of buffer in bytes (>=0) + If max_sizeof_buffer > 0 and the amount of information saved + requires a buffer larger than this size, then writing fails. + If max_sizeof_buffer <= 0, then no buffer size limits are enforced. + archive_3dm_version - [in] (0, ,2,3,4,5,50,60,70,...) + Pass 0 or ON_BinaryArchive::CurrentArchiveVersion() to write the + version of opennurbs archives used by lastest version of Rhino. + archive_opennurbs_version - [in] + */ + ON_Write3dmBufferArchive( + size_t initial_sizeof_buffer, + size_t max_sizeof_buffer, + int archive_3dm_version, + unsigned int archive_opennurbs_version + ); + + ~ON_Write3dmBufferArchive(); + + /* + Returns: + Size of the archive in bytes. + */ + size_t SizeOfArchive() const; + + /* + Returns: + value of m_sizeof_buffer + */ + size_t SizeOfBuffer() const; + + /* + Returns: + value of m_buffer. + SizeOfArchive() reports the number of bytes + written to this buffer. + SizeOfBuffer() reports the number of bytes + allocated in this buffer. + + */ + const void* Buffer() const; + + /* + Returns: + The pointer to the buffer and sets all + members on this archive back to zero. + The caller is responsible for calling onfree() on + the pointer when finished with the buffer. + */ + void* HarvestBuffer(); + +protected: + // ON_BinaryArchive overrides + ON__UINT64 Internal_CurrentPositionOverride() const override; + bool Internal_SeekFromCurrentPositionOverride(int byte_offset) override; + bool Internal_SeekToStartOverride() override; + +public: + // ON_BinaryArchive overrides + bool AtEnd() const override; + +protected: + // ON_BinaryArchive overrides + size_t Internal_ReadOverride( size_t, void* ) override; // return actual number of bytes read (like fread()) + size_t Internal_WriteOverride( size_t, const void* ) override; + bool Flush() override; + +private: + void AllocBuffer(size_t); + void* m_p; + unsigned char* m_buffer; + size_t m_sizeof_buffer; + const size_t m_max_sizeof_buffer; + size_t m_sizeof_archive; + size_t m_buffer_position; + ON__INT_PTR m_reserved1; + ON__INT_PTR m_reserved2; + ON__INT_PTR m_reserved3; + ON__INT_PTR m_reserved4; + +private: + // prohibit use - no implementation + ON_Write3dmBufferArchive(); + ON_Write3dmBufferArchive( const ON_Write3dmBufferArchive& ); + ON_Write3dmBufferArchive& operator=(const ON_Write3dmBufferArchive&); +}; + +/* +Description: + Create a simple archive that contains a single or multiple geometric object(s). +Parameters: + archive - [in] destination archive. + version - [in] (0, 2, 3, 4,50,60,70,...) format version.archive version number. + Version 2 format can be read by Rhino 2 and Rhino 3. Version + 3 format can be read by Rhino 3. + Pass 0 or ON_BinaryArchive::CurrentArchiveVersion() to write + the latest version of archives supported by Rhino. + object - [in] object to be saved in the archive's object table. + This is typically some type of ON_Curve, ON_Surface, ON_Mesh, + or ON_Brep. + object_list - [in] objects to be saved in the archive's object table. + These are typically some type of ON_Curve, ON_Surface, ON_Mesh, + or ON_Brep. + object_list_count - [in] explicit count of number of objects in object_list. +Returns: + @untitled table + true archive successfully written. + false archive not successfully written. +Example: + + const char* filename = "myfile.3dm"; + FILE* fp = ON::OpenFile( filename, "wb" ); + ON_BinaryFile file( fp, ON::archive_mode::write3dm ); + bool ok = ON_WriteArchive( archive, geometry ); + ON::CloseFile( fp ); + +Remarks: + For ON_WriteOneObjectArchive the object table in the archive will contain a single + object. +*/ +ON_DECL +bool ON_WriteOneObjectArchive( + ON_BinaryArchive& archive, + int version, + const ON_Object& object + ); + +ON_DECL +bool ON_WriteOneObjectArchive( + const wchar_t* filename, + const ON_Object& object + ); + +ON_DECL +bool ON_WriteMultipleObjectArchive( + ON_BinaryArchive& archive, + int version, + const ON_SimpleArray& object_list + ); + +ON_DECL +bool ON_WriteMultipleObjectArchive( + ON_BinaryArchive& archive, + int version, + size_t object_list_count, + const ON_Object* const* object_list + ); + +bool ON_WriteMultipleObjectArchive( + const wchar_t* filename, + int version, + size_t object_list_count, + const ON_Object* const* object_list + ); + + +/* +Opens a debug archive file + Uses directory set by ON_SetDebugWriteObjectDirectory(const wchar_t* ). + creates a file named "debug_file_nnnn.3dm" +Example: + ON_DebugWriteArchive debug; + if(debug.m_Archive) + ON_WriteArchive( *debug.m_Archive, geometry ); + +*/ +class ON_CLASS ON_DebugWriteArchive +{ +public: + /* + Creates a file in N_DebugWriteObjectDirectory() and allocates archive to write to + that file. + */ + ON_DebugWriteArchive(); + ~ON_DebugWriteArchive(); + + // check for nullptr before using + // Destructor closes archive and deletes it. + + ON_BinaryArchive* Archive() const; + + // Name of the archive file. + // = .../debug_file_NNNNN.3dm where N = Number(). + const ON_wString& FilePath() const; + + // the number of the archive or 0 + unsigned int Number() const; + +private: + ON_BinaryArchive* m_archive = nullptr; + FILE* m_fp = nullptr; + unsigned int m_N = 0; + ON_wString m_file_path; + +private: + ON_DebugWriteArchive(const ON_DebugWriteArchive&) = delete; + ON_DebugWriteArchive& operator=(const ON_DebugWriteArchive&) = delete; +}; + +#endif diff --git a/opennurbs/Include/opennurbs_array.h b/opennurbs/Include/opennurbs_array.h new file mode 100644 index 0000000..ec3e586 --- /dev/null +++ b/opennurbs/Include/opennurbs_array.h @@ -0,0 +1,1794 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_ARRAY_INC_) +#define ON_ARRAY_INC_ + + + +//////////////////////////////////////////////////////////////// +// +// The ON_SimpleArray<> template is more efficient than the +// ON_ClassArray<> template, but ON_SimpleArray<> should not +// be used for arrays of classes that require explicit +// construction, destruction, or copy operators. +// +// Elements returned by AppendNew() are memset to zero. +// +// By default, ON_SimpleArray<> uses onrealloc() to manage +// the dynamic array memory. If you want to use something +// besides onrealloc() to manage the array memory, then override +// ON_SimpleArray::Realloc(). + +template class ON_SimpleArray +{ +public: + // construction //////////////////////////////////////////////////////// + + // These constructors create an array that uses onrealloc() to manage + // the array memory. + ON_SimpleArray() ON_NOEXCEPT; + + virtual + ~ON_SimpleArray(); + + // Copy constructor + ON_SimpleArray( const ON_SimpleArray& ); + + ////// Assignment operator + ////// Making a virtual operator= was a mistake. + ////// One reason might have been that the operator is virtual + ////// so ON_UuidList::operator= will be called when one is + ////// passed as an ON_SimpleArray& to a function? + ////virtual + ON_SimpleArray& operator=( const ON_SimpleArray& ); + +#if defined(ON_HAS_RVALUEREF) + // Clone constructor + ON_SimpleArray( ON_SimpleArray&& ) ON_NOEXCEPT; + + // Clone assignment + ON_SimpleArray& operator=( ON_SimpleArray&& ) ON_NOEXCEPT; +#endif + + ON_SimpleArray(size_t); // size_t parameter = initial capacity + + // emergency bailout /////////////////////////////////////////////////// + void EmergencyDestroy(void); // call only when memory used by this array + // may have become invalid for reasons beyond + // your control. EmergencyDestroy() zeros + // anything that could possibly cause + // ~ON_SimpleArray() to crash. + + // query /////////////////////////////////////////////////////////////// + + int Count() const; // number of elements in array + unsigned int UnsignedCount() const; + + int Capacity() const; // capacity of array + + unsigned int SizeOfArray() const; // amount of memory in the m_a[] array + + unsigned int SizeOfElement() const; // amount of memory in an m_a[] array element + + ON__UINT32 DataCRC(ON__UINT32 current_remainder) const; + + // The operator[] does to not check for valid indices. + // The caller is responsibile for insuring that 0 <= i < Capacity() + T& operator[]( int ); + T& operator[]( unsigned int ); + T& operator[]( ON__INT64 ); + T& operator[]( ON__UINT64 ); +#if defined(ON_RUNTIME_APPLE) + T& operator[]( size_t ); +#endif + + const T& operator[]( int ) const; + const T& operator[]( unsigned int ) const; + const T& operator[]( ON__INT64 ) const; + const T& operator[]( ON__UINT64 ) const; +#if defined(ON_RUNTIME_APPLE) + const T& operator[]( size_t ) const; +#endif + + operator T*(); // The cast operators return a pointer + operator const T*() const; // to the array. If Count() is zero, + // this pointer is nullptr. + + T* First(); + const T* First() const; // returns nullptr if count = 0 + + // At(index) returns nullptr if index < 0 or index >= count + T* At( int ); + T* At( unsigned int ); + T* At( ON__INT64 ); + T* At( ON__UINT64 ); + const T* At( int ) const; + const T* At( unsigned int ) const; + const T* At( ON__INT64 ) const; + const T* At( ON__UINT64 ) const; + + T* Last(); + const T* Last() const; // returns nullptr if count = 0 + + + // array operations //////////////////////////////////////////////////// + + T& AppendNew(); // Most efficient way to add a new element + // to the array. Increases count by 1. + // Returned element is memset to zero. + + void Append( const T& ); // Append copy of element. + // Increments count by 1. + + void Append( int, const T* ); // Append copy of an array T[count] + + void Prepend( int, const T* ); // Prepend copy of an array T[count] + + void Insert( int, const T& ); // Insert copy of element. Uses + // memmove() to perform any + // necessary moving. + // Increases count by 1. + + void Remove(); // Removes last element. Decrements + // count by 1. Does not change capacity. + + virtual + void Remove( int ); // Removes element. Uses memmove() to + // perform any necessary shifting. + // Decrements count by 1. Does not change + // capacity + + void Empty(); // Sets count to 0, leaves capacity untouched. + + void Reverse(); // reverse order + + void Swap(int,int); // swap elements i and j + + ////////// + // Search( e ) does a SLOW search of the array starting at array[0] + // and returns the index "i" of the first element that satisfies + // e == array[i]. (== is really memcmp()). If the search is not + // successful, then Search() returns -1. For Search(T) to work + // correctly, T must be a simple type. Use Search(p,compare()) + // for Ts that are structs/classes that contain pointers. Search() + // is only suitable for performing infrequent searchs of small + // arrays. Sort the array and use BinarySearch() for performing + // efficient searches. + int Search( const T& ) const; + + ////////// + // Search( p, compare ) does a SLOW search of the array starting + // at array[0] and returns the index "i" of the first element + // that satisfies compare(p,&array[i])==0. If the search is not + // successful, then Search() returns -1. Search() is only suitable + // for performing infrequent searches of small arrays. Sort the + // array and use BinarySearch() for performing efficient searches. + // See Also: ON_CompareIncreasing and ON_CompareDeccreasing + int Search( const T*, int (*)(const T*,const T*) ) const; + + ////////// + // BinarySearch( p, compare ) does a fast search of a sorted array + // and returns the smallest index "i" of the element that satisifies + // 0==compare(p,&array[i]). + // + // BinarySearch( p, compare, count ) does a fast search of the first + // count element sorted array and returns the smallest index "i" of + // the element that satisifies 0==compare(p,&array[i]). The version + // that takes a "count" is useful when elements are being appended + // during a calculation and the appended elements are not sorted. + // + // If the search is successful, + // BinarySearch() returns the index of the element (>=0). + // If the search is not successful, BinarySearch() returns -1. + // Use QuickSort( compare ) or, in rare cases and after meaningful + // performance testing using optimzed release builds, + // HeapSort( compare ) to sort the array. + // See Also: ON_CompareIncreasing and ON_CompareDeccreasing + int BinarySearch( const T*, int (*)(const T*,const T*) ) const; + int BinarySearch( const T*, int (*)(const T*,const T*), int ) const; + + int InsertInSortedList(const T&, int (*)(const T*, const T*)); + int InsertInSortedList(const T&, int (*)(const T*, const T*), int); + + ////////// + // Sorts the array using the heap sort algorithm. + // QuickSort() is generally the better choice. + bool HeapSort( int (*)(const T*,const T*) ); + + ////////// + // Sorts the array using the quick sort algorithm. + // See Also: ON_CompareIncreasing and ON_CompareDeccreasing + bool QuickSort( int (*)(const T*,const T*) ); + + ////////// + // Sorts the array using the quick sort algorithma and then removes duplicates. + // See Also: ON_CompareIncreasing and ON_CompareDeccreasing + bool QuickSortAndRemoveDuplicates( int (*)(const T*,const T*) ); + + /* + Description: + Sort() fills in the index[] array so that + array[index[i]] <= array[index[i+1]]. + The array is not modified. + + Parameters: + sort_algorithm - [in] + ON::sort_algorithm::quick_sort (best in general) or ON::sort_algorithm::heap_sort + Use ON::sort_algorithm::heap_sort only if you have done extensive testing with + optimized release builds and are confident heap sort is + significantly faster. + index - [out] an array of length Count() that is returned with + some permutation of (0,1,...,Count()-1). + compare - [in] compare function compare(a,b,p) should return + <0 if a0 if a>b. + Returns: + true if successful + */ + bool Sort( + ON::sort_algorithm sort_algorithm, + int* /* index[] */ , + int (*)(const T*,const T*) + ) const; + + /* + Description: + Sort() fills in the index[] array so that + array[index[i]] <= array[index[i+1]]. + The array is not modified. + + Parameters: + sort_algorithm - [in] + ON::sort_algorithm::quick_sort (best in general) or ON::sort_algorithm::heap_sort + Use ON::sort_algorithm::heap_sort only if you have done extensive testing with + optimized release builds and are confident heap sort is + significantly faster. + index - [out] an array of length Count() that is returned with + some permutation of (0,1,...,Count()-1). + compare - [in] compare function compare(a,b,p) should return + <0 if a0 if a>b. + p - [in] pointer passed as third argument to compare. + + Returns: + true if successful + */ + bool Sort( + ON::sort_algorithm sort_algorithm, + int*, // index[] + int (*)(const T*,const T*,void*), // int compare(const T*,const T*,void* p) + void* // p + ) const; + + ////////// + // Permutes the array so that output[i] = input[index[i]]. + // The index[] array should be a permutation of (0,...,Count()-1). + bool Permute( const int* /*index[]*/ ); + + ////////// + // Zeros all array memory. + // Count and capacity are not changed. + void Zero(); + + ////////// + // Sets all bytes in array memory to value. + // Count and capacity are not changed. + void MemSet(unsigned char); + + // memory managment //////////////////////////////////////////////////// + + T* Reserve( size_t ); // increase capacity to at least the requested value + + void Shrink(); // remove unused capacity + + void Destroy(); // onfree any memory and set count and capacity to zero + + // low level memory managment ////////////////////////////////////////// + + // By default, ON_SimpleArray<> uses onrealloc() to manage + // the dynamic array memory. If you want to use something + // besides onrealloc() to manage the array memory, then override + // Realloc(). The T* Realloc(ptr, capacity) should do the following: + // + // 1) If ptr and capacity are zero, return nullptr. + // 2) If ptr is nullptr, an capacity > 0, allocate a memory block of + // capacity*sizeof(T) bytes and return a pointer to this block. + // If the allocation request fails, return nullptr. + // 3) If ptr is not nullptr and capacity is 0, free the memory block + // pointed to by ptr and return nullptr. + // 4) If ptr is not nullptr and capacity > 0, then reallocate the memory + // block and return a pointer to the reallocated block. If the + // reallocation request fails, return nullptr. + // + // NOTE WELL: + // Microsoft's VC 6.0 realloc() contains a bug that can cause + // crashes and should be avoided. See MSDN Knowledge Base article + // ID Q225099 for more information. + virtual + T* Realloc(T*,int); // (re)allocated capacity*sizeof(T) bytes + + T* Array(); // The Array() function return the + + const T* Array() const; // m_a pointer value. + + void SetCount( int ); // If value is <= Capacity(), then + // sets count to specified value. + + T* SetCapacity( size_t ); // Shrink/grows capacity. If value + // is < current Count(), then count + // is reduced to value. + // + + int NewCapacity() const; // When the dynamic array needs to grow, + // this calculates the new value for m_capacity. + + /* + Description: + Expert user tool to take charge of the memory used by + the dyanmic array. + Returns: + A pointer to the array and zeros out this class. + The returned pointer is on the heap and must be + deallocated by calling onfree(). + */ + T* KeepArray(); + + /* + Description: + Do not use this version of SetArray(). Use the one that takes + a pointer, count and capacity. + */ + void SetArray(T*); + + /* + Description: + Expert user tool to set the memory used by the dyanmic array. + Parameters: + T* pointer - [in] + int count [in] + int capacity - [in] + m_a is set to pointer, m_count is set to count, and m_capacity + is set to capacity. It is critical that the pointer be one + returned by onmalloc(sz), where sz >= capacity*sizeof(T[0]). + */ + void SetArray(T*, int, int); + +protected: + // implimentation ////////////////////////////////////////////////////// + void Move( int /* dest index*/, int /* src index */, int /* element count*/ ); + T* m_a; // pointer to array memory + int m_count; // 0 <= m_count <= m_capacity + int m_capacity; // actual length of m_a[] +}; + + +//////////////////////////////////////////////////////////////// +// + +#if defined(ON_DLL_TEMPLATE) + +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; + +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; + +#endif + + + +//////////////////////////////////////////////////////////////// +// +// The ON_ClassArray<> template is designed to be used with +// classes that require non-trivial construction or destruction. +// Any class used with the ON_ClassArray<> template must have a +// robust operator=(). +// +// By default, ON_ClassArray<> uses onrealloc() to manage +// the dynamic array memory. If you want to use something +// besides onrealloc() to manage the array memory, then override +// ON_ClassArray::Realloc(). In practice this means that if your +// class has members with back-pointers, then you cannot use +// it in the defaule ON_ClassArray. See ON_ObjectArray +// for an example. +// +template class ON_ClassArray +{ +public: + // construction //////////////////////////////////////////////////////// + ON_ClassArray() ON_NOEXCEPT; + ON_ClassArray( size_t ); // size_t parameter = initial capacity + + // Copy constructor + ON_ClassArray( const ON_ClassArray& ); + + virtual + ~ON_ClassArray(); // override for struct member deallocation, etc. + + // Assignment operator + ON_ClassArray& operator=( const ON_ClassArray& ); + +#if defined(ON_HAS_RVALUEREF) + // Clone constructor + ON_ClassArray( ON_ClassArray&& ) ON_NOEXCEPT; + + // Clone Assignment operator + ON_ClassArray& operator=( ON_ClassArray&& ) ON_NOEXCEPT; +#endif + + // emergency bailout /////////////////////////////////////////////////// + void EmergencyDestroy(void); // call only when memory used by this array + // may have become invalid for reasons beyond + // your control. EmergencyDestroy() zeros + // anything that could possibly cause + // ~ON_ClassArray() to crash. + + // query /////////////////////////////////////////////////////////////// + + int Count() const; // number of elements in array + unsigned int UnsignedCount() const; + + int Capacity() const; // capacity of array + + unsigned int SizeOfArray() const; // amount of memory in the m_a[] array + + unsigned int SizeOfElement() const; // amount of memory in an m_a[] array element + + // The operator[] does to not check for valid indices. + // The caller is responsibile for insuring that 0 <= i < Capacity() + T& operator[]( int ); + T& operator[]( unsigned int ); + T& operator[]( ON__INT64 ); + T& operator[]( ON__UINT64 ); +#if defined(ON_RUNTIME_APPLE) + T& operator[]( size_t ); +#endif + + const T& operator[]( int ) const; + const T& operator[]( unsigned int ) const; + const T& operator[]( ON__INT64 ) const; + const T& operator[]( ON__UINT64 ) const; +#if defined(ON_RUNTIME_APPLE) + const T& operator[]( size_t ) const; +#endif + + operator T*(); // The cast operators return a pointer + operator const T*() const; // to the array. If Count() is zero, + // this pointer is nullptr. + T* First(); + const T* First() const; // returns nullptr if count = 0 + + // At(index) returns nullptr if index < 0 or index >= count + T* At( int ); + T* At( unsigned int ); + T* At( ON__INT64 ); + T* At( ON__UINT64 ); + const T* At( int ) const; + const T* At( unsigned int ) const; + const T* At( ON__INT64 ) const; + const T* At( ON__UINT64 ) const; + + T* Last(); + const T* Last() const; // returns nullptr if count = 0 + + + // array operations //////////////////////////////////////////////////// + + T& AppendNew(); // Most efficient way to add a new class + // to the array. Increases count by 1. + + void Append( const T& ); // Append copy of element. + // Increments count by 1. + + void Append( int, const T*); // Append copy of an array T[count] + + void Insert( int, const T& ); // Insert copy of element. Uses + // memmove() to perform any + // necessary moving. + // Increases count by 1. + + void Remove(); // Removes last element. Decrements + // count by 1. Does not change capacity. + + void Remove( int ); // Removes element. Uses memmove() to + // perform any necessary shifting. + // Decrements count by 1. Does not change + // capacity + + void Empty(); // Sets count to 0, leaves capacity untouched. + + void Reverse(); // reverse order + + void Swap(int,int); // swap elements i and j + + ////////// + // Search( p, compare ) does a SLOW search of the array starting + // at array[0] and returns the index "i" of the first element + // that satisfies compare(p,&array[i])==0. If the search is not + // successful, then Search() returns -1. Search() is only suitable + // for performing infrequent searches of small arrays. Sort the + // array and use BinarySearch() for performing efficient searches. + int Search( const T*, int (*)(const T*,const T*) ) const; + + ////////// + // BinarySearch( p, compare ) does a fast search of a sorted array + // and returns the smallest index "i" of the element that satisifies + // 0==compare(p,&array[i]). + // + // BinarySearch( p, compare, count ) does a fast search of the first + // count element sorted array and returns the smallest index "i" of + // the element that satisifies 0==compare(p,&array[i]). The version + // that takes a "count" is useful when elements are being appended + // during a calculation and the appended elements are not sorted. + // + // If the search is successful, + // BinarySearch() returns the index of the element (>=0). + // If the search is not successful, BinarySearch() returns -1. + // Use QuickSort( compare ) or, in rare cases and after meaningful + // performance testing using optimzed release builds, + // HeapSort( compare ) to sort the array. + // See Also: ON_CompareIncreasing and ON_CompareDeccreasing + int BinarySearch( const T*, int (*)(const T*,const T*) ) const; + int BinarySearch( const T*, int (*)(const T*,const T*), int ) const; + + int InsertInSortedList(const T&, int (*)(const T*, const T*)); + int InsertInSortedList(const T&, int (*)(const T*, const T*), int); + + ////////// + // Sorts the array using the heap sort algorithm. + // See Also: ON_CompareIncreasing and ON_CompareDeccreasing + // QuickSort() is generally the better choice. + virtual + bool HeapSort( int (*)(const T*,const T*) ); + + ////////// + // Sorts the array using the heap sort algorithm. + virtual + bool QuickSort( int (*)(const T*,const T*) ); + + /* + Description: + Sort() fills in the index[] array so that + array[index[i]] <= array[index[i+1]]. + The array is not modified. + + Parameters: + sort_algorithm - [in] + ON::sort_algorithm::quick_sort (best in general) or ON::sort_algorithm::heap_sort + Use ON::sort_algorithm::heap_sort only if you have done extensive testing with + optimized release builds and are confident heap sort is + significantly faster. + index - [out] an array of length Count() that is returned with + some permutation of (0,1,...,Count()-1). + compare - [in] compare function compare(a,b) should return + <0 if a0 if a>b. + + Returns: + true if successful + */ + bool Sort( + ON::sort_algorithm sort_algorithm, + int* /* index[] */ , + int (*)(const T*,const T*) + ) const; + + /* + Description: + Sort() fills in the index[] array so that + array[index[i]] <= array[index[i+1]]. + The array is not modified. + + Parameters: + sort_algorithm - [in] + ON::sort_algorithm::quick_sort (best in general) or ON::sort_algorithm::heap_sort + Use ON::sort_algorithm::heap_sort only if you have done extensive testing with + optimized release builds and are confident heap sort is + significantly faster. + index - [out] an array of length Count() that is returned with + some permutation of (0,1,...,Count()-1). + compare - [in] compare function compare(a,b,p) should return + <0 if a0 if a>b. + p - [in] pointer passed as third argument to compare. + + Returns: + true if successful + */ + bool Sort( + ON::sort_algorithm sort_algorithm, + int*, // index[] + int (*)(const T*,const T*,void*), // int compare(const T*,const T*,void* p) + void* // p + ) const; + + ////////// + // Permutes the array so that output[i] = input[index[i]]. + // The index[] array should be a permutation of (0,...,Count()-1). + bool Permute( const int* /*index[]*/ ); + + ////////// + // Destroys all elements and fills them with values + // set by the defualt constructor. + // Count and capacity are not changed. + void Zero(); + + // memory managment ///////////////////////////////////////////////// + + T* Reserve( size_t ); // increase capacity to at least the requested value + + void Shrink(); // remove unused capacity + + void Destroy(); // onfree any memory and set count and capacity to zero + + // low level memory managment /////////////////////////////////////// + + // By default, ON_ClassArray<> uses onrealloc() to manage + // the dynamic array memory. If you want to use something + // besides onrealloc() to manage the array memory, then override + // Realloc(). The T* Realloc(ptr, capacity) should do the following: + // + // 1) If ptr and capacity are zero, return nullptr. + // 2) If ptr is nullptr, an capacity > 0, allocate a memory block of + // capacity*sizeof(T) bytes and return a pointer to this block. + // If the allocation request fails, return nullptr. + // 3) If ptr is not nullptr and capacity is 0, free the memory block + // pointed to by ptr and return nullptr. + // 4) If ptr is not nullptr and capacity > 0, then reallocate the memory + // block and return a pointer to the reallocated block. If the + // reallocation request fails, return nullptr. + // + // NOTE WELL: + // Microsoft's VC 6.0 realloc() contains a bug that can cause + // crashes and should be avoided. See MSDN Knowledge Base article + // ID Q225099 for more information. + virtual + T* Realloc(T*,int); // (re)allocated capacity*sizeof(T) bytes + + T* Array(); // The Array() function return the + + const T* Array() const; // m_a pointer value. + + void SetCount( int ); // If value is <= Capacity(), then + // sets count to specified value. + + T* SetCapacity( size_t ); // Shrink/grows capacity. If value + // is < current Count(), then count + // is reduced to value. + + int NewCapacity() const; // When the dynamic array needs to grow, + // this calculates the new value for m_capacity. + + T* KeepArray(); // returns pointer to array and zeros + // out this class. Caller is responsible + // for calling destructor on each element + // and then using onfree() to release array + // memory. E.g., + // + // for (int i=capacity;i>=0;i--) { + // array[i].~T(); + // } + // onfree(array); + + /* + Description: + Do not use this version of SetArray(). Use the one that takes + a pointer, count and capacity: SetArray(pointer,count,capacity) + */ + void SetArray(T*); + + /* + Description: + Expert user tool to set the memory used by the dyanmic array. + Parameters: + T* pointer - [in] + int count - [in] 0 <= count <= capacity + int capacity - [in] + m_a is set to pointer, m_count is set to count, and m_capacity + is set to capacity. It is critical that the pointer be one + returned by onmalloc(sz), where sz >= capacity*sizeof(T[0]), + and that the in-place operator new has been used to initialize + each element of the array. + */ + void SetArray(T*, int, int); + +protected: + // implimentation ////////////////////////////////////////////////////// + void Move( int /* dest index*/, int /* src index */, int /* element count*/ ); + void ConstructDefaultElement(T*); + void DestroyElement(T&); + T* m_a; // pointer to array memory + int m_count; // 0 <= m_count <= m_capacity + int m_capacity; // actual length of m_a[] +}; + +#if defined(ON_DLL_TEMPLATE) + +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; + +#endif + +/* +Description: + ON_Object array is used to store lists of classes that are + derived from ON_Object. It differs from ON_ClassArray in + that the virtual ON_Object::MemoryRelocate function is called + when growing the dynamic array requires changing the location + of the memory buffer used to store the elements in the array. +*/ +template class ON_ObjectArray : public ON_ClassArray +{ +public: + ON_ObjectArray(); + ~ON_ObjectArray(); // override for struct member deallocation, etc. + ON_ObjectArray( size_t ); // size_t parameter = initial capacity + ON_ObjectArray( const ON_ObjectArray& ); + ON_ObjectArray& operator=( const ON_ObjectArray& ); + +#if defined(ON_HAS_RVALUEREF) + // Clone constructor + ON_ObjectArray( ON_ObjectArray&& ); + + // Clone Assignment operator + ON_ObjectArray& operator=( ON_ObjectArray&& ); +#endif + + ON__UINT32 DataCRC(ON__UINT32 current_remainder) const; + + // virtual ON_ClassArray override that + // calls MemoryRelocate on each element after + // the reallocation. + T* Realloc(T*,int); + + // virtual ON_ClassArray override that + // calls MemoryRelocate on each element after + // the heap sort. + // QuickSort() is generally the better choice. + bool HeapSort( int (*)(const T*,const T*) ); + + // virtual ON_ClassArray override that + // calls MemoryRelocate on each element after + // the quick sort. + bool QuickSort( int (*)(const T*,const T*) ); +}; + +class ON_CLASS ON_UuidPair +{ +public: + /* + Description: + Compares m_uuid[0] and ignores m_uuid[1] + */ + static + int CompareFirstUuid(const class ON_UuidPair*,const class ON_UuidPair*); + + /* + Description: + Compares m_uuid[1] and ignores m_uuid[0] + */ + static + int CompareSecondUuid(const class ON_UuidPair*,const class ON_UuidPair*); + + /* + Description: + Compares m_uuid[0] then m_uuid[1]. + */ + static + int Compare(const class ON_UuidPair*,const class ON_UuidPair*); + + ON_UuidPair(); + ON_UUID m_uuid[2]; +}; + +#if defined(ON_DLL_TEMPLATE) + +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray >; + +#endif + + +/* +Description: + The ON_UuidList class provides a tool to efficiently + maintain a list of uuids and determine if a uuid is + in the list. This class is based on the premise that + there are no duplicate uuids in the list. +*/ +class ON_CLASS ON_UuidList : private ON_SimpleArray +{ +public: + ON_UuidList(); + ON_UuidList(int capacity); + ~ON_UuidList(); + ON_UuidList(const ON_UuidList& src); + ON_UuidList& operator=(const ON_UuidList& src); + + /* + Description: + Fast uuid compare. Not necessarily the same + as ON_UuidCompare(). + */ + static + int CompareUuid( const ON_UUID* a, const ON_UUID* b ); + + /* + Returns: + Number of active uuids in the list. + */ + int Count() const; + + /* + Returns: + Array of uuids in the list. Sorted with + respect to ON_UuidList::CompareUuid(). + Remarks: + Calling AddUuid() may grow the dynamic array + and make the pointer invalid. + */ + const ON_UUID* Array() const; + + /* + Description: + Provides an efficient way to empty a list so that it + can be used again. + */ + void Empty(); + + /* + Description: + Destroy list. If list will be reused, Empty() is more + efficient. + */ + void Destroy(); + + void Reserve(size_t capacity); + + /* + Description: + Makes the uuid list as efficent as possible in both search + speed and memory usage. Use Compact() when a uuid list + will be in use but is not likely to be modifed. A list + that has been compacted can still be modified. + */ + void Compact(); + + /* + Description: + Adds a uuid to the list. + Parameters: + uuid - [in] id to add. + bCheckForDupicates - [in] if true, then the uuid + is not added if it is already in the list. + If you are certain that the uuid is not in the + list and you are going to have a large list of uuids, + then setting bCheckForDupicates=false will + speed up the addition of uuids. + Returns: + True if uuid was added. False if uuid was not added + because it is already in the collection. + */ + bool AddUuid(ON_UUID uuid, bool bCheckForDupicates=true); + + /* + Description: + Removes a uuid from the list. + Parameters: + uuid - [in] id to remove + Returns: + True if uuid was in the list and was removed. + False if uuid was not in the list. + */ + bool RemoveUuid(ON_UUID uuid); + + /* + Description: + Determine if a uuid is in the list. + Returns: + True if uuid is in the list. + */ + bool FindUuid(ON_UUID uuid) const; + + /* + Description: + Saves the uuid list in an archive. + Parameters: + archive - [in] archive to write to. + Returns: + true if write was successful. + */ + bool Write( + class ON_BinaryArchive& archive + ) const; + + /* + Description: + Saves the uuid list in an archive. + Parameters: + archive - [in] archive to write to. + bSortBeforeWrite - [in] + True if ids should be sorted before the write + so future lookups will be fast. False if + the current state of the sorted/unsorted bits + should be preserved. + Returns: + true if write was successful. + */ + bool Write( + class ON_BinaryArchive& archive, + bool bSortBeforeWrite + ) const; + + /* + Description: + Read the uuid list from an archive. + Parameters: + archive - [in] archive to read from. + Returns: + true if the read was successful. + */ + bool Read( + class ON_BinaryArchive& archive + ); + + /* + Description: + Read the uuid list from an archive. + Parameters: + archive - [in] + archive to read from. + bool bSortAfterRead - [in] + True if ids should be sorted after the read + so future lookups will be fast. False if + the state of the sorted/unsorted bits that + existed at write time should be preserved. + Returns: + true if the read was successful. + */ + bool Read( + class ON_BinaryArchive& archive, + bool bSortAferRead + ); + + /* + Description: + Append the uuids in this class to uuid_list. + Parameters: + uuid_list - [in/out] + Returns: + Number of uuids added to uuid_list. + */ + int GetUuids( + ON_SimpleArray& uuid_list + ) const; + + /* + Description: + This tool is used in rare situations when the object ids + stored in the uuid list need to be remapped. + Parameters: + uuid_remap - [in] + Is it critical that uuid_remap[] be sorted with respect + to ON_UuidPair::CompareFirstUuid. + */ + void RemapUuids( + const ON_SimpleArray& uuid_remap + ); + +private: + void PurgeHelper(); + void SortHelper(); + ON_UUID* SearchHelper(const ON_UUID*) const; + int m_sorted_count; + int m_removed_count; +}; + +/* +Description: + The ON_UuidList class provides a tool + to efficiently maintain a list of uuid-index + pairs and determine if a uuid is in the list. + This class is based on the premise that there are + no duplicate uuids in the list. +*/ +class ON_CLASS ON_UuidIndexList : private ON_SimpleArray +{ +public: + ON_UuidIndexList() = default; + ON_UuidIndexList(size_t capacity); + ~ON_UuidIndexList() = default; + ON_UuidIndexList(const ON_UuidIndexList& src); + ON_UuidIndexList& operator=(const ON_UuidIndexList& src); + + /* + Returns: + Number of active uuids in the list. + */ + unsigned int Count() const; + + /* + Description: + Provides an efficient way to empty a list so that it + can be used again. + */ + void RemoveAll(); + + void Reserve( size_t capacity ); + + /* + Description: + Adds a uuid-index pair to the list. + Parameters: + uuid - [in] id to add. + This uuid cannot be ON_max_uuid because ON_max_uuid + is + bCheckForDupicates - [in] if true, then the uuid + is not added if it is already in the list. + If you are certain that the uuid is not in the list + and you have a have a large collection of uuids, + then setting bCheckForDupicates=false will + speed up the addition of uuids. + Returns: + True if uuid was added. False if uuid was not added + because it is already in the collection. + */ + bool AddUuidIndex( + ON_UUID uuid, + int index, + bool bCheckForDupicates=true); + + /* + Description: + Removes an element with a matching uuid from the list. + Parameters: + uuid - [in] id to remove + Returns: + True if an element was removed. False if the uuid + was not in the list. + */ + bool RemoveUuid( + ON_UUID uuid + ); + + /* + Description: + Determine if an element with a uuid is in the list. + Parameters: + index - [out] if not nullptr and a matching uuid is found, + then *index is set to the value of the index. + Returns: + True if an element was found. Returns false if + the uuid is not in the list. + */ + bool FindUuid(ON_UUID uuid) const; + bool FindUuid(ON_UUID uuid, int* index) const; + + /* + Description: + Determine if a uuid-index pair is in the list. + Returns: + True if the uuid-index pair is in the list. + Returns false if the uuid-index pair is not + in the list. + */ + bool FindUuidIndex(ON_UUID uuid, int index) const; + + /* + Description: + Append the uuids in this class to uuid_list. + Parameters: + uuid_list - [in/out] + Returns: + Number of uuids added to uuid_list. + */ + unsigned int GetUuids( + ON_SimpleArray& uuid_list + ) const; + + /* + Description: + If you will perform lots of searches before the next + change to the list, then calling ImproveSearchSpeed() + will speed up the searches by culling removed objects + and completely sorting the list so only a binary search + is required. You may edit the list at any time after + calling ImproveSearchSpeed(). If you are performing + a few searches between edits, then excessive calling + of ImproveSearchSpeed() may actually decrease overall + program performance. + */ + void ImproveSearchSpeed(); + +private: + ON_UuidIndex* SearchHelper(const ON_UUID*) const; + unsigned int m_sorted_count = 0; + unsigned int m_removed_count = 0; +}; + + +/* +Description: + The ON_UuidList class provides a tool + to efficiently maintain a list of uuid-pointer + pairs and determine if a uuid is in the list. + This class is based on the premise that there are + no duplicate uuids in the list. +*/ +class ON_CLASS ON_UuidPtrList : private ON_SimpleArray +{ +public: + ON_UuidPtrList() = default; + ON_UuidPtrList(size_t capacity); + ~ON_UuidPtrList() = default; + ON_UuidPtrList(const ON_UuidPtrList& src); + ON_UuidPtrList& operator=(const ON_UuidPtrList& src); + + /* + Returns: + Number of active uuids in the list. + */ + unsigned int Count() const; + + /* + Description: + Provides an efficient way to empty a list so that it + can be used again. + */ + void RemoveAll(); + + void Reserve( size_t capacity ); + + /* + Description: + Adds a uuid-index pair to the list. + Parameters: + uuid - [in] id to add. + This uuid cannot be ON_max_uuid because ON_max_uuid + is + bCheckForDupicates - [in] if true, then the uuid + is not added if it is already in the list. + If you are certain that the uuid is not in the list + and you have a have a large collection of uuids, + then setting bCheckForDupicates=false will + speed up the addition of uuids. + Returns: + True if uuid was added. False if uuid was not added + because it is already in the collection. + */ + bool AddUuidPtr( + ON_UUID uuid, + ON__UINT_PTR ptr, + bool bCheckForDupicates=true); + + /* + Description: + Removes an element with a matching uuid from the list. + Parameters: + uuid - [in] id to remove + Returns: + True if an element was removed. False if the uuid + was not in the list. + */ + bool RemoveUuid( + ON_UUID uuid + ); + + /* + Description: + Determine if an element with a uuid is in the list. + Parameters: + ptr - [out] if not nullptr and a matching uuid is found, + then *ptr is set to the value of the m_ptr. + Returns: + True if an element was found. Returns false if + the uuid is not in the list. + */ + bool FindUuid(ON_UUID uuid) const; + bool FindUuid(ON_UUID uuid, ON__UINT_PTR* ptr) const; + + /* + Description: + Determine if a uuid-index pair is in the list. + Returns: + True if the uuid-index pair is in the list. + Returns false if the uuid-index pair is not + in the list. + */ + bool FindUuidPtr(ON_UUID uuid, ON__UINT_PTR index) const; + + /* + Description: + Append the uuids in this class to uuid_list. + Parameters: + uuid_list - [in/out] + Returns: + Number of uuids added to uuid_list. + */ + unsigned int GetUuids( + ON_SimpleArray& uuid_list + ) const; + + /* + Description: + If you will perform lots of searches before the next + change to the list, then calling ImproveSearchSpeed() + will speed up the searches by culling removed objects + and completely sorting the list so only a binary search + is required. You may edit the list at any time after + calling ImproveSearchSpeed(). If you are performing + a few searches between edits, then excessive calling + of ImproveSearchSpeed() may actually decrease overall + program performance. + */ + void ImproveSearchSpeed(); + +private: + ON_UuidPtr* SearchHelper(const ON_UUID*) const; + unsigned int m_sorted_count = 0; + unsigned int m_removed_count = 0; +}; + + +/* +Description: + The ON_UuidPairList class provides a tool + to efficiently maintain a list of uuid pairs + and determine if a uuid is in the list. + This class is based on the premise that there are + no duplicate uuids in the list. +*/ +class ON_CLASS ON_UuidPairList : private ON_SimpleArray +{ +public: + ON_UuidPairList(); + ON_UuidPairList(int capacity); + ~ON_UuidPairList(); + ON_UuidPairList(const ON_UuidPairList& src); + ON_UuidPairList& operator=(const ON_UuidPairList& src); + + static const ON_UuidPairList EmptyList; + + /* + Returns: + Number of active uuids in the list. + */ + int Count() const; + + /* + Description: + Provides an efficient way to empty a list so that it + can be used again. + */ + void Empty(); + + void Reserve( size_t capacity ); + + /* + Description: + Adds a uuid-index pair to the list. + Parameters: + id1 - [in] id to add. + id2 - [in] id to add. + bCheckForDupicates - [in] if true, then the pair + is not added if id1 is already in the list. + If you are certain that the id1 is not in the list + and you have a have a large collection of uuids, + then setting bCheckForDupicates=false will + speed up the addition of uuids. + Returns: + True if the pair was added. False if the pair was not added + because it is already in the collection. + Remarks: + You cannot add the pair value ( ON_max_uuid, ON_max_uuid ). This + pair value is used to mark removed elements in the ON_UuidPairList[]. + */ + bool AddPair( + ON_UUID id1, + ON_UUID id2, + bool bCheckForDupicates=true + ); + + /* + Description: + Removes an element with a matching id1 from the list. + Parameters: + id1 - [in] id to remove + Returns: + True if an element was removed. False if the id1 + was not in the list. + */ + bool RemovePair( + ON_UUID id1 + ); + + /* + Description: + Removes an element with a matching id pair from the list. + Parameters: + id1 - [in] + id2 - [in] + Returns: + True if an element was removed. False if the id pair + does not appear in the list. + */ + bool RemovePair( + ON_UUID id1, + ON_UUID id2 + ); + + /* + Description: + Determine if an element with a uuid is in the list. + Parameters: + id1 - [in] + id2 - [out] if not nullptr and a matching id1 is found, + then *id2 is set to the value of the second uuid. + Returns: + True if an element was found. Returns false if + the id1 is not in the list. + */ + bool FindId1(ON_UUID id1, ON_UUID* id2=0) const; + + /* + Description: + Determine if an id pair is in the list. + Returns: + True if the id pair is in the list. + False if the id pair is not in the list. + */ + bool FindPair(ON_UUID id1, ON_UUID id2) const; + + /* + Description: + Append the value of the first id in each pair to uuid_list[]. + Parameters: + uuid_list - [in/out] + Returns: + Number of ids appended to uuid_list[]. + */ + int GetId1s( + ON_SimpleArray& uuid_list + ) const; + + /* + Description: + If you will perform lots of searches before the next + change to the list, then calling ImproveSearchSpeed() + will speed up the searches by culling removed objects + and completely sorting the list so only a binary search + is required. You may edit the list at any time after + calling ImproveSearchSpeed(). If you are performing + a few searches between edits, then excessive calling + of ImproveSearchSpeed() may actually decrease overall + program performance. + */ + void ImproveSearchSpeed(); + + bool Write( + class ON_BinaryArchive& archive + ) const; + + bool Read( + class ON_BinaryArchive& archive + ); + +private: + ON_UuidPair* SearchHelper(const ON_UUID*) const; + unsigned int m_sorted_count; + unsigned int m_removed_count; +}; + +class ON_CLASS ON_2dexMap : private ON_SimpleArray +{ +public: + ON_2dexMap(); + ON_2dexMap(int capacity); + ~ON_2dexMap(); + + int Count() const; + + void Reserve(size_t capacity); + + const ON_2dex* Array() const; + + ON_2dex operator[](int i) const; + + /* + Description: + Creates an index map with the values + (i0,j),...,(i0+count-1,j) + Parameters: + count - [in] + number of elements + i0 - [in] + i value of first element + j - [in] + j value for all elements + */ + void Create(int count, int i0, int j); + + /* + Description: + Searches for an element with a matching i + and returns its j value. If no matching + element is found, then not_found_rc is returned. + Parameters: + i - [in] + value of i to search for + not_found_rc - [in] + value to return if there is not a match. + Returns: + j value + */ + int FindIndex( + int i, + int not_found_rc + ) const; + + /* + Description: + Adds and element (i,j). If there is already an entry with + value (i,*), then no element is added. + Parameters: + i - [in] + i - [in] + Returns: + True if and element it added. + */ + bool AddIndex( + int i, + int j + ); + + /* + Description: + Searches for an element (i,*) and sets its j value to j. + If there is no element with a matching i, then false + is returned. + Parameters: + i - [in] + j - [in] + Returns: + True if and element exists and was set. + */ + bool SetIndex( + int i, + int j + ); + + /* + Description: + If an element (i,*) exists, its j value is set. Otherwise + a new element with value (i,j) is added. + Parameters: + i - [in] + j - [in] + */ + void SetOrAddIndex( + int i, + int j + ); + + /* + Description: + If an element (i,*) exists, it is removed. If there is + not an element with a matching i value, then false + is returned. + Parameters: + i - [in] + Returns: + True if the element was removed + */ + bool RemoveIndex( + int i + ); + + const ON_2dex* Find2dex(int i) const; + +private: + bool m_bSorted; +}; + +/* +Description: + Compare function for Sort and Search methods. +Returns: + -1 if *a < *b is true + 1 if *b < *a is true + 0 if niether *a <*b nor *b<*a is true +Details: + Use this template functions to sort ON_SimpleArray and + ON_ClassArray objects into increasing order. The elements + of the arrays must be a type with an operator < defined. + In particular it works with built in types like double, + int and pointers. +Example: + + ON_SimpleArray A; + A = ...; + // Sort A in increasing order + A.QuickSort( ON_CompareIncreasing ); + +See Also: + ON_CompareDecreasing +*/ +template< class T> +static +int ON_CompareIncreasing( const T* a, const T* b); + +/* +Description: + Compare function for Sort and Search methods. +Returns: + -1 if *b < *a is true + 1 if *a < *b is true + 0 if niether *a < *b nor *b < *a is true +Details: + Use this template functions to sort ON_SimpleArray and + ON_ClassArray objects into decreasing order. The elements + of the arrays must be a type with an operator < defined. + In particular it works with built in types like double, + int and pointers. +Example: + + class C + { + public: + ... + bool operator<(const C&) const; + }; + ... + ON_ClassArray A; + A = ...; + // Sort A in descrasing order + A.QuickSort( ON_CompareDecreasing ); + +See Also: + ON_CompareIncreasing +*/ +template< class T> +static +int ON_CompareDecreasing( const T* a, const T* b); + +void ON_SHA1_Accumulate2fPointArray( + class ON_SHA1& sha1, + const class ON_SimpleArray& a +); + +void ON_SHA1_Accumulate3fPointArray( + class ON_SHA1& sha1, + const class ON_SimpleArray& a +); + +void ON_SHA1_Accumulate4fPointArray( + class ON_SHA1& sha1, + const class ON_SimpleArray& a +); + +void ON_SHA1_Accumulate2fVectorArray( + class ON_SHA1& sha1, + const class ON_SimpleArray& a +); + +void ON_SHA1_Accumulate3fVectorArray( + class ON_SHA1& sha1, + const class ON_SimpleArray& a +); + +void ON_SHA1_Accumulate2dPointArray( + class ON_SHA1& sha1, + const class ON_SimpleArray& a +); + +void ON_SHA1_Accumulate3dPointArray( + class ON_SHA1& sha1, + const class ON_SimpleArray& a +); + +void ON_SHA1_Accumulate4dPointArray( + class ON_SHA1& sha1, + const class ON_SimpleArray& a +); + +void ON_SHA1_Accumulate2dVectorArray( + class ON_SHA1& sha1, + const class ON_SimpleArray& a +); + +void ON_SHA1_Accumulate3dVectorArray( + class ON_SHA1& sha1, + const class ON_SimpleArray& a +); + +// definitions of the template functions are in a different file +// so that Microsoft's developer studio's autocomplete utility +// will work on the template functions. +#include "opennurbs_array_defs.h" + +class ON_CLASS ON_Big5UnicodePair +{ +public: + ON_Big5UnicodePair() = default; + ~ON_Big5UnicodePair() = default; + ON_Big5UnicodePair(const ON_Big5UnicodePair&) = default; + ON_Big5UnicodePair& operator=(const ON_Big5UnicodePair&) = default; + +public: + /// + /// An array sorted by BIG5 code points and useful for converting BIG5 code points to Unicode code points. + /// + /// Returns an array sorted by ON_Big5UnicodePair::CompareBig5AndUnicodeCodePoints() + static const ON_SimpleArray< ON_Big5UnicodePair >& Big5ToUnicode(); + + /// + /// An array sorted by Unicode code points and useful for converting Unicode code points to BIG5 code points. + /// + /// Returns an array sorted by ON_Big5UnicodePair::CompareUnicodeAndBig5CodePoints() + static const ON_SimpleArray< ON_Big5UnicodePair >& UnicodeToBig5(); + +public: + static const ON_Big5UnicodePair Null; + + /// + /// ON_Big5UnicodePair::Error.Big5() = ON_Big5CodePoint::Error and ON_Big5UnicodePair::Error.Unicode() = ON_UnicodeShortCodePoint::Error. + /// + static const ON_Big5UnicodePair Error; + + /// + /// Create a BIG5 - Unicode code point pair. + /// + /// + /// BIG5 code point. + /// + /// + /// Unicode code point. + /// + /// + static const ON_Big5UnicodePair Create( + ON_Big5CodePoint big5_code_point, + ON_UnicodeShortCodePoint unicode_code_point + ); + + static const ON_Big5UnicodePair Create( + unsigned int big5_code_point, + unsigned int unicode_code_point + ); + + /// + /// Determine if both code points in this pair are 0. + /// + /// True if both code points are 0. + bool IsNull() const; + + /// + /// Determing if the values stored as the BIG5 and Unicode code points are equal nonzero ASCII code points. + /// ASCII code point are in the range 0-0x7F (127 decimal). + /// Unicode extends ASCII. Strictly speaking, BIG5 does not extend ASCII, but it is common to mix + /// single bytes ASCII and double byte BIG5 encodings in the same char string. + /// BIG5 is a double byte string encoding with the first byte in the range 0x81 to 0xFE, the + /// minimum BIG5 code point is 0x8140 and the maximum BIG5 code point is 0xFEFE. + /// Thus it is possible to mix ASCII and BIG5 encodings in the same char string. + /// + /// + /// Value to return if both code points are 0. + /// + /// True if both code points are equal and ASCII code points (0 to 0x7F). + bool IsASCII(bool bNullIsASCII) const; + + /// + /// Determine if the pair of code points is valid. + /// If the values for BIG5 and Unicode code point values are < 0xFF and equal, the pair is considered valid. + /// Use IsASCII() if you need to treat nonzero ASCII code points differently. + /// + /// + /// Value to return if this pair is null. + /// + /// + /// Value to return if this pair is an ASCII code point. + /// + /// True if the BIG5 and Unicode code points are both valid or IsASCII() is true. + bool IsValid(bool bNullIsValid, bool bASCIICodePointIsValid) const; + + const ON_Big5CodePoint Big5() const; + const ON_UnicodeShortCodePoint Unicode() const; + + unsigned int Big5CodePoint() const; + unsigned int UnicodeCodePoint() const; + + /// + /// + /// + /// + /// + /// Value to return if this pair is null. + /// + /// + /// Value to return if this pair is an ASCII code point. + /// + /// + bool IsStandard(bool bNullIsValid, bool bASCIICodePointIsStandard) const; + + /// + /// + /// + /// Returns true if this pair is valid and at least one of the code points is a private use code point. + /// + bool IsPrivateUse() const; + + /// + /// Compares the BIG5 code point. + /// + /// + /// + /// + static int CompareBig5CodePoint(const ON_Big5UnicodePair* lhs, const ON_Big5UnicodePair* rhs); + + /// + /// Compares the Unicode code point. + /// + /// + /// + /// + static int CompareUnicodeCodePoint(const ON_Big5UnicodePair* lhs, const ON_Big5UnicodePair* rhs); + + /// + /// Dictionary compare (BIG5 code point first, Unicode code point second). + /// + /// + /// + /// + static int CompareBig5AndUnicodeCodePoints(const ON_Big5UnicodePair* lhs, const ON_Big5UnicodePair* rhs); + + /// + /// Dictionary compare (Unicode code point first, BIG5 code point second). + /// + /// + /// + /// + static int CompareUnicodeAndBig5CodePoints(const ON_Big5UnicodePair* lhs, const ON_Big5UnicodePair* rhs); + +private: + ON_Big5CodePoint m_big5; + ON_UnicodeShortCodePoint m_unicode; +}; + +ON_DECL bool operator==(ON_Big5UnicodePair lhs, ON_Big5UnicodePair rhs); +ON_DECL bool operator!=(ON_Big5UnicodePair lhs, ON_Big5UnicodePair rhs); + +#if defined(ON_DLL_TEMPLATE) + +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; + +#endif + +#endif diff --git a/opennurbs/Include/opennurbs_array_defs.h b/opennurbs/Include/opennurbs_array_defs.h new file mode 100644 index 0000000..2a7cd96 --- /dev/null +++ b/opennurbs/Include/opennurbs_array_defs.h @@ -0,0 +1,2186 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_ARRAY_DEFS_INC_) +#define ON_ARRAY_DEFS_INC_ + +// When this file is parsed with /W4 warnings, two bogus warnings +// are generated. +#pragma ON_PRAGMA_WARNING_PUSH + +// The ON_ClassArray::DestroyElement template function generates a +// C4100: 'x' : unreferenced formal parameter +// warning. +// This appears to be caused by a bug in the compiler warning code +// or the way templates are expanded. This pragma is needed squelch the +// bogus warning. +#pragma ON_PRAGMA_WARNING_DISABLE_MSC(4100) + +// The ON_CompareIncreasing and ON_CompareDecreasing templates generate a +// C4211: nonstandard extension used : redefined extern to static +// warning. Microsoft's compiler appears to have a little trouble +// when static functions are declared before they are defined in a +// single .cpp file. This pragma is needed squelch the bogus warning. +#pragma ON_PRAGMA_WARNING_DISABLE_MSC(4211) + +// The main reason the definitions of the functions for the +// ON_SimpleArray and ON_ClassArray templates are in this separate +// file is so that the Microsoft developer studio autocomplete +// functions will work on these classes. +// +// This file is included by opennurbs_array.h in the appropriate +// spot. If you need the definitions in the file, then you +// should include opennurbs_array.h and let it take care of +// including this file. + + +///////////////////////////////////////////////////////////////////////////////////// +// Class ON_SimpleArray<> +///////////////////////////////////////////////////////////////////////////////////// + +// construction //////////////////////////////////////////////////////// + +template +T* ON_SimpleArray::Realloc(T* ptr,int capacity) +{ + return (T*)onrealloc(ptr,capacity*sizeof(T)); +} + +template +ON_SimpleArray::ON_SimpleArray() ON_NOEXCEPT + : m_a(nullptr) + , m_count(0) + , m_capacity(0) +{} + +template +ON_SimpleArray::ON_SimpleArray( size_t c ) + : m_a(nullptr) + , m_count(0) + , m_capacity(0) +{ + if ( c > 0 ) + SetCapacity( c ); +} + +// Copy constructor +template +ON_SimpleArray::ON_SimpleArray( const ON_SimpleArray& src ) + : m_a(0) + , m_count(0) + , m_capacity(0) +{ + *this = src; // operator= defined below +} + +template +ON_SimpleArray::~ON_SimpleArray() +{ + SetCapacity(0); +} + +template +ON_SimpleArray& ON_SimpleArray::operator=( const ON_SimpleArray& src ) +{ + if( this != &src ) { + if ( src.m_count <= 0 ) { + m_count = 0; + } + else { + if ( m_capacity < src.m_count ) { + SetCapacity( src.m_count ); + } + if ( m_a ) { + m_count = src.m_count; + memcpy( (void*)(m_a), (void*)(src.m_a), m_count*sizeof(T) ); + } + } + } + return *this; +} + +#if defined(ON_HAS_RVALUEREF) + +// Clone constructor +template +ON_SimpleArray::ON_SimpleArray( ON_SimpleArray&& src ) ON_NOEXCEPT + : m_a(src.m_a) + , m_count(src.m_count) + , m_capacity(src.m_capacity) +{ + src.m_a = 0; + src.m_count = 0; + src.m_capacity = 0; +} + +// Clone assignment +template +ON_SimpleArray& ON_SimpleArray::operator=( ON_SimpleArray&& src ) ON_NOEXCEPT +{ + if( this != &src ) + { + this->Destroy(); + m_a = src.m_a; + m_count = src.m_count; + m_capacity = src.m_capacity; + src.m_a = 0; + src.m_count = 0; + src.m_capacity = 0; + } + return *this; +} + +#endif + +// emergency destroy /////////////////////////////////////////////////// + +template +void ON_SimpleArray::EmergencyDestroy(void) +{ + m_count = 0; + m_capacity = 0; + m_a = 0; +} + +// query /////////////////////////////////////////////////////////////// + +template +int ON_SimpleArray::Count() const +{ + return m_count; +} + +template +unsigned int ON_SimpleArray::UnsignedCount() const +{ + return ((unsigned int)m_count); +} + +template +int ON_SimpleArray::Capacity() const +{ + return m_capacity; +} + +template +unsigned int ON_SimpleArray::SizeOfArray() const +{ + return ((unsigned int)(m_capacity*sizeof(T))); +} + +template +unsigned int ON_SimpleArray::SizeOfElement() const +{ + return ((unsigned int)(sizeof(T))); +} + + +template +ON__UINT32 ON_SimpleArray::DataCRC(ON__UINT32 current_remainder) const +{ + return ON_CRC32(current_remainder,m_count*sizeof(m_a[0]),m_a); +} + +template +T& ON_SimpleArray::operator[]( int i ) +{ +#if defined(ON_DEBUG) + if ( i < 0 || i > m_capacity ) + { + ON_ERROR("ON_SimpleArray[i]: i out of range."); + } +#endif + return m_a[i]; +} + +template +T& ON_SimpleArray::operator[]( unsigned int i ) +{ +#if defined(ON_DEBUG) + if ( i > (unsigned int)m_capacity ) + { + ON_ERROR("ON_SimpleArray[i]: i out of range."); + } +#endif + return m_a[i]; +} + + +template +T& ON_SimpleArray::operator[]( ON__INT64 i ) +{ +#if defined(ON_DEBUG) + if ( i < 0 || i > (ON__INT64)m_capacity ) + { + ON_ERROR("ON_SimpleArray[i]: i out of range."); + } +#endif + return m_a[i]; +} + +template +T& ON_SimpleArray::operator[]( ON__UINT64 i ) +{ +#if defined(ON_DEBUG) + if ( i > (ON__UINT64)m_capacity ) + { + ON_ERROR("ON_SimpleArray[i]: i out of range."); + } +#endif + return m_a[i]; +} + + +#if defined(ON_RUNTIME_APPLE) +template +T& ON_SimpleArray::operator[](size_t i ) +{ +#if defined(ON_DEBUG) + if ( i > (size_t)m_capacity ) + { + ON_ERROR("ON_SimpleArray[i]: i out of range."); + } +#endif + return m_a[i]; +} +#endif + +template +const T& ON_SimpleArray::operator[](int i) const +{ +#if defined(ON_DEBUG) + if ( i < 0 || i > m_capacity ) + { + ON_ERROR("ON_SimpleArray[i]: i out of range."); + } +#endif + return m_a[i]; +} + +template +const T& ON_SimpleArray::operator[](unsigned int i) const +{ +#if defined(ON_DEBUG) + if ( i > (unsigned int)m_capacity ) + { + ON_ERROR("ON_SimpleArray[i]: i out of range."); + } +#endif + return m_a[i]; +} + + +template +const T& ON_SimpleArray::operator[](ON__INT64 i) const +{ +#if defined(ON_DEBUG) + if ( i < 0 || i > ((ON__INT64)m_capacity) ) + { + ON_ERROR("ON_SimpleArray[i]: i out of range."); + } +#endif + return m_a[i]; +} + +template +const T& ON_SimpleArray::operator[](ON__UINT64 i) const +{ +#if defined(ON_DEBUG) + if ( i > (ON__UINT64)m_capacity ) + { + ON_ERROR("ON_SimpleArray[i]: i out of range."); + } +#endif + return m_a[i]; +} + +#if defined(ON_RUNTIME_APPLE) +template +const T& ON_SimpleArray::operator[](size_t i) const +{ +#if defined(ON_DEBUG) + if ( i > (size_t)m_capacity ) + { + ON_ERROR("ON_SimpleArray[i]: i out of range."); + } +#endif + return m_a[i]; +} +#endif + +template +ON_SimpleArray::operator T*() +{ + return (m_count > 0) ? m_a : 0; +} + +template +ON_SimpleArray::operator const T*() const +{ + return (m_count > 0) ? m_a : 0; +} + +template +T* ON_SimpleArray::Array() +{ + return m_a; +} + +template +const T* ON_SimpleArray::Array() const +{ + return m_a; +} + +template +T* ON_SimpleArray::KeepArray() +{ + T* p = m_a; + m_a = 0; + m_count = 0; + m_capacity = 0; + return p; +} + +template +void ON_SimpleArray::SetArray(T* p) +{ + if ( m_a && m_a != p ) + onfree(m_a); + m_a = p; +} + +template +void ON_SimpleArray::SetArray(T* p, int count, int capacity) +{ + if ( m_a && m_a != p ) + onfree(m_a); + m_a = p; + m_count = count; + m_capacity = capacity; +} + +template +T* ON_SimpleArray::First() +{ + return (m_count > 0) ? m_a : 0; +} + +template +const T* ON_SimpleArray::First() const +{ + return (m_count > 0) ? m_a : 0; +} + +template +T* ON_SimpleArray::At( int i ) +{ + return (i >= 0 && i < m_count) ? m_a+i : 0; +} + +template +T* ON_SimpleArray::At( unsigned int i ) +{ + return (i < (unsigned int)m_count) ? m_a+i : 0; +} + +template +const T* ON_SimpleArray::At( int i) const +{ + return (i >= 0 && i < m_count) ? m_a+i : 0; +} + +template +const T* ON_SimpleArray::At( unsigned int i) const +{ + return (i < (unsigned int)m_count) ? m_a+i : 0; +} + +template +T* ON_SimpleArray::At( ON__INT64 i ) +{ + return (i >= 0 && i < (ON__INT64)m_count) ? m_a+i : 0; +} + +template +T* ON_SimpleArray::At( ON__UINT64 i ) +{ + return (i < (ON__UINT64)m_count) ? m_a+i : 0; +} + +template +const T* ON_SimpleArray::At( ON__INT64 i) const +{ + return (i >= 0 && i < (ON__INT64)m_count) ? m_a+i : 0; +} + +template +const T* ON_SimpleArray::At( ON__UINT64 i) const +{ + return (i < (ON__UINT64)m_count) ? m_a+i : 0; +} + +template +T* ON_SimpleArray::Last() +{ + return (m_count > 0) ? m_a+(m_count-1) : 0; +} + +template +const T* ON_SimpleArray::Last() const +{ + return (m_count > 0) ? m_a+(m_count-1) : 0; +} + +// array operations //////////////////////////////////////////////////// + +template +void ON_SimpleArray::Move( int dest_i, int src_i, int ele_cnt ) +{ + // private function for moving blocks of array memory + // caller is responsible for updating m_count. + if ( ele_cnt <= 0 || src_i < 0 || dest_i < 0 || src_i == dest_i || + src_i + ele_cnt > m_count || dest_i > m_count ) + return; + + int capacity = dest_i + ele_cnt; + if ( capacity > m_capacity ) { + if ( capacity < 2*m_capacity ) + capacity = 2*m_capacity; + SetCapacity( capacity ); + } + + memmove( &m_a[dest_i], &m_a[src_i], ele_cnt*sizeof(T) ); +} + +template +T& ON_SimpleArray::AppendNew() +{ + if ( m_count == m_capacity ) + { + int new_capacity = NewCapacity(); + Reserve( new_capacity ); + } + memset( (void*)(&m_a[m_count]), 0, sizeof(T) ); + return m_a[m_count++]; +} + +template +void ON_SimpleArray::Append( const T& x ) +{ + const T* p = &x; + if ( m_count == m_capacity ) + { + const int newcapacity = NewCapacity(); + if ( p >= m_a && p < (m_a + m_capacity) ) + { + // 26 Sep 2005 Dale Lear + // x is in the block of memory about to be reallocated. + void* temp = onmalloc(sizeof(T)); + memcpy(temp, p, sizeof(T)); + p = (T*)temp; + } + Reserve(newcapacity); + if (nullptr == m_a) + { + ON_ERROR("allocation failure"); + return; + } + } + m_a[m_count++] = *p; + if (p != &x) + onfree((void*)p); +} + +template +void ON_SimpleArray::Append( int count, const T* buffer ) +{ + if ( count > 0 && nullptr != buffer ) + { + const size_t sizeof_buffer = count * sizeof(T); + void* temp = nullptr; + if ( count + m_count > m_capacity ) + { + int newcapacity = NewCapacity(); + if ( newcapacity < count + m_count ) + newcapacity = count + m_count; + if ( buffer >= m_a && buffer < (m_a + m_capacity) ) + { + // buffer is in the block of memory about to be reallocated + temp = onmalloc(sizeof_buffer); + memcpy(temp, buffer, sizeof_buffer); + buffer = (const T*)temp; + } + Reserve( newcapacity ); + } + memcpy( (void*)(m_a + m_count), (void*)(buffer), sizeof_buffer ); + if (nullptr != temp) + onfree(temp); + m_count += count; + } +} + + +template +void ON_SimpleArray::Prepend( int count, const T* buffer ) +{ + if ( count > 0 && nullptr != buffer ) + { + const size_t sizeof_buffer = count * sizeof(T); + void* temp = nullptr; + if ( count + m_count > m_capacity ) + { + int newcapacity = NewCapacity(); + if ( newcapacity < count + m_count ) + newcapacity = count + m_count; + if ( buffer >= m_a && buffer < (m_a + m_capacity) ) + { + // buffer is in the block of memory about to be reallocated + temp = onmalloc(sizeof_buffer); + memcpy(temp, buffer, sizeof_buffer); + buffer = (const T*)temp; + } + Reserve( newcapacity ); + } + + const size_t count0 = (size_t)m_count; + const size_t count1 = count0 + ((size_t)count); + T* p0 = m_a; + T* p = p0 + count0; + T* p1 = m_a + count1; + while (p > p0) + *(--p1) = *(--p); + memcpy( (void*)(m_a), (void*)(buffer), sizeof_buffer ); + if (nullptr != temp) + onfree(temp); + m_count = (int)count1; + } +} + +template +void ON_SimpleArray::Insert( int i, const T& x ) +{ + if( i >= 0 && i <= m_count ) + { + const T* p = &x; + if ( m_count == m_capacity ) + { + if (&x >= m_a && &x < (m_a + m_capacity)) + { + // x is in the block of memory about to be reallocated. + void* temp = onmalloc(sizeof(T)); + memcpy(temp, p, sizeof(T)); + p = (T*)temp; + } + int newcapacity = NewCapacity(); + Reserve( newcapacity ); + } + m_count++; + Move( i+1, i, m_count-1-i ); + m_a[i] = *p; + if (p != &x) + onfree((void*)p); + } +} + +template +void ON_SimpleArray::Remove() +{ + Remove(m_count-1); +} + +template +void ON_SimpleArray::Remove( int i ) +{ + if ( i >= 0 && i < m_count ) { + Move( i, i+1, m_count-1-i ); + m_count--; + memset( (void*)(&m_a[m_count]), 0, sizeof(T) ); + } +} + +template +void ON_SimpleArray::Empty() +{ + if ( m_a ) + memset( (void*)(m_a), 0, m_capacity*sizeof(T) ); + m_count = 0; +} + +template +void ON_SimpleArray::Reverse() +{ + // NOTE: + // If anything in "T" depends on the value of this's address, + // then don't call Reverse(). + T t; + int i = 0; + int j = m_count-1; + for ( /*empty*/; i < j; i++, j-- ) { + t = m_a[i]; + m_a[i] = m_a[j]; + m_a[j] = t; + } +} + +template +void ON_SimpleArray::Swap( int i, int j ) +{ + if ( i != j ) { + const T t(m_a[i]); + m_a[i] = m_a[j]; + m_a[j] = t; + } +} + +template +int ON_SimpleArray::Search( const T& key ) const +{ + const T* p = &key; + for ( int i = 0; i < m_count; i++ ) { + if (!memcmp(p,m_a+i,sizeof(T))) + return i; + } + return -1; +} + +template +int ON_SimpleArray::Search( const T* key, int (*compar)(const T*,const T*) ) const +{ + for ( int i = 0; i < m_count; i++ ) { + if (!compar(key,m_a+i)) + return i; + } + return -1; +} + +template +int ON_SimpleArray::BinarySearch( const T* key, int (*compar)(const T*,const T*) ) const +{ + const T* found = (key&&m_a&&m_count>0) + ? (const T*)bsearch( key, m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar ) + : 0; + + // This worked on a wide range of 32 bit compilers. + + int rc; + if ( 0 != found ) + { + // Convert "found" pointer to array index. + +#if defined(ON_COMPILER_MSC1300) + rc = ((int)(found - m_a)); +#elif 8 == ON_SIZEOF_POINTER + // In an ideal world, return ((int)(found - m_a)) would work everywhere. + // In practice, this should work any 64 bit compiler and we can hope + // the optimzer generates efficient code. + const ON__UINT64 fptr = (ON__UINT64)found; + const ON__UINT64 aptr = (ON__UINT64)m_a; + const ON__UINT64 sz = (ON__UINT64)sizeof(T); + const ON__UINT64 i = (fptr - aptr)/sz; + rc = (int)i; +#else + // In an ideal world, return ((int)(found - m_a)) would work everywhere. + // In practice, this should work any 32 bit compiler and we can hope + // the optimzer generates efficient code. + const ON__UINT32 fptr = (ON__UINT32)found; + const ON__UINT32 aptr = (ON__UINT32)m_a; + const ON__UINT32 sz = (ON__UINT32)sizeof(T); + const ON__UINT32 i = (fptr - aptr)/sz; + rc = (int)i; +#endif + } + else + { + // "key" not found + rc = -1; + } + + return rc; + +} + +template +int ON_SimpleArray::BinarySearch( const T* key, int (*compar)(const T*,const T*), int count ) const +{ + if ( count > m_count ) + count = m_count; + if ( count <= 0 ) + return -1; + const T* found = (key&&m_a&&m_count>0) + ? (const T*)bsearch( key, m_a, count, sizeof(T), (int(*)(const void*,const void*))compar ) + : 0; + + // This worked on a wide range of 32 bit compilers. + + int rc; + if ( 0 != found ) + { + // Convert "found" pointer to array index. + +#if defined(ON_COMPILER_MSC1300) + rc = ((int)(found - m_a)); +#elif 8 == ON_SIZEOF_POINTER + // In an ideal world, return ((int)(found - m_a)) would work everywhere. + // In practice, this should work any 64 bit compiler and we can hope + // the optimzer generates efficient code. + const ON__UINT64 fptr = (ON__UINT64)found; + const ON__UINT64 aptr = (ON__UINT64)m_a; + const ON__UINT64 sz = (ON__UINT64)sizeof(T); + const ON__UINT64 i = (fptr - aptr)/sz; + rc = (int)i; +#else + // In an ideal world, return ((int)(found - m_a)) would work everywhere. + // In practice, this should work any 32 bit compiler and we can hope + // the optimzer generates efficient code. + const ON__UINT32 fptr = (ON__UINT32)found; + const ON__UINT32 aptr = (ON__UINT32)m_a; + const ON__UINT32 sz = (ON__UINT32)sizeof(T); + const ON__UINT32 i = (fptr - aptr)/sz; + rc = (int)i; +#endif + } + else + { + // "key" not found + rc = -1; + } + return rc; +} + +template +int ON_SimpleArray::InsertInSortedList(const T& e, int (*compar)(const T*, const T*)) +{ + const int count = m_count; + if (count < 0) + return -1; + if (0 == count) + { + Insert(0, e); + return 0; + } + + const unsigned ucount = ((unsigned)count); + unsigned i0 = 0; + unsigned i1 = ucount; + while (i0 < i1) + { + const unsigned i = (i0 + i1) / 2; + const int c = compar(&e, m_a + i); + if (c < 0) + { + i1 = i; + } + else if (c > 0) + { + i0 = i + 1; + } + else + { + i1 = i; + while (i1 + 1 < ucount && 0 == compar(&e, m_a + (i1 + 1))) + ++i1; + i0 = i1; + } + } + if (i0 <= ucount) + { + Insert(i0, e); + return ((int)i0); + } + + return -1; +} + + +template +int ON_SimpleArray::InsertInSortedList(const T& e, int (*compar)(const T*, const T*), int count) +{ + if (count > m_count) + count = m_count; + if (count < 0) + return -1; + if (0 == count) + { + Insert(0, e); + return 0; + } + + const unsigned ucount = ((unsigned)count); + unsigned i0 = 0; + unsigned i1 = ucount; + while (i0 0) + { + i0 = i + 1; + } + else + { + i1 = i; + while (i1 + 1 < ucount && 0 == compar(&e, m_a + (i1 + 1))) + ++i1; + i0 = i1; + } + } + if (i0 <= ucount) + { + Insert(i0, e); + return ((int)i0); + } + + return -1; +} + +template +bool ON_SimpleArray::HeapSort( int (*compar)(const T*,const T*) ) +{ + bool rc = false; + if ( m_a && m_count > 0 && compar ) { + if ( m_count > 1 ) + ON_hsort( m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar ); + rc = true; + } + return rc; +} + +template +bool ON_SimpleArray::QuickSort( int (*compar)(const T*,const T*) ) +{ + bool rc = false; + if ( m_a && m_count > 0 && compar ) { + if ( m_count > 1 ) + ON_qsort( m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar ); + rc = true; + } + return rc; +} + +template +bool ON_SimpleArray::QuickSortAndRemoveDuplicates( int (*compar)(const T*,const T*) ) +{ + bool rc = false; + if ( m_a && m_count > 0 && compar ) + { + if (m_count > 1) + { + ON_qsort(m_a, m_count, sizeof(T), (int(*)(const void*, const void*))compar); + const T* prev_ele = &m_a[0]; + int clean_count = 1; + for (int i = 1; i < m_count; ++i) + { + if (0 == compar(prev_ele, &m_a[i])) + continue; // duplicate + if (i > clean_count) + m_a[clean_count] = m_a[i]; + prev_ele = &m_a[clean_count]; + ++clean_count; + } + if (clean_count < m_count) + { + memset( (void*)(&m_a[clean_count]), 0, (m_count-clean_count)*sizeof(T) ); + SetCount(clean_count); + } + } + rc = true; + } + return rc; +} + +template +bool ON_SimpleArray::Sort( ON::sort_algorithm sa, int* index, int (*compar)(const T*,const T*) ) const +{ + bool rc = false; + if ( m_a && m_count > 0 && compar && index ) { + if ( m_count > 1 ) + ON_Sort(sa, index, m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar ); + else if ( m_count == 1 ) + index[0] = 0; + rc = true; + } + return rc; +} + +template +bool ON_SimpleArray::Sort( ON::sort_algorithm sa, int* index, int (*compar)(const T*,const T*,void*),void* p ) const +{ + bool rc = false; + if ( m_a && m_count > 0 && compar && index ) { + if ( m_count > 1 ) + ON_Sort(sa, index, m_a, m_count, sizeof(T), (int(*)(const void*,const void*,void*))compar, p ); + else if ( m_count == 1 ) + index[0] = 0; + rc = true; + } + return rc; +} + +template +bool ON_SimpleArray::Permute( const int* index ) +{ + bool rc = false; + if ( m_a && m_count > 0 && index ) { + int i; + T* buffer = (T*)onmalloc(m_count*sizeof(buffer[0])); + memcpy( (void*)(buffer), (void*)(m_a), m_count*sizeof(T) ); + for (i = 0; i < m_count; i++ ) + memcpy( (void*)(m_a+i), (void*)(buffer+index[i]), sizeof(T) ); // must use memcopy and not operator= + onfree(buffer); + rc = true; + } + return rc; +} + +template +void ON_SimpleArray::Zero() +{ + if ( m_a && m_capacity > 0 ) { + memset( (void*)(m_a), 0, m_capacity*sizeof(T) ); + } +} + +template +void ON_SimpleArray::MemSet( unsigned char value ) +{ + if ( m_a && m_capacity > 0 ) { + memset( (void*)(m_a), value, m_capacity*sizeof(T) ); + } +} + +// memory managment //////////////////////////////////////////////////// + +template +T* ON_SimpleArray::Reserve( size_t newcap ) +{ + if( (size_t)m_capacity < newcap ) + SetCapacity( newcap ); + return m_a; +} + +template +void ON_SimpleArray::Shrink() +{ + SetCapacity( m_count ); +} + +template +void ON_SimpleArray::Destroy() +{ + SetCapacity( 0 ); +} + +// low level memory managment ////////////////////////////////////////// + +template +void ON_SimpleArray::SetCount( int count ) +{ + if ( count >= 0 && count <= m_capacity ) + m_count = count; +} + +template +T* ON_SimpleArray::SetCapacity( size_t new_capacity ) +{ + if (0 == m_capacity) + { + // Allow "expert" users of ON_SimpleArray<>.SetArray(*,*,0) to clean up after themselves + // and deals with the case when the forget to clean up after themselves. + m_a = nullptr; + m_count = 0; + } + + // sets capacity to input value + int capacity = (new_capacity > 0 && new_capacity < ON_UNSET_UINT_INDEX) + ? (int)new_capacity + : 0; + if ( capacity != m_capacity ) { + if( capacity > 0 ) { + if ( m_count > capacity ) + m_count = capacity; + // NOTE: Realloc() does an allocation if the first argument is nullptr. + m_a = Realloc( m_a, capacity ); + if ( m_a ) { + if ( capacity > m_capacity ) { + // zero new memory + memset( (void*) (m_a + m_capacity), 0, (capacity-m_capacity)*sizeof(T) ); + } + m_capacity = capacity; + } + else { + // out of memory + m_count = m_capacity = 0; + } + } + else if (m_a) { + Realloc(m_a,0); + m_a = 0; + m_count = m_capacity = 0; + } + } + return m_a; +} + +template +int ON_SimpleArray::NewCapacity() const +{ + // Note: + // This code appears in ON_SimpleArray::NewCapacity() + // and ON_ClassArray::NewCapacity(). Changes made to + // either function should be made to both functions. + // Because this code is template code that has to + // support dynamic linking and the code is defined + // in a header, I'm using copy-and-paste rather + // than a static. + + // This function returns 2*m_count unless that will + // result in an additional allocation of more than + // cap_size bytes. The cap_size concept was added in + // January 2010 because some calculations on enormous + // models were slightly underestimating the initial + // Reserve() size and then wasting gigabytes of memory. + + // cap_size = 128 MB on 32-bit os, 256 MB on 64 bit os + const size_t cap_size = 32*sizeof(void*)*1024*1024; + if (m_count*sizeof(T) <= cap_size || m_count < 8) + return ((m_count <= 2) ? 4 : 2*m_count); + + // Growing the array will increase the memory + // use by more than cap_size. + int delta_count = 8 + cap_size/sizeof(T); + if ( delta_count > m_count ) + delta_count = m_count; + return (m_count + delta_count); +} + +template +int ON_ClassArray::NewCapacity() const +{ + // Note: + // This code appears in ON_SimpleArray::NewCapacity() + // and ON_ClassArray::NewCapacity(). Changes made to + // either function should be made to both functions. + // Because this code is template code that has to + // support dynamic linking and the code is defined + // in a header, I'm using copy-and-paste rather + // than a static. + + // This function returns 2*m_count unless that will + // result in an additional allocation of more than + // cap_size bytes. The cap_size concept was added in + // January 2010 because some calculations on enormous + // models were slightly underestimating the initial + // Reserve() size and then wasting gigabytes of memory. + + // cap_size = 128 MB on 32-bit os, 256 MB on 64 bit os + const size_t cap_size = 32*sizeof(void*)*1024*1024; + if (m_count*sizeof(T) <= cap_size || m_count < 8) + return ((m_count <= 2) ? 4 : 2*m_count); + + // Growing the array will increase the memory + // use by more than cap_size. + int delta_count = 8 + cap_size/sizeof(T); + if ( delta_count > m_count ) + delta_count = m_count; + return (m_count + delta_count); +} + +///////////////////////////////////////////////////////////////////////////////////// +// Class ON_ObjectArray<> +///////////////////////////////////////////////////////////////////////////////////// + +template +ON_ObjectArray::ON_ObjectArray() +{ +} + +template +ON_ObjectArray::~ON_ObjectArray() +{ +} + +template +ON_ObjectArray::ON_ObjectArray( const ON_ObjectArray& src ) : ON_ClassArray(src) +{ +} + +template +ON_ObjectArray& ON_ObjectArray::operator=( const ON_ObjectArray& src) +{ + if( this != &src) + { + ON_ClassArray::operator =(src); + } + return *this; +} + +#if defined(ON_HAS_RVALUEREF) + +// Clone constructor +template +ON_ObjectArray::ON_ObjectArray( ON_ObjectArray&& src ) + : ON_ClassArray(std::move(src)) +{} + +// Clone assignment +template +ON_ObjectArray& ON_ObjectArray::operator=( ON_ObjectArray&& src ) +{ + if( this != &src ) + { + ON_ClassArray::operator=(std::move(src)); + } + return *this; +} + +#endif + +template +ON_ObjectArray::ON_ObjectArray( size_t c ) + : ON_ClassArray(c) +{ +} + +template +T* ON_ObjectArray::Realloc(T* ptr,int capacity) +{ + T* reptr = (T*)onrealloc(ptr,capacity*sizeof(T)); + if ( ptr && reptr && reptr != ptr ) + { + // The "this->" in this->m_count and this->m_a + // are needed for gcc 4 to compile. + int i; + for ( i = 0; i < this->m_count; i++ ) + { + reptr[i].MemoryRelocate(); + } + } + return reptr; +} + +///////////////////////////////////////////////////////////////////////////////////// +// Class ON_ClassArray<> +///////////////////////////////////////////////////////////////////////////////////// + + +// construction //////////////////////////////////////////////////////// + +template +T* ON_ClassArray::Realloc(T* ptr,int capacity) +{ + return (T*)onrealloc(ptr,capacity*sizeof(T)); +} + +template +ON__UINT32 ON_ObjectArray::DataCRC(ON__UINT32 current_remainder) const +{ + // The "this->" in this->m_count and this->m_a + // are needed for gcc 4 to compile. + int i; + for ( i = 0; i < this->m_count; i++ ) + { + current_remainder = this->m_a[i].DataCRC(current_remainder); + } + return current_remainder; +} + +template +ON_ClassArray::ON_ClassArray() ON_NOEXCEPT + : m_a(nullptr) + , m_count(0) + , m_capacity(0) +{} + +template +ON_ClassArray::ON_ClassArray( size_t c ) + : m_a(nullptr) + , m_count(0) + , m_capacity(0) +{ + if ( c > 0 ) + SetCapacity( c ); +} + +// Copy constructor +template +ON_ClassArray::ON_ClassArray( const ON_ClassArray& src ) + : m_a(nullptr) + , m_count(0) + , m_capacity(0) +{ + *this = src; // operator= defined below +} + +template +ON_ClassArray::~ON_ClassArray() +{ + SetCapacity(0); +} + +template +ON_ClassArray& ON_ClassArray::operator=( const ON_ClassArray& src ) +{ + int i; + if( this != &src ) { + if ( src.m_count <= 0 ) { + m_count = 0; + } + else { + if ( m_capacity < src.m_count ) { + SetCapacity( src.m_count ); + } + if ( m_a ) { + m_count = src.m_count; + for ( i = 0; i < m_count; i++ ) { + m_a[i] = src.m_a[i]; + } + } + } + } + return *this; +} + +#if defined(ON_HAS_RVALUEREF) + +// Clone constructor +template +ON_ClassArray::ON_ClassArray( ON_ClassArray&& src ) ON_NOEXCEPT + : m_a(src.m_a) + , m_count(src.m_count) + , m_capacity(src.m_capacity) +{ + src.m_a = 0; + src.m_count = 0; + src.m_capacity = 0; +} + +// Clone assignment +template +ON_ClassArray& ON_ClassArray::operator=( ON_ClassArray&& src ) ON_NOEXCEPT +{ + if( this != &src ) + { + // TODO - investigate why we should use std::move(src) + // instead of the code below + //ON_ClassArray::operator=(std::move(src)); + // Then investigate why the change was requested only for class array. + // What about the other dynamic array classes? + this->Destroy(); + m_a = src.m_a; + m_count = src.m_count; + m_capacity = src.m_capacity; + src.m_a = 0; + src.m_count = 0; + src.m_capacity = 0; + } + return *this; +} + +#endif + +// emergency destroy /////////////////////////////////////////////////// + +template +void ON_ClassArray::EmergencyDestroy(void) +{ + m_count = 0; + m_capacity = 0; + m_a = 0; +} + +// query /////////////////////////////////////////////////////////////// + +template +int ON_ClassArray::Count() const +{ + return m_count; +} + +template +unsigned int ON_ClassArray::UnsignedCount() const +{ + return ((unsigned int)m_count); +} + +template +int ON_ClassArray::Capacity() const +{ + return m_capacity; +} + +template +unsigned int ON_ClassArray::SizeOfArray() const +{ + return ((unsigned int)(m_capacity*sizeof(T))); +} + +template +unsigned int ON_ClassArray::SizeOfElement() const +{ + return ((unsigned int)(sizeof(T))); +} + +template +T& ON_ClassArray::operator[]( int i ) +{ +#if defined(ON_DEBUG) + if ( i < 0 || i > m_capacity ) + { + ON_ERROR("ON_ClassArray[i]: i out of range."); + } +#endif + return m_a[i]; +} + + +template +T& ON_ClassArray::operator[]( ON__INT64 i ) +{ +#if defined(ON_DEBUG) + if ( i < 0 || i > (ON__INT64)m_capacity ) + { + ON_ERROR("ON_ClassArray[i]: i out of range."); + } +#endif + return m_a[i]; +} + +template +T& ON_ClassArray::operator[]( unsigned int i ) +{ +#if defined(ON_DEBUG) + if ( i > (unsigned int)m_capacity ) + { + ON_ERROR("ON_ClassArray[i]: i out of range."); + } +#endif + return m_a[i]; +} + +template +T& ON_ClassArray::operator[]( ON__UINT64 i ) +{ +#if defined(ON_DEBUG) + if ( i > (ON__UINT64)m_capacity ) + { + ON_ERROR("ON_ClassArray[i]: i out of range."); + } +#endif + return m_a[i]; +} + +#if defined(ON_RUNTIME_APPLE) +template +T& ON_ClassArray::operator[](size_t i ) +{ +#if defined(ON_DEBUG) + if ( i > (size_t)m_capacity ) + { + ON_ERROR("ON_ClassArray[i]: i out of range."); + } +#endif + return m_a[i]; +} +#endif + +template +const T& ON_ClassArray::operator[](int i) const +{ +#if defined(ON_DEBUG) + if ( i < 0 || i > m_capacity ) + { + ON_ERROR("ON_ClassArray[i]: i out of range."); + } +#endif + return m_a[i]; +} + +template +const T& ON_ClassArray::operator[](ON__INT64 i) const +{ +#if defined(ON_DEBUG) + if ( i < 0 || i > (ON__INT64)m_capacity ) + { + ON_ERROR("ON_ClassArray[i]: i out of range."); + } +#endif + return m_a[i]; +} + +template +const T& ON_ClassArray::operator[](unsigned int i) const +{ +#if defined(ON_DEBUG) + if ( i > (unsigned int)m_capacity ) + { + ON_ERROR("ON_ClassArray[i]: i out of range."); + } +#endif + return m_a[i]; +} + +template +const T& ON_ClassArray::operator[](ON__UINT64 i) const +{ +#if defined(ON_DEBUG) + if ( i > (ON__UINT64)m_capacity ) + { + ON_ERROR("ON_ClassArray[i]: i out of range."); + } +#endif + return m_a[i]; +} + +#if defined(ON_RUNTIME_APPLE) +template +const T& ON_ClassArray::operator[](size_t i) const +{ +#if defined(ON_DEBUG) + if ( i > (size_t)m_capacity ) + { + ON_ERROR("ON_ClassArray[i]: i out of range."); + } +#endif + return m_a[i]; +} +#endif + +template +ON_ClassArray::operator T*() +{ + return (m_count > 0) ? m_a : 0; +} + +template +ON_ClassArray::operator const T*() const +{ + return (m_count > 0) ? m_a : 0; +} + +template +T* ON_ClassArray::Array() +{ + return m_a; +} + +template +const T* ON_ClassArray::Array() const +{ + return m_a; +} + +template +T* ON_ClassArray::KeepArray() +{ + T* p = m_a; + m_a = 0; + m_count = 0; + m_capacity = 0; + return p; +} + +template +void ON_ClassArray::SetArray(T* p) +{ + if ( m_a && m_a != p ) + Destroy(); + m_a = p; +} + +template +void ON_ClassArray::SetArray(T* p, int count, int capacity) +{ + if ( m_a && m_a != p ) + Destroy(); + m_a = p; + m_count = count; + m_capacity = capacity; +} + +template +T* ON_ClassArray::First() +{ + return (m_count > 0) ? m_a : 0; +} + +template +const T* ON_ClassArray::First() const +{ + return (m_count > 0) ? m_a : 0; +} + +template +T* ON_ClassArray::At( int i ) +{ + return (i >= 0 && i < m_count) ? m_a+i : 0; +} + +template +T* ON_ClassArray::At( unsigned int i ) +{ + return (i < (unsigned int)m_count) ? m_a+i : 0; +} + +template +const T* ON_ClassArray::At( int i) const +{ + return (i >= 0 && i < m_count) ? m_a+i : 0; +} + +template +const T* ON_ClassArray::At( unsigned int i) const +{ + return (i < (unsigned int)m_count) ? m_a+i : 0; +} + + +template +T* ON_ClassArray::At( ON__INT64 i ) +{ + return (i >= 0 && i < (ON__INT64)m_count) ? m_a+i : 0; +} + +template +T* ON_ClassArray::At( ON__UINT64 i ) +{ + return (i < (ON__UINT64)m_count) ? m_a+i : 0; +} + +template +const T* ON_ClassArray::At( ON__INT64 i) const +{ + return (i >= 0 && i < (ON__INT64)m_count) ? m_a+i : 0; +} + +template +const T* ON_ClassArray::At( ON__UINT64 i) const +{ + return (i < (ON__UINT64)m_count) ? m_a+i : 0; +} + + +template +T* ON_ClassArray::Last() +{ + return (m_count > 0) ? m_a+(m_count-1) : 0; +} + +template +const T* ON_ClassArray::Last() const +{ + return (m_count > 0) ? m_a+(m_count-1) : 0; +} + +// array operations //////////////////////////////////////////////////// + +template +void ON_ClassArray::Move( int dest_i, int src_i, int ele_cnt ) +{ + // private function for moving blocks of array memory + // caller is responsible for updating m_count and managing + // destruction/creation. + if ( ele_cnt <= 0 || src_i < 0 || dest_i < 0 || src_i == dest_i || + src_i + ele_cnt > m_count || dest_i > m_count ) + return; + + int capacity = dest_i + ele_cnt; + if ( capacity > m_capacity ) { + if ( capacity < 2*m_capacity ) + capacity = 2*m_capacity; + SetCapacity( capacity ); + } + + // This call to memmove is ok, even when T is a class with a vtable + // because the it doesn't change the vtable for the class. + // Classes that have back pointers, like ON_UserData, are + // handled elsewhere and cannot be in ON_ClassArray<>s. + memmove( (void*)(&m_a[dest_i]), (const void*)(&m_a[src_i]), ele_cnt*sizeof(T) ); +} + +template +void ON_ClassArray::ConstructDefaultElement(T* p) +{ + // use placement ( new(size_t,void*) ) to construct + // T in supplied memory + new(p) T; +} + +template +void ON_ClassArray::DestroyElement(T& x) +{ + x.~T(); +} + +template +T& ON_ClassArray::AppendNew() +{ + if ( m_count == m_capacity ) + { + int newcapacity = NewCapacity(); + Reserve( newcapacity ); + } + else + { + // First destroy what's there .. + DestroyElement(m_a[m_count]); + // and then get a properly initialized element + ConstructDefaultElement(&m_a[m_count]); + } + return m_a[m_count++]; +} + +template +void ON_ClassArray::Append( const T& x ) +{ + if ( m_count == m_capacity ) + { + const int newcapacity = NewCapacity(); + if (m_a) + { + const int s = (int)(&x - m_a); // (int) cast is for 64 bit pointers + if ( s >= 0 && s < m_capacity ) + { + // 26 Sep 2005 Dale Lear + // User passed in an element of the m_a[] + // that will get reallocated by the call + // to Reserve(newcapacity). + T temp; // ON_*Array<> templates do not require robust copy constructor. + temp = x; // ON_*Array<> templates require a robust operator=. + Reserve( newcapacity ); + if (nullptr == m_a) + { + ON_ERROR("allocation failure"); + return; + } + m_a[m_count++] = temp; + return; + } + } + Reserve(newcapacity); + if (nullptr == m_a) + { + ON_ERROR("allocation failure"); + return; + } + } + m_a[m_count++] = x; +} + +template +void ON_ClassArray::Append( int count, const T* p ) +{ + int i; + if ( count > 0 && p ) + { + if ( count + m_count > m_capacity ) + { + int newcapacity = NewCapacity(); + if ( newcapacity < count + m_count ) + newcapacity = count + m_count; + Reserve( newcapacity ); + } + for ( i = 0; i < count; i++ ) { + m_a[m_count++] = p[i]; + } + } +} + +// Insert called with a reference uses operator = +template +void ON_ClassArray::Insert( int i, const T& x ) +{ + if( i >= 0 && i <= m_count ) + { + if ( m_count == m_capacity ) + { + int newcapacity = NewCapacity(); + Reserve( newcapacity ); + } + DestroyElement( m_a[m_count] ); + m_count++; + if ( i < m_count-1 ) { + Move( i+1, i, m_count-1-i ); + // This call to memset is ok even when T has a vtable + // because in-place construction is used later. + memset( (void*)(&m_a[i]), 0, sizeof(T) ); + ConstructDefaultElement( &m_a[i] ); + } + else { + ConstructDefaultElement( &m_a[m_count-1] ); + } + m_a[i] = x; // uses T::operator=() to copy x to array + } +} + +template +void ON_ClassArray::Remove( ) +{ + Remove(m_count-1); +} + +template +void ON_ClassArray::Remove( int i ) +{ + if ( i >= 0 && i < m_count ) + { + DestroyElement( m_a[i] ); + // This call to memset is ok even when T has a vtable + // because in-place construction is used later. + memset( (void*)(&m_a[i]), 0, sizeof(T) ); + Move( i, i+1, m_count-1-i ); + // This call to memset is ok even when T has a vtable + // because in-place construction is used later. + memset( (void*)(&m_a[m_count-1]), 0, sizeof(T) ); + ConstructDefaultElement(&m_a[m_count-1]); + m_count--; + } +} + +template +void ON_ClassArray::Empty() +{ + int i; + for ( i = m_count-1; i >= 0; i-- ) { + DestroyElement( m_a[i] ); + // This call to memset is ok even when T has a vtable + // because in-place construction is used later. + memset( (void*)(&m_a[i]), 0, sizeof(T) ); + ConstructDefaultElement( &m_a[i] ); + } + m_count = 0; +} + +template +void ON_ClassArray::Reverse() +{ + // NOTE: + // If anything in "T" depends on the value of this's address, + // then don't call Reverse(). + char t[sizeof(T)]; + int i = 0; + int j = m_count-1; + for ( /*empty*/; i < j; i++, j-- ) { + memcpy( (void*)(t), (void*)(&m_a[i]), sizeof(T) ); + memcpy( (void*)(&m_a[i]), (void*)(&m_a[j]), sizeof(T) ); + memcpy( (void*)(&m_a[j]), (void*)(t), sizeof(T) ); + } +} + +template +void ON_ClassArray::Swap( int i, int j ) +{ + if ( i != j && i >= 0 && j >= 0 && i < m_count && j < m_count ) { + char t[sizeof(T)]; + memcpy( (void*)(t), (void*)(&m_a[i]), sizeof(T) ); + memcpy( (void*)(&m_a[i]), (void*)(&m_a[j]), sizeof(T) ); + memcpy( (void*)(&m_a[j]), (void*)(t), sizeof(T) ); + } +} + +template +int ON_ClassArray::Search( const T* key, int (*compar)(const T*,const T*) ) const +{ + for ( int i = 0; i < m_count; i++ ) + { + if (!compar(key,m_a+i)) + return i; + } + return -1; +} + +template +int ON_ClassArray::BinarySearch( const T* key, int (*compar)(const T*,const T*) ) const +{ + const T* found = (key&&m_a&&m_count>0) ? (const T*)bsearch( key, m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar ) : nullptr; + return (nullptr != found && found >= m_a) ? ((int)(found - m_a)) : -1; +} + +template +int ON_ClassArray::BinarySearch( const T* key, int (*compar)(const T*,const T*), int count ) const +{ + if ( count > m_count ) + count = m_count; + if ( count <= 0 ) + return -1; + const T* found = (key&&m_a&&m_count>0) ? (const T*)bsearch( key, m_a, count, sizeof(T), (int(*)(const void*,const void*))compar ) : nullptr; + return (nullptr != found && found >= m_a) ? ((int)(found - m_a)) : -1; +} + + +template +int ON_ClassArray::InsertInSortedList(const T& e, int (*compar)(const T*, const T*)) +{ + const int count = m_count; + if (count < 0) + return -1; + if (0 == count) + { + Insert(0, e); + return 0; + } + + const unsigned ucount = ((unsigned)count); + unsigned i0 = 0; + unsigned i1 = ucount; + while (i0 < i1) + { + const unsigned i = (i0 + i1) / 2; + const int c = compar(&e, m_a + i); + if (c < 0) + { + i1 = i; + } + else if (c > 0) + { + i0 = i + 1; + } + else + { + i1 = i; + while (i1 + 1 < ucount && 0 == compar(&e, m_a + (i1 + 1))) + ++i1; + i0 = i1; + } + } + if (i0 <= ucount) + { + Insert(i0, e); + return ((int)i0); + } + + return -1; +} + + +template +int ON_ClassArray::InsertInSortedList(const T& e, int (*compar)(const T*, const T*), int count) +{ + if (count > m_count) + count = m_count; + if (count < 0) + return -1; + if (0 == count) + { + Insert(0, e); + return 0; + } + + const unsigned ucount = ((unsigned)count); + unsigned i0 = 0; + unsigned i1 = ucount; + while (i0 < i1) + { + const unsigned i = (i0 + i1) / 2; + const int c = compar(&e, m_a + i); + if (c < 0) + { + i1 = i; + } + else if (c > 0) + { + i0 = i + 1; + } + else + { + i1 = i; + while (i1 + 1 < ucount && 0 == compar(&e, m_a + (i1 + 1))) + ++i1; + i0 = i1; + } + } + if (i0 <= ucount) + { + Insert(i0, e); + return ((int)i0); + } + + return -1; +} + + +template +bool ON_ClassArray::HeapSort( int (*compar)(const T*,const T*) ) +{ + bool rc = false; + if ( m_a && m_count > 0 && compar ) + { + if ( m_count > 1 ) + ON_hsort( m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar ); + rc = true; + } + return rc; +} + +template +bool ON_ClassArray::QuickSort( int (*compar)(const T*,const T*) ) +{ + bool rc = false; + if ( m_a && m_count > 0 && compar ) + { + if ( m_count > 1 ) + ON_qsort( m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar ); + rc = true; + } + return rc; +} + + + +template +bool ON_ObjectArray::HeapSort( int (*compar)(const T*,const T*) ) +{ + bool rc = false; + // The "this->" in this->m_count and this->m_a + // are needed for gcc 4 to compile. + if ( this->m_a && this->m_count > 0 && compar ) + { + if ( this->m_count > 1 ) + { + ON_hsort( this->m_a, this->m_count, sizeof(T), (int(*)(const void*,const void*))compar ); + + // The MemoryRelocate step is required to synch userdata back pointers + // so the user data destructor will work correctly. + int i; + for ( i = 0; i < this->m_count; i++ ) + { + this->m_a[i].MemoryRelocate(); + } + } + rc = true; + } + return rc; +} + +template +bool ON_ObjectArray::QuickSort( int (*compar)(const T*,const T*) ) +{ + bool rc = false; + // The "this->" in this->m_count and this->m_a + // are needed for gcc 4 to compile. + if ( this->m_a && this->m_count > 0 && compar ) + { + if ( this->m_count > 1 ) + { + ON_qsort( this->m_a, this->m_count, sizeof(T), (int(*)(const void*,const void*))compar ); + + // The MemoryRelocate step is required to synch userdata back pointers + // so the user data destructor will work correctly. + int i; + for ( i = 0; i < this->m_count; i++ ) + { + this->m_a[i].MemoryRelocate(); + } + } + rc = true; + } + return rc; +} + + +template +bool ON_ClassArray::Sort( ON::sort_algorithm sa, int* index, int (*compar)(const T*,const T*) ) const +{ + bool rc = false; + if ( m_a && m_count > 0 && compar && index ) + { + if ( m_count > 1 ) + ON_Sort(sa, index, m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar ); + else if ( m_count == 1 ) + index[0] = 0; + rc = true; + } + return rc; +} + +template +bool ON_ClassArray::Sort( ON::sort_algorithm sa, int* index, int (*compar)(const T*,const T*,void*),void* p ) const +{ + bool rc = false; + if ( m_a && m_count > 0 && compar && index ) + { + if ( m_count > 1 ) + ON_Sort(sa, index, m_a, m_count, sizeof(T), (int(*)(const void*,const void*,void*))compar, p ); + else if ( m_count == 1 ) + index[0] = 0; + rc = true; + } + return rc; +} + +template +bool ON_ClassArray::Permute( const int* index ) +{ + bool rc = false; + if ( m_a && m_count > 0 && index ) + { + int i; + T* buffer = (T*)onmalloc(m_count*sizeof(buffer[0])); + memcpy( (void*)(buffer), (void*)(m_a), m_count*sizeof(T) ); + for (i = 0; i < m_count; i++ ) + memcpy( (void*)(m_a+i), (void*)(buffer+index[i]), sizeof(T) ); // must use memcopy and not operator= + onfree(buffer); + rc = true; + } + return rc; +} + +template +void ON_ClassArray::Zero() +{ + int i; + if ( m_a && m_capacity > 0 ) { + for ( i = m_capacity-1; i >= 0; i-- ) { + DestroyElement(m_a[i]); + // This call to memset is ok even when T has a vtable + // because in-place construction is used later. + memset( (void*)(&m_a[i]), 0, sizeof(T) ); + ConstructDefaultElement(&m_a[i]); + } + } +} + +// memory managment //////////////////////////////////////////////////// + +template +T* ON_ClassArray::Reserve( size_t newcap ) +{ + if( (size_t)m_capacity < newcap ) + SetCapacity( newcap ); + return m_a; +} + +template +void ON_ClassArray::Shrink() +{ + SetCapacity( m_count ); +} + +template +void ON_ClassArray::Destroy() +{ + SetCapacity( 0 ); +} + +// low level memory managment ////////////////////////////////////////// + +template +void ON_ClassArray::SetCount( int count ) +{ + if ( count >= 0 && count <= m_capacity ) + m_count = count; +} + +template +T* ON_ClassArray::SetCapacity( size_t new_capacity ) +{ + if (0 == m_capacity) + { + // Allow "expert" users of ON_SimpleArray<>.SetArray(*,*,0) to clean up after themselves + // and deals with the case when the forget to clean up after themselves. + m_a = nullptr; + m_count = 0; + } + // uses "placement" for class construction/destruction + int i; + int capacity = (new_capacity > 0 && new_capacity < ON_UNSET_UINT_INDEX) + ? (int)new_capacity + : 0; + + if ( capacity <= 0 ) { + if ( m_a ) { + for ( i = m_capacity-1; i >= 0; i-- ) { + DestroyElement(m_a[i]); + } + Realloc(m_a,0); + m_a = 0; + } + m_count = 0; + m_capacity = 0; + } + else if ( m_capacity < capacity ) { + // growing + m_a = Realloc( m_a, capacity ); + // initialize new elements with default constructor + if ( 0 != m_a ) + { + // even when m_a is an array of classes with vtable pointers, + // this call to memset(..., 0, ...) is what I want to do + // because in-place construction will be used when needed + // on this memory. + memset( (void*)(m_a + m_capacity), 0, (capacity-m_capacity)*sizeof(T) ); + for ( i = m_capacity; i < capacity; i++ ) { + ConstructDefaultElement(&m_a[i]); + } + m_capacity = capacity; + } + else + { + // memory allocation failed + m_capacity = 0; + m_count = 0; + } + } + else if ( m_capacity > capacity ) { + // shrinking + for ( i = m_capacity-1; i >= capacity; i-- ) { + DestroyElement(m_a[i]); + } + if ( m_count > capacity ) + m_count = capacity; + m_capacity = capacity; + m_a = Realloc( m_a, capacity ); + if ( 0 == m_a ) + { + // memory allocation failed + m_capacity = 0; + m_count = 0; + } + } + return m_a; +} + +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// + +template< class T> +int ON_CompareIncreasing( const T* a, const T* b) +{ + if( *a < *b ) + return -1; + if( *b < *a ) + return 1; + return 0; +} + +template< class T> +int ON_CompareDecreasing( const T* a, const T* b) +{ + if( *b < *a ) + return -1; + if( *a < *b ) + return 1; + return 0; +} + +#pragma ON_PRAGMA_WARNING_POP + +#endif diff --git a/opennurbs/Include/opennurbs_atomic_op.h b/opennurbs/Include/opennurbs_atomic_op.h new file mode 100644 index 0000000..d025c5a --- /dev/null +++ b/opennurbs/Include/opennurbs_atomic_op.h @@ -0,0 +1,22 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2018 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_ATOMIC_OP_INC_) +#define OPENNURBS_ATOMIC_OP_INC_ + +#error OBSOLETE FILE + +#endif diff --git a/opennurbs/Include/opennurbs_base32.h b/opennurbs/Include/opennurbs_base32.h new file mode 100644 index 0000000..b5a6385 --- /dev/null +++ b/opennurbs/Include/opennurbs_base32.h @@ -0,0 +1,126 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_BASE32_INC_) +#define ON_BASE32_INC_ + + +/* +Description: + Convert a number into base32 digits. +Parameters: + x - [in] + x_count - [in] + x[] is an array of length x_count and represents the value + x[0]*2^(8*(x_count-1)) + ... + x[x_count-2]*256 + x[x_count-1]. + base32_digits - [out] + When base32_digits is not a dynamic array, base32_digits[] + must a be an array of length at least + ((8*x_count)/5) + (((8*x_count)%5)?1:0) or 1, + whichever is greater. + + The base32_digits[] array will be filled in with base32 digit + values (0 to 31) so that the value + b[0]*32^(b_count-1) + ... + b[b_count-2]*32 + b[b_count-1] + is the same as that defined by the x[] array. +Returns + The number of base 32 digits in the base32_digits[] array. + If 0 is returned, the input is not valid. +*/ +ON_DECL +int ON_GetBase32Digits( const ON_SimpleArray& x, ON_SimpleArray& base32_digits ); +ON_DECL +int ON_GetBase32Digits( const unsigned char* x, int x_count, unsigned char* base32_digits ); + + +/* +Description: + Convert a list of base32 digits into a string form. +Parameters: + base32_digits - [in] + base32_digit_count - [in] + base32_digits[] is an array of length base32_digit_count. + Each element is in the range 0 to 31. + sBase32 - [out] + sBase32[] must be an array of length base32_digit_count+1 or 2, + whichever is greater. The string representation of the base 32 + number will be put in this string. A hash mark symbol (#) is + used to indicate an error in the input value. The returned + string is null terminated. +Returns + True if the input is valid. False if the input is not valid, + in which case hash marks indicate the invalid entries. +*/ +ON_DECL +bool ON_Base32ToString( const ON_SimpleArray& base32_digits, ON_String& sBase32 ); +ON_DECL +bool ON_Base32ToString( const ON_SimpleArray& base32_digits, ON_wString& sBase32 ); +ON_DECL +bool ON_Base32ToString( const unsigned char* base32_digits, int base32_digit_count, char* sBase32 ); + + +/* +Description: + Fixt a common typos in sBase32 string. Lower case letters are + converted to upper case. The letters 'I', 'L', 'O' and 'S' are + converted to '1' (one), '1' (one) '0' zero and '5' (five). +Parameters: + sBase32 - [in] + sBase32clean - [out] + (can be the same string as sBase32) +Returns: + If the input is valid, the length of the converted string is returned. + If the input is not valid, 0 is returned. +*/ +ON_DECL +int ON_CorrectBase32StringTypos( const wchar_t* sBase32, ON_wString& sBase32clean ); +ON_DECL +int ON_CorrectBase32StringTypos( const char* sBase32, ON_String& sBase32clean ); +ON_DECL +int ON_CorrectBase32StringTypos( const char* sBase32, char* sBase32clean ); + + +/* +Description: + Convert a null terminate string containing the 32 symbols + + 0 1 2 3 4 5 6 7 8 9 A B C D E F G H J K M N P Q R T U V W X Y Z + + (I,L,O and S are missing) into a list of base 32 digits. +Parameters: + sBase32 - [in] + String with base 32 digits + base32_digits - [out] + base32_digits[] is an array of length strlen(sBase32). + The returned array, element will be in the range 0 to 31. + sBase32[] must be an array of length base32_digit_count+1 or 2, + whichever is greater. The string representation of the base 32 + number will be put in this string. A hash mark symbol (#) is + used to indicate an error in the input value. The returned + string is null terminated. +Returns + True if the input is valid. False if the input is not valid, + in which case hash marks indicate the invalid entries. +*/ +ON_DECL +int ON_StringToBase32(const ON_wString& sBase32, ON_SimpleArray& base32_digits ); +ON_DECL +int ON_StringToBase32(const ON_String& sBase32, ON_SimpleArray& base32_digits ); +ON_DECL +int ON_StringToBase32(const char* sBase32, unsigned char* base32_digits ); + + +#endif diff --git a/opennurbs/Include/opennurbs_base64.h b/opennurbs/Include/opennurbs_base64.h new file mode 100644 index 0000000..bfbb9d2 --- /dev/null +++ b/opennurbs/Include/opennurbs_base64.h @@ -0,0 +1,345 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_BASE64_INC_) +#define OPENNURBS_BASE64_INC_ + +////////////////////////////////////////////////////////////////////////////////////////// + +class ON_CLASS ON_Base64EncodeStream +{ +public: + ON_Base64EncodeStream(); + virtual ~ON_Base64EncodeStream(); + + /* + Description: + ON_Base64EncodeStream delivers the base64 encoded stream by + calling a base64 encoded stream output handler function. + There are two options for specifying the base64 encoded stream + output handler function. + 1. Overriding the virtual Out() function. + 2. Providing a callback function. + SetCallback() is used to specify a callback function to handle + the base64 encoded stream and to specify a context pointer to be + passed to either option of the handler. + Parameters: + callback_function - [in] + Function to handle sections of the base64 encoded stream. + If callback_function is null, then the virtual Out() + function will be called. When callback_function + is specified, it must return true if the base64 encoding + calculation should continue and false to cancel the + base64 encoding calculation. + callback_context - [in] + This value is passed as the first argument when calling + callback_function or the virutal Out() function. + Returns: + True if successful. + Remarks: + Once base64 encoding has started, it would be unusual to + intentionally change the base64 encoded stream output handler, + but you can do this if you need to. + */ + bool SetCallback( + ON_StreamCallbackFunction callback_function, + void* callback_context + ); + + /* + Returns: + Current value of the callback function for handling + the base64 encoded stream. If the callback function is + null, the the virtual Out() function is used to + handle the output stream. + */ + ON_StreamCallbackFunction CallbackFunction() const; + + /* + Returns: + Current value of the context pointer passed as the first + argument to the base64 encoded stream output handler function. + */ + void* CallbackContext() const; + + /* + Description: + Call Begin() one time to initialize the base64 encoding + calculation. Then call In() one or more times + to submit the unencoded stream to the base64 encoding + calculation. When you reach the end of the unencoded + stream, call End(). + Returns: + true if successful, false if an error occured. + */ + bool Begin(); + + + /* + Description: + Call In() one or more times to base64 encode a stream of bytes. + After the last call to In(), call End(). Calling In() will + result in at least in_buffer_size/57 and at most + (in_buffer_size+56)/57 calls to to the output stream handler. + Parameters: + in_buffer_size - [in] + number of bytes in in_buffer + in_buffer - [in] + Returns: + true if successful, false if an error occured. + */ + bool In( + ON__UINT64 in_buffer_size, + const void* in_buffer + ); + + /* + Description: + If an explicit base 64 encoded stream output handler is not + specified ( CallbackFunction() returns null ), then the + virtual Out() function is called to handle the base 64 encoded + output stream. As the input stream is encoded, one or more + calls to Out() will occur. + + With a possible exception of the last call to Out(), when Out() + is called, 57 input bytes have been encoded into 76 output + characters with ASCII codes A-Z, a-z, 0-9, +, /. + Parameters: + callback_context - [in] + context pointer set by calling SetCallback(). Typically + the context pointer is not used by a virtual override + because the context can be added as member variables + of the derived class, but it is available if needed. + out_buffer_size - [in] + number of non-null characters in out_buffer. + out_buffer - [in] + A null terminated ASCII string that is a base 64 encoding. + out_buffer[0...(out_buffer_size-1)] are ASCII characters with + values characters with ASCII codes A-Z, a-z, 0-9, +, / + and out_buffer[out_buffer_size] = 0. + Returns: + True to continue base 64 encodeing and false to cancel the + encoding calculation. + */ + virtual bool Out( + void* callback_context, + ON__UINT32 out_buffer_size, + const char* out_buffer + ); + + /* + Description: + After the last call to In(), call End(). Calling End() may + generate one call to the output stream handler with the value + of out_buffer_size = 4 to 76. + Returns: + true if successful, false if an error occured. + */ + bool End(); + + /* + Returns: + Then the returned value is the total number bytes in the input + stream. The size is updated every time In() is called before + any calls are made to the output stream handler. If the + calculation is finished ( End() has been called ), then the + returned value is the total number of bytes in the entire + input stream. + */ + ON__UINT64 InSize() const; + + /* + Returns: + Then the returned value is the total number characters in the + output stream. The size is incremented immediately after each + call to the output stream handler. If the base64 encoding + calculation is finished ( End() has been called ), then the + returned value is the total number of bytes in the entire + output stream. + */ + ON__UINT64 OutSize() const; + + /* + Returns: + Then the returned value is the 32-bit crc of the input stream. + The crc is updated every time In() is called before any calls + are made to the output stream handler. If the base64 encoding + calculation is finished ( End() has been called ), then the + returned value is the 32-bit crc of the entire input stream. + */ + ON__UINT32 InCRC() const; + + /* + Returns: + Then the returned value is the 32bit crc of the output stream. + The crc is updated immediately after each call to the output + stream handler. If the calculation is finished ( End() has + been called ), then the returned value is the 32-bit crc of + the entire output stream. + */ + ON__UINT32 OutCRC() const; + +private: + ON_StreamCallbackFunction m_out_callback_function; + void* m_out_callback_context; + ON__UINT64 m_in_size; + ON__UINT64 m_out_size; + ON__UINT32 m_in_crc; + ON__UINT32 m_out_crc; + void* m_implementation; + void* m_reserved; + + void ErrorHandler(); + +private: + // prohibit use - no implementation + ON_Base64EncodeStream(const ON_Base64EncodeStream&); + ON_Base64EncodeStream& operator=(const ON_Base64EncodeStream&); +}; + +////////////////////////////////////////////////////////////////////////////////////////// + +class ON_CLASS ON_DecodeBase64 +{ +public: + ON_DecodeBase64(); + virtual ~ON_DecodeBase64(); + + void Begin(); + + // Decode will generate zero or more callbacks to the + // virtual Output() function. If the base 64 encoded information + // is in pieces, you can call Decode() for each piece. For example, + // if your encoded information is in a text file, you might call + // Decode() for every line in the file. Decode() returns 0 if + // there is nothing in base64str to decode or if it detects an + // error that prevents any further decoding. The function Error() + // can be used to determine if an error occured. Otherwise, + // Decode() returns a pointer to the location in the string where + // it stopped decoding because it detected a character, like a null + // terminator, an end of line character, or any other character + // that could not be part of the base 64 encoded information. + const char* Decode(const char* base64str); + const char* Decode(const char* base64str, size_t base64str_count); + const wchar_t* Decode(const wchar_t* base64str); + const wchar_t* Decode(const wchar_t* base64str, size_t base64str_count); + + // You must call End() when Decode() returns 0 or when you have + // reached the end of your encoded information. End() may + // callback to Output() zero or one time. If all the information + // passed to Decode() was successfully decoded, then End() + // returns true. If something was not decoded, then End() + // returns false. + bool End(); + + // Override the virtual Output() callback function to process the + // decoded output. Each time Output() is called there are m_output_count + // bytes in the m_output[] array. + // Every call to Decode() can result in zero, one, or many callbacks + // to Output(). Calling End() may result in zero or one callbacks + // to Output(). + virtual void Output(); + + // m_decode_count = total number of input base64 characters + // that Decode() has decoded. + unsigned int m_decode_count; + + int m_output_count; // 0 to 512 + unsigned char m_output[512]; + + // Call if your Output() function detects an error and + // wants to stop further decoding. + void SetError(); + + // Returns true if an error occured during decoding because + // invalid input was passed to Decode(). + const bool Error() const; + +private: + int m_status; // 1: error - decoding stopped + // 2: '=' encountered as 3rd char in Decode() + // 3: successfully parsed "**==" + // 4: successfully parsed "***=" + // 5: End() successfully called. + + // cached encoded input from previous call to Decode() + int m_cache_count; + int m_cache[4]; + + void DecodeHelper1(); // decodes "**==" quartet into 1 byte + void DecodeHelper2(); // decodes "***=" quartet into 2 bytes +}; + + +///////////////////////////////////////////////////////////////////// + + +/* +class ON_CLASS ON_EncodeBase64 +{ +public: + ON_EncodeBase64(); + virtual ~ON_EncodeBase64(); + + void Begin(); + + // Calling Encode will generate at least + // sizeof_buffer/57 and at most (sizeof_buffer+56)/57 + // calls to Output(). Every callback to Output() will + // have m_output_count = 76. + void Encode(const void* buffer, size_t sizeof_buffer); + + // Calling End may generate a single call to Output() + // If it does generate a single call to Output(), + // then m_output_count will be between 1 and 76. + void End(); // may generate a single call to Output(). + + // With a single exception, when Output() is called, + // 57 input bytes have been encoded into 76 output + // characters with ASCII codes A-Z, a-z, 0-9, +, /. + // m_output_count will be 76 + // m_output[0...(m_output_count-1)] will be the base 64 + // encoding. + // m_output[m_output_count] = 0. + // The Output() function can modify the values of m_output[] + // and m_output_count anyway it wants. + virtual void Output(); + + // Total number of bytes passed to Encode(). + int m_encode_count; + + // When the virtual Output() is called, there are m_output_count (1 to 76) + // characters of base64 encoded output in m_output[]. The remainder of + // the m_output[] array is zero. The Output function may modify the + // contents of m_output[] any way it sees fit. + int m_output_count; + char m_output[80]; + +private: + // input waiting to be encoded + // At most 56 bytes can be waiting to be processed in m_input[]. + unsigned int m_unused2; // Here for alignment purposes. Never used by opennurbs. + unsigned int m_input_count; + unsigned char m_input[64]; + + void EncodeHelper1(const unsigned char*, char*); + void EncodeHelper2(const unsigned char*, char*); + void EncodeHelper3(const unsigned char*, char*); + void EncodeHelper57(const unsigned char*); +}; +*/ + +#endif diff --git a/opennurbs/Include/opennurbs_beam.h b/opennurbs/Include/opennurbs_beam.h new file mode 100644 index 0000000..6ddc1d8 --- /dev/null +++ b/opennurbs/Include/opennurbs_beam.h @@ -0,0 +1,1000 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2014 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_EXTRUSION_INC_) +#define OPENNURBS_EXTRUSION_INC_ + +/* +Description: + Get the transformation that maps the ON_Extrusion + 2d xy profile to 3d world space. +Parameters: + P - [in] start or end of path + T - [in] unit tanget to path + U - [in] unit up vector perpendicular to T + Normal - [in] optional unit vector with Normal->z > 0 that + defines the unit normal to the miter plane. + xform - [out] + transformation that maps the profile curve to 3d world space + scale2d - [out] + If not nullptr, this is the scale part of the transformation. + If there is no mitering, then this is the identity. + rot2d - [out] + If not null, this is the part of the transformation + that rotates the xy plane into its 3d world location. +Returns: + true if successful. +*/ +ON_DECL +bool ON_GetEndCapTransformation( + ON_3dPoint P, + ON_3dVector T, + ON_3dVector U, + const ON_3dVector* Normal, + ON_Xform& xform, // = rot3d*scale2d + ON_Xform* scale2d, + ON_Xform* rot2d + ); + +class ON_CLASS ON_Extrusion : public ON_Surface +{ + ON_OBJECT_DECLARE(ON_Extrusion); +public: + ON_Extrusion(); + ON_Extrusion(const ON_Extrusion& src); + ~ON_Extrusion(); + + ON_Extrusion& operator=(const ON_Extrusion&); + + //////////////////////////////////////////////////////////// + // + // overrides of virtual ON_Object functions + // + void DestroyRuntimeCache( bool bDelete = true ) override; + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + void Dump( ON_TextLog& ) const override; + unsigned int SizeOf() const override; + ON__UINT32 DataCRC( ON__UINT32 current_remainder ) const override; + bool Write( ON_BinaryArchive& binary_archive) const override; + bool Read( ON_BinaryArchive& binary_archive ) override; + ON::object_type ObjectType() const override; + + //////////////////////////////////////////////////////////// + // + // overrides of virtual ON_Geometry functions + // + int Dimension() const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + // virtual ON_Geometry GetTightBoundingBox override + bool GetTightBoundingBox( class ON_BoundingBox& tight_bbox, bool bGrowBox = false, const class ON_Xform* xform = nullptr ) const override; + + bool Transform( + const ON_Xform& xform + ) override; + + /* + Description: + Build a brep form of the extrusion. The outer profile is always + the first face in the brep. If there are inner profiles, + additional brep faces are created for each profile. If the + outer profile is closed, then end caps are added as the last + two faces in the brep. + Parameters: + brep - [in] + If the brep pointer is not null, then the brep form is constructed + in brep. If the brep pointer is null, then an ON_Brep is allocated + on the heap. + Returns: + If successful, a pointer to the brep form. If unsuccessful, null. + */ + ON_Brep* BrepForm( + ON_Brep* brep = nullptr + ) const override; + + /* + Description: + Build a brep form of the extrusion. The outer profile is always + the first face in the brep. If there are inner profiles, + additional brep faces are created for each profile. If the + outer profile is closed, then end caps are added as the last + two faces in the brep. + Parameters: + brep - [in] + If the brep pointer is not null, then the brep form is constructed + in brep. If the brep pointer is null, then an ON_Brep is allocated + on the heap. + bSmoothFaces - [in] + If true and the profiles have kinks, then the faces corresponding + to those profiles are split so they will be G1. + Returns: + If successful, a pointer to the brep form. If unsuccessful, null. + */ + ON_Brep* BrepForm( + ON_Brep* brep, + bool bSmoothFaces + ) const; + + /* + Description: + Build a sum surface form of the extrusion. + Parameters: + sum_surface - [in] + If the sum_surface pointer is not null, then the sum surface + form is constructed in sum_surface. If the sum_surface pointer + is null, then an ON_SumSurface is allocated on the heap. + Returns: + If successful, a pointer to the sum surface form. + If unsuccessful, null. In particular, extrusions with + mitered ends do not have sum surface forms. + */ + ON_SumSurface* SumSurfaceForm( + ON_SumSurface* sum_surface + ) const; + + /* + Description: + Convert a component index that identifies a part of this extrusion + to a component index that identifies a part of the brep created + by BrepForm(...,false). + Parameters: + extrusion_ci - [in] + extrusion_profile_parameter - [in] + brep_form - [in] + brep created by ON_Extrusion::BrepForm() + brep_ci - [out] + Returns: + True if successful. False if input is not valid, in which case brep_ci + is set by calling ON_COMPONENT_INDEX::UnSet(). + Remarks: + If the wall surfaces have creases, then this function cannot + be used to identify brep components created by BrepForm(...,true). + */ + bool GetBrepFormComponentIndex( + ON_COMPONENT_INDEX extrusion_ci, + ON_COMPONENT_INDEX& brep_ci + ) const; + + bool GetBrepFormComponentIndex( + ON_COMPONENT_INDEX extrusion_ci, + double extrusion_profile_parameter, + const ON_Brep& brep_form, + ON_COMPONENT_INDEX& brep_ci + ) const; + + bool GetBrepFormComponentIndex( + ON_COMPONENT_INDEX extrusion_ci, + double extrusion_profile_parameter, + const ON_Brep* brep_form, + ON_COMPONENT_INDEX& brep_ci + ) const; + + //////////////////////////////////////////////////////////// + // + // overrides of virtual ON_Surface functions + // + + bool SetDomain( + int dir, + double t0, + double t1 + ) override; + ON_Interval Domain( + int dir + ) const override; + bool GetSurfaceSize( + double* width, + double* height + ) const override; + int SpanCount( + int dir + ) const override; + bool GetSpanVector( + int dir, + double* span_vector + ) const override; + bool GetSpanVectorIndex( + int dir, + double t, + int side, + int* span_vector_index, + ON_Interval* span_interval + ) const override; + int Degree( + int dir + ) const override; + bool GetParameterTolerance( + int dir, + double t, + double* tminus, + double* tplus + ) const override; + ISO IsIsoparametric( + const ON_Curve& curve, + const ON_Interval* curve_domain = nullptr + ) const override; + bool IsPlanar( + ON_Plane* plane = nullptr, + double tolerance = ON_ZERO_TOLERANCE + ) const override; + bool IsClosed( + int + ) const override; + bool IsPeriodic( + int + ) const override; + bool GetNextDiscontinuity( + int dir, + ON::continuity c, + double t0, + double t1, + double* t, + int* hint=nullptr, + int* dtype=nullptr, + double cos_angle_tolerance=ON_DEFAULT_ANGLE_TOLERANCE_COSINE, + double curvature_tolerance=ON_SQRT_EPSILON + ) const override; + bool IsContinuous( + ON::continuity c, + double s, + double t, + int* hint = nullptr, + double point_tolerance=ON_ZERO_TOLERANCE, + double d1_tolerance=ON_ZERO_TOLERANCE, + double d2_tolerance=ON_ZERO_TOLERANCE, + double cos_angle_tolerance=ON_DEFAULT_ANGLE_TOLERANCE_COSINE, + double curvature_tolerance=ON_SQRT_EPSILON + ) const override; + ISO IsIsoparametric( + const ON_BoundingBox& bbox + ) const override; + bool Reverse( int dir ) override; + bool Transpose() override; + bool Evaluate( + double u, double v, + int num_der, + int array_stride, + double* der_array, + int quadrant = 0, + int* hint = 0 + ) const override; + ON_Curve* IsoCurve( + int dir, + double c + ) const override; + + + bool Trim( + int dir, + const ON_Interval& domain + ) override; + bool Extend( + int dir, + const ON_Interval& domain + ) override; + bool Split( + int dir, + double c, + ON_Surface*& west_or_south_side, + ON_Surface*& east_or_north_side + ) const override; + + + //ON_Surface* Offset( + // double offset_distance, + // double tolerance, + // double* max_deviation = nullptr + // ) const; + + int GetNurbForm( + ON_NurbsSurface& nurbs_surface, + double tolerance = 0.0 + ) const override; + int HasNurbForm() const override; + bool GetSurfaceParameterFromNurbFormParameter( + double nurbs_s, double nurbs_t, + double* surface_s, double* surface_t + ) const override; + bool GetNurbFormParameterFromSurfaceParameter( + double surface_s, double surface_t, + double* nurbs_s, double* nurbs_t + ) const override; + + + //////////////////////////////////////////////////////////// + // + // ON_Extrusion mesh interface + // + + /* + Description: + Attach a mesh to the ON_Extrusion. + Parameters: + mt - [in] + type of mesh that is being attached. + If mt is ON::render_mesh, ON::analysis_mesh or ON::preview_mesh, + the mesh is attached as that type of mesh. + If mt is ON::default_mesh or ON::any_mesh, then + nothing is done and false is returned. + mesh - [in] + * mesh to attach. + * mesh must be on the heap because ~ON_Extrusion() + will delete it. + * if there is already of mesh of the prescribed type, + it will be deleted. + * if mesh is null, any existing mesh is deleted and + nothing is attached. + Remarks: + DEPRECATED. Use ON_Extrusion.m_mesh_cache to managed chached meshes. + */ + ON_DEPRECATED_MSG("Use ON_Extrusion.m_mesh_cache to managed chached meshes") + bool SetMesh( ON::mesh_type mt, ON_Mesh* mesh ); + + /* + Description: + Get a mesh attached to the ON_Extrusion. + Parameters: + mt - [in] + type of mesh to get. + ON::render_mesh, ON::analysis_mesh and ON::preview_mesh + remove the meshes of those types. + If mt is ON::default_mesh or ON::any_mesh, then + the first non null mesh is returned. + Returns: + A pointer to a mesh on the ON_Extusion object. + This mesh will be deleted by ~ON_Extrusion(). + If a mesh of the requested type is not available, + then null is returned. + Remarks: + DEPRECATED. Use ON_Extrusion.m_mesh_cache to managed chached meshes. + */ + ON_DEPRECATED_MSG("Use ON_Extrusion.m_mesh_cache to managed chached meshes") + const ON_Mesh* Mesh( ON::mesh_type mt ) const; + + /* + Description: + Destroy a mesh attached to the ON_Extrusion. + Parameters: + mt - [in] type of mesh to destroy + If mt is ON::default_mesh or ON::any_mesh, then + all attached meshes of all types are destroyed. + bDeleteMesh - [in] if true, cached mesh is deleted. + If false, pointer to cached mesh is just set to null. + Remarks: + DEPRECATED. Use ON_Extrusion.m_mesh_cache to managed chached meshes. + */ + ON_DEPRECATED_MSG("Use ON_Extrusion.m_mesh_cache to managed chached meshes") + void DestroyMesh( ON::mesh_type mt ); + + //////////////////////////////////////////////////////////// + // + // ON_Extrusion interface + // + void Destroy(); + + /* + Description: + Sets m_path to (A,B), m_path_domain to [0,Length(AB)], + and m_t to [0,1]. + Parameters: + A - [in] path start + B - [in] path end + Returns: + true A and B are valid, the distance from A to B is larger + than ON_ZERO_TOLERANCE, and the path was set. + false A or B is not valid or the distance from A to B is + at most ON_ZERO_TOLERANCE. In this case nothing is set. + Remark: + You must also set the up direction to be perpendicular to the path. + */ + bool SetPath(ON_3dPoint A, ON_3dPoint B); + + /* + Description: + Sets m_path to (A,B), m_path_domain to [0,Length(AB)], + m_t to [0,1], and m_up. + Parameters: + A - [in] path start + B - [in] path end + up - [in] up direction + If up is a unit vector and perpendicular to the line + segment from A to B, then m_up is set to up. + Otherwise up will be adjusted so it is perpendicular + to the line segment from A to B and unitized. + Returns: + true A and B are valid, the distance from A to B is larger + than ON_ZERO_TOLERANCE, and the path was set. + false A or B is not valid, or the distance from A to B is + at most ON_ZERO_TOLERANCE, or up is invalid, or up + is zero, or up is parallel to the line segment. + In this case nothing is set. + */ + bool SetPathAndUp(ON_3dPoint A, ON_3dPoint B, ON_3dVector up ); + + /* + Description: + Get the surface parameter for the path. + Returns: + 0: The first surface parameter corresponds to the path direction. + (m_bTransposed = true) + 1: The second surface parameter corresponds to the path direction. + (m_bTransposed = false) + Remarks: + The default ON_Extrusion constructor sets + m_bTransposed = false which corresponds to the 1 = PathParameter(). + */ + int PathParameter() const; + + ON_3dPoint PathStart() const; + ON_3dPoint PathEnd() const; + ON_3dVector PathTangent() const; + + /* + Description: + Set miter plane normal. + Parameters: + N - [in] If N = ON_3dVector::UnsetVector or N is parallel to the z-axis, + then the miter plane is the default plane + perpendicular to the path. + If N is valid and the z coordinate of a unitized + N is greater than m_Nz_tol, then the miter plane + normal is set. + end - [in] 0 = set miter plane at the start of the path. + 1 = set miter plane at the end of the path. + */ + bool SetMiterPlaneNormal(ON_3dVector N, int end); + + void GetMiterPlaneNormal(int end, ON_3dVector& N) const; + + /* + Returns: + 0: not mitered. + 1: start of path is mitered. + 2: end of path is mitered. + 3: start and end are mitered. + */ + int IsMitered() const; + + /* + Returns: + True if extrusion object is a capped solid. + */ + bool IsSolid() const; + + /* + Returns: + 0: no or profile is open + 1: bottom cap + 2: top cap + 3: both ends capped. + */ + int IsCapped() const; + + /* + Returns: + 0: no caps + 1: exrusion has either a top cap or a bottom cap + 2: both ends are capped. + See Also: + ON_Extrusion::ProfileCount() + ON_Extrusion::ProfileSmoothSegmentCount() + */ + int CapCount() const; + + /* + Description: + Deprecated function. + + Use CapCount() to determine how many end caps there are. + Use ProfileCount() to determine how many profiles there are. + Use ProfileSmoothSegmentCount() to determine how many + smooth subsegments are in a profile. Each smooth subsegment + becomes a wall face in the brep form. + + Returns: + Number of "faces" the extrusion has. + 0: extrusion is not valid + 1: extrusion is not capped + 2: extrusion has a closed outer profile and one cap + 3: extrusion has a closed outer profile and two caps + + Remarks: + This function was written before extrusions supported "holes" + and before the brep form was divided at profile creases. + At this point it simply leads to confusion. See the Description + function replacements. + */ + ON_DEPRECATED_MSG("Use CapCount(), ProfileCount(), or ProfileSmoothSegmentCount()") + int FaceCount() const; + + /* + Description: + Get the transformation that maps the xy profile curve + to its 3d location. + Parameters: + s - [in] 0.0 = starting profile + 1.0 = ending profile + */ + bool GetProfileTransformation( double s, ON_Xform& xform ) const; + + /* + Description: + Get the the 3d plane containing the profile curve at a + normalized path parameter. + Parameters: + s - [in] 0.0 = starting plane + 1.0 = ending plane + plane - [out] + Plane containing profile is returned in plane. If + false is returned, then the input value of plane + is not changed. + Returns: + true if plane was set. False if this is invalid and plane + could not be set. + Remarks: + When no mitering is happening, GetPathPlane() and + GetProfilePlane() return the same plane. + */ + bool GetProfilePlane( double s, ON_Plane& plane ) const; + + + /* + Description: + Get the the 3d plane perpendicular to the path at a + normalized path parameter. + Parameters: + s - [in] 0.0 = starting plane + 1.0 = ending plane + plane - [out] + Plane is returned here. If + false is returned, then the input value of plane + is not changed. + Returns: + true if plane was set. False if this is invalid and plane + could not be set. + Remarks: + When no mitering is happening, GetPathPlane() and + GetProfilePlane() return the same plane. + */ + bool GetPathPlane( double s, ON_Plane& plane ) const; + + /* + Description: + Set the outer profile of the extrusion. + Paramters: + outer_profile - [in] + curve in the xy plane or a 2d curve. + bCap - [in] + If outer_profile is a closed curve, then bCap + determines if the extrusion has end caps. + If outer_profile is an open curve, bCap is ignored. + Returns: + True if the profile was set. In this case the ON_Extrusion class + manages the curve and ~ON_Extrusion will delete it. If the outer + profile is closed, then the extrusion may also have inner profiles. + If the outer profile is open, the extrusion may not have inner + profiles. If the extrusion already has a profile, the set will + fail. + Remarks: + If needed, outer_profile will be converted to a 2d + curve. If outer_curve is closed but not correctly oriented, + it will reversed so it has a counter-clockwise orientation. + */ + bool SetOuterProfile( ON_Curve* outer_profile, bool bCap ); + + /* + Description: + Add an inner profile. + Paramters: + inner_profile - [in] + closed curve in the xy plane or a 2d curve. + Returns: + True if the profile was set. In this case the + ON_Extrusion class manages the curve and ~ON_Extrusion will + delete it. The extrusion must already have an outer profile. + If the extrusion already has a profile, the set will + fail. + Remarks: + If needed, innter_profile will be converted to a 2d + curve. If inner_profile is not correctly oriented, it + will be reversed so it has a clockwise orientation. + */ + bool AddInnerProfile( ON_Curve* inner_profile ); + + /* + Returns: + Number of profile curves. + See Also: + ON_Extrusion::CapCount() + ON_Extrusion::ProfileSmoothSegmentCount() + */ + int ProfileCount() const; + + /* + Parameter: + profile_index - [in] + 0 <= profile_index < ProfileCount(). + The outer profile has index 0. + Returns: + Number of smooth segments in the profile curve. + See Also: + ON_Extrusion::CapCount() + ON_Extrusion::GetProfileKinkParameters() + ON_Extrusion::ProfileCount() + */ + int ProfileSmoothSegmentCount( int profile_index ) const; + + /* + Description: + Get the surface parameter for the profile. + Returns: + 0: The first surface parameter corresponds to the profile direction. + (m_bTransposed = false) + 1: The second surface parameter corresponds to the profile direction. + (m_bTransposed = true) + Remarks: + The default ON_Extrusion constructor sets + m_bTransposed = false which corresponds to the 0 = ProfileParameter(). + */ + int ProfileParameter() const; + + /* + Paramters: + profile_index - [in] + 0 <= profile_index < ProfileCount(). + The outer profile has index 0. + Returns: + Pointer to the i-th 2d profile. The ON_Extrusion + class manages this curve. Do not delete it + and do not use the pointer if the ON_Extrusion + class changes. + */ + const ON_Curve* Profile(int profile_index) const; + + /* + Paramters: + profile_index - [in] + 0 <= profile_index < ProfileCount(). + The outer profile has index 0. + s - [in] ( 0.0 <= s <= 1.0 ) + A relative parameter controling which priofile + is returned. s = 0.0 returns the bottom profile + and s = 1.0 returns the top profile. + Returns: + nullptr if the input parameters or the ON_Extrusion class is + not valid. Otherwise a pointer to a 3d curve for + the requested profile. This curve is on the heap and + the caller is responsible for deleting this curve. + */ + ON_Curve* Profile3d(int profile_index, double s ) const; + + /* + Paramters: + ci - [in] + component index identifying a 3d extrusion profile curve. + Returns: + nullptr if the component index or the ON_Extrusion class is + not valid. Otherwise a pointer to a 3d curve for + the requested profile. This curve is on the heap and + the caller is responsible for deleting this curve. + */ + ON_Curve* Profile3d( ON_COMPONENT_INDEX ci ) const; + + /* + Paramters: + ci - [in] + component index identifying a wall edge curve. + Returns: + nullptr if the component index or the ON_Extrusion class is + not valid. Otherwise a pointer to a 3d curve for + the requested wall edge. This curve is on the heap and + the caller is responsible for deleting this curve. + */ + ON_Curve* WallEdge( ON_COMPONENT_INDEX ci ) const; + + /* + Paramters: + ci - [in] + component index identifying a wall surface. + Returns: + nullptr if the component index or the ON_Extrusion class is + not valid. Otherwise a pointer to a surface for + the requested wall surface. This curve is on the heap and + the caller is responsible for deleting this curve. + */ + ON_Surface* WallSurface( ON_COMPONENT_INDEX ci ) const; + + /* + Paramters: + line_curve - [in] + If null, a line curve will be allocated using new. + Returns: + Null if the extrusion path is not valid. Otherwise + a pointer to an ON_LineCurve that is set to the + extrusion's path. The caller must delete this curve. + */ + ON_LineCurve* PathLineCurve(ON_LineCurve* line_curve) const; + + /* + Paramters: + profile_parameter - [in] + parameter on profile curve + Returns: + -1: if the profile_parameter does not correspond + to a point on the profile curve. + >= 0: index of the profile curve with domain containing + this paramter. When the profile_parameter corresponds + to the end of one profile and the beginning of the next + profile, the index of the next profile is returned. + */ + int ProfileIndex( double profile_parameter ) const; + + + /* + Returns: + If m_profile_count >= 2 and m_profile is an ON_PolyCurve + with m_profile_count segments defining outer and inner + profiles, a pointer to the polycurve is returned. + Otherwise null is returned. + */ + const ON_PolyCurve* PolyProfile() const; + + /* + Description: + Get a list of the 2d profile curves. + Returns: + Number of curves appended to the list. + */ + int GetProfileCurves( ON_SimpleArray& profile_curves ) const; + + + /* + Description: + Get the parameters where a profile curve has kinks. + Parameters: + profile_index - [in] + profile_kink_parameters - [out] + parameters at internal kinks are appended to this array. + Returns: + Number of parameters appended to profile_kink_parameters[] + Remarks: + This function is used when making the brep form that has + smooth faces. + */ + int GetProfileKinkParameters( int profile_index, ON_SimpleArray& profile_kink_parameters ) const; + int GetProfileKinkParameters( int profile_index, ON_SimpleArray* profile_kink_parameters ) const; + + /* + Parameters: + profile_index - [in] + Returns: + True if the profile has at least one kink. + */ + bool ProfileIsKinked( int profile_index ) const; + + /* + Description: + Test a polycurve to determine if it meets the necessary + conditions to be used as a multi-segment profile in a extrusion. + Returns: + True if the returned polycurve can be used a a multi-segment + profile in a extrusion. + */ + static bool IsValidPolyCurveProfile( const ON_PolyCurve& polycurve, ON_TextLog* text_log = 0 ); + + /* + Description: + If possible, modify a polycurve so it meets the necessary conditions + to be used as a multi-segment profile in a extrusion. + Returns: + True if the returned polycurve can be used a a multi-segment + profile in a extrusion. + */ + static bool CleanupPolyCurveProfile( ON_PolyCurve& polycurve ); + + // path definition: + // The line m_path must have length > m_path_length_min. + // The interval m_t must statisfy 0 <= m_t[0] < m_t[1] <= 1. + // The extrusion starts at m_path.PointAt(m_t[0]) and ends + // at m_path.PointAt(m_t[1]). + // The "up" direction m_up is a unit vector that must + // be perpendicular to m_path.Tangent(). + ON_Line m_path; + ON_Interval m_t; + ON_3dVector m_up; + + // profile information: + // In general, use SetOuterProfile() and AddInnerProfile() + // to set m_profile_count and m_profile. If you are + // a glutton for punishment, then you might be interested + // in the following. + // The profile curves must be in the x-y plane. + // The profile's "y" axis corresponds to m_up. + // The point (0,0) is extruded along the m_path line. + // If m_profile_count = 1, then m_profile can be any + // type of continous curve. If m_profile_count > 1, + // then m_profile must be an ON_PolyCurve with + // m_profile_count segments, the domain of each segment + // must exactly match the polycurve's segment domain, + // every segment must be continuous and closed, + // the first segement curve must have counter-clockwise + // orientation, and the rest must have clockwise + // orientations. + int m_profile_count; + ON_Curve* m_profile; + + // capped end information: + // If the profile is closed, then m_bCap[] determines + // if the ends are capped. + bool m_bCap[2]; + + // mitered end information: + // The normals m_N[] are with respect to the xy plane. + // A normal parallel to the z axis has no mitering. + // If m_bHaveN[i] is true, then m_N[i] must be a 3d unit + // vector with m_N[i].z > m_Nz_tol; If m_bHaveN[i] + // is false, then m_N[i] is ignored. The normal m_N[0] + // defines the start miter plane and m_N[1] defines the + // end miter plane. + bool m_bHaveN[2]; + ON_3dVector m_N[2]; + + // Surface parameterization information + ON_Interval m_path_domain; + bool m_bTransposed; // false: (s,t) = (profile,path) + + // The z coordinates of miter plane normals must be + // greater than m_Nz_tol + static const double m_Nz_min; // 1/64; + + // The length of the m_path line must be greater than + // m_path_length_min + static const double m_path_length_min; // ON_ZERO_TOLERANCE; + + // Cached meshes used for rendering, analysis, ... + mutable ON_MeshCache m_mesh_cache = ON_MeshCache::Empty; + + /* + Description: + Get an ON_Exrusion form of a cylinder. + Parameters: + cylinder - [in] cylinder.IsFinite() must be true + bCapBottom - [in] if true, the end at cylinder.m_height[0] will be capped + bCapTop - [in] if true, the end at cylinder.m_height[1] will be capped + extrusion - [in] + If the input extrusion pointer is null, one will be allocated on the heap + and it is the caller's responsibility to delte it at an appropriate time. + If the input pointer is not null, this extrusion will be used and the same + pointer will be returned, provided the input is valid. + Returns: + If the input is valid, a pointer to an ON_Exrusion form of the cylinder. + If the input is not valid, then null, even when the input extrusion + object is not null. + Example: + + ON_Cylinder cylinder = ...; + bool bCapBottom = true; + bool bCapTop = true; + ON_Extrusion extrusion; + if ( 0 == ON_Extrusion::Cylinder(cylinder,bCapBottom,bCapTop,&extrusion) ) + { + // input is not valid - nothing set + ... + } + else + { + // extrusion = cylinder + ... + } + */ + static ON_Extrusion* Cylinder( + const ON_Cylinder& cylinder, + bool bCapBottom, + bool bCapTop, + ON_Extrusion* extrusion = 0 + ); + + /* + Description: + Get an ON_Exrusion form of a pipe. + Parameters: + cylinder - [in] cylinder.IsFinite() must be true + The cylinder can be either the inner or outer wall of the pipe. + other_radius - [in] ( != cylinder.Radius() ) + If cylinder.Radius() < other_radius, then the cylinder will be + the inside of the pipe. If cylinder.Radius() > other_radius, then + the cylinder will be the outside of the pipe. + bCapBottom - [in] if true, the end at cylinder.m_height[0] will be capped + bCapTop - [in] if true, the end at cylinder.m_height[1] will be capped + extrusion - [in] + If the input extrusion pointer is null, one will be allocated on the heap + and it is the caller's responsibility to delte it at an appropriate time. + If the input pointer is not null, this extrusion will be used and the same + pointer will be returned, provided the input is valid. + Returns: + If the input is valid, a pointer to an ON_Exrusion form of the pipe. + If the input is not valid, then null, even when the input extrusion + object is not null. + Example: + + ON_Cylinder cylinder = ...; + double other_radius = cylinder.Radius()+1.0; + bool bCapBottom = true; + bool bCapTop = true; + ON_Extrusion extrusion; + if ( 0 == ON_Extrusion::Pipe(cylinder,other_radius,bCapBottom,bCapTop,&extrusion) ) + { + // input is not valid - nothing set + ... + } + else + { + // extrusion = pipe + ... + } + */ + static ON_Extrusion* Pipe( + const ON_Cylinder& cylinder, + double other_radius, + bool bCapBottom, + bool bCapTop, + ON_Extrusion* extrusion = 0 + ); + + /* + Description: + Create an ON_Exrusion from a 3d curve, a plane and a height. + Parameters: + curve - [in] + A continuous 3d curve. + plane - [in] + If plane is null, then the plane returned by curve.IsPlanar() is used. + The 3d curve is projected to this plane and the result is passed to + ON_Extrusion::SetOuterProfile(). + height - [in] + If the height > 0, the bottom of the extrusion will be in plane and + the top will be height units above the plane. + If the height < 0, the top of the extrusion will be in plane and + the bottom will be height units below the plane. + bCap - [in] + If the curve is closed and bCap is true, then the resulting extrusion + is capped. + extrusion - [in] + If the input extrusion pointer is null, one will be allocated on the heap + and it is the caller's responsibility to delte it at an appropriate time. + If the input pointer is not null, this extrusion will be used and the same + pointer will be returned, provided the input is valid. + Returns: + If the input is valid, a pointer to an ON_Exrusion form of the pipe. + If the input is not valid, then null, even when the input extrusion + object is not null. + */ + static ON_Extrusion* CreateFrom3dCurve( + const ON_Curve& curve, + const ON_Plane* plane, + double height, + bool bCap, + ON_Extrusion* extrusion = 0 + ); + +}; + + +#endif + diff --git a/opennurbs/Include/opennurbs_bezier.h b/opennurbs/Include/opennurbs_bezier.h new file mode 100644 index 0000000..2f68499 --- /dev/null +++ b/opennurbs/Include/opennurbs_bezier.h @@ -0,0 +1,1973 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_BEZIER_INC_) +#define OPENNURBS_BEZIER_INC_ + +class ON_PolynomialCurve; +class ON_PolynomialSurface; +class ON_BezierCurve; +class ON_BezierSurface; +class ON_TextLog; +class ON_NurbsCurve; +class ON_NurbsSurface; +class ON_X_EVENT; + +class ON_CLASS ON_PolynomialCurve +{ +public: + ON_PolynomialCurve(); + + // Description: + // See ON_PolynomialCurve::Create. + // Parameters: + // dim - [in] dimension of the curve + // bIsRational - [in] true if rational + // order - [in] (>=2) order = degree+1 + ON_PolynomialCurve( + int dim, + bool bIsRational, + int order + ); + + ~ON_PolynomialCurve(); + + ON_PolynomialCurve(const ON_PolynomialCurve&); + + ON_PolynomialCurve(const ON_BezierCurve&); + + ON_PolynomialCurve& operator=(const ON_PolynomialCurve&); + + ON_PolynomialCurve& operator=(const ON_BezierCurve&); + + // Description: + // Initializes fields and allocates the m_cv array. + // Parameters: + // dim - [in] dimension of the curve + // bIsRational - [in] true if rational + // order - [in] (>=2) order = degree+1 + bool Create( + int dim, + bool bIsRational, + int order + ); + + // Description: + // Deallocates the m_cv array and sets fields to zero. + void Destroy(); + + // Description: + // Evaluate a polynomial curve. + // Parameters: + // t - [in] evaluation parameter ( usually in Domain() ). + // der_count - [in] (>=0) number of derivatives to evaluate + // v_stride - [in] (>=Dimension()) stride to use for the v[] array + // v - [out] array of length (der_count+1)*v_stride + // curve(t) is returned in (v[0],...,v[m_dim-1]), + // curve'(t) is retuned in (v[v_stride],...,v[v_stride+m_dim-1]), + // curve"(t) is retuned in (v[2*v_stride],...,v[2*v_stride+m_dim-1]), + // etc. + // Returns: + // false if unable to evaluate. + bool Evaluate( + double t, + int der_count, + int v_stride, + double* v + ) const; + + // dimension of polynomial curve (1,2, or 3) + int m_dim; + + // 1 if polynomial curve is rational, 0 if polynomial curve is not rational + int m_is_rat; + + // order (=degree+1) of polynomial + int m_order; + + // coefficients ( m_cv.Count() = order of monomial ) + ON_4dPointArray m_cv; + + // domain of polynomial + ON_Interval m_domain; +}; + +class ON_CLASS ON_PolynomialSurface +{ +public: + ON_PolynomialSurface(); + ON_PolynomialSurface( + int, // dim, + bool, // true if rational + int, // "u" order + int // "v" order + ); + ~ON_PolynomialSurface(); + ON_PolynomialSurface(const ON_PolynomialSurface&); + ON_PolynomialSurface(const ON_BezierSurface&); + ON_PolynomialSurface& operator=(const ON_PolynomialSurface&); + ON_PolynomialSurface& operator=(const ON_BezierSurface&); + + bool Create( + int, // dim, + bool, // true if rational + int, // "u" order + int // "v" order + ); + void Destroy(); + + bool Evaluate( // returns false if unable to evaluate + double s, + double t, // evaluation parameter + int der_count, // number of derivatives (>=0) + int v_stride, // array stride (>=Dimension()) + double* v // array of length stride*(ndir+1)*(ndir+2)/2 + ) const; + + int m_dim; // 1,2, or 3 + int m_is_rat; // 1 if rational, 0 if not rational + int m_order[2]; + ON_4dPointArray m_cv; // coefficients ( m_C.Length() = m_order[0]*m_order[1] + // coefficient of s^m*t^n = m_cv[m_order[1]*m+n] + ON_Interval m_domain[2]; +}; + +class ON_CLASS ON_BezierCurve +{ +public: + + ON_BezierCurve(); + + // Description: + // Creates a bezier with cv memory allocated. + // Parameters: + // dim - [in] (>0) dimension of bezier curve + // bIsRational - [in] true for a rational bezier + // order - [in] (>=2) order (=degree+1) of bezier curve + ON_BezierCurve( + int dim, + bool bIsRational, + int order + ); + + ~ON_BezierCurve(); + ON_BezierCurve(const ON_BezierCurve&); + ON_BezierCurve(const ON_PolynomialCurve&); + ON_BezierCurve(const ON_2dPointArray&); // sets control points + ON_BezierCurve(const ON_3dPointArray&); // sets control points + ON_BezierCurve(const ON_4dPointArray&); // sets control points + ON_BezierCurve& operator=(const ON_BezierCurve&); + ON_BezierCurve& operator=(const ON_PolynomialCurve&); + + + ON_BezierCurve& operator=(const ON_2dPointArray&); // sets control points + ON_BezierCurve& operator=(const ON_3dPointArray&); // sets control points + ON_BezierCurve& operator=(const ON_4dPointArray&); // sets control points + + bool IsValid() const; + + void Dump( ON_TextLog& ) const; // for debugging + + // Returns: + // Dimension of bezier. + int Dimension() const; + + // Description: + // Creates a bezier with cv memory allocated. + // Parameters: + // dim - [in] (>0) dimension of bezier curve + // bIsRational - [in] true for a rational bezier + // order - [in] (>=2) order (=degree+1) of bezier curve + // Returns: + // true if successful. + bool Create( + int dim, + bool bIsRational, + int order + ); + + // Description: + // Deallocates m_cv memory. + void Destroy(); + + void EmergencyDestroy(); // call if memory used by ON_NurbsCurve becomes invalid + + // Description: + // Loft a bezier curve through a list of points. + // Parameters: + // points - [in] an array of 2 or more points to interpolate + // Returns: + // true if successful + // Remarks: + // The result has order = points.Count() and the loft uses the + // uniform parameterizaton curve( i/(points.Count()-1) ) = points[i]. + bool Loft( + const ON_3dPointArray& points + ); + + // Description: + // Loft a bezier curve through a list of points. + // Parameters: + // pt_dim - [in] dimension of points to interpolate + // pt_count - [in] number of points (>=2) + // pt_stride - [in] (>=pt_dim) pt[] array stride + // pt - [in] array of points + // t_stride - [in] (>=1) t[] array stride + // t - [in] strictly increasing array of interpolation parameters + // Returns: + // true if successful + // Remarks: + // The result has order = points.Count() and the loft uses the + // parameterizaton curve( t[i] ) = points[i]. + bool Loft( + int pt_dim, + int pt_count, + int pt_stride, + const double* pt, + int t_stride, + const double* t + ); + + // Description: + // Gets bounding box. + // Parameters: + // box_min - [out] minimum corner of axis aligned bounding box + // The box_min[] array must have size m_dim. + // box_max - [out] maximum corner of axis aligned bounding box + // The box_max[] array must have size m_dim. + // bGrowBox - [in] if true, input box_min/box_max must be set + // to valid bounding box corners and this box is enlarged to + // be the union of the input box and the bezier's bounding + // box. + // Returns: + // true if successful. + bool GetBBox( // returns true if successful + double* box_min, + double* box_max, + bool bGrowBox = false + ) const; + + // Description: + // Gets bounding box. + // Parameters: + // bbox - [out] axis aligned bounding box returned here. + // bGrowBox - [in] if true, input bbox must be a valid + // bounding box and this box is enlarged to + // be the union of the input box and the + // bezier's bounding box. + // Returns: + // true if successful. + bool GetBoundingBox( + ON_BoundingBox& bbox, + int bGrowBox = false + ) const; + + // Description: + // Gets bounding box. + // Returns: + // Axis aligned bounding box. + ON_BoundingBox BoundingBox() const; + + /* + Description: + Get tight bounding box of the bezier. + Parameters: + tight_bbox - [in/out] tight bounding box + bGrowBox -[in] (default=false) + If true and the input tight_bbox is valid, then returned + tight_bbox is the union of the input tight_bbox and the + tight bounding box of the bezier curve. + xform -[in] (default=nullptr) + If not nullptr, the tight bounding box of the transformed + bezier is calculated. The bezier curve is not modified. + Returns: + True if the returned tight_bbox is set to a valid + bounding box. + */ + bool GetTightBoundingBox( + ON_BoundingBox& tight_bbox, + bool bGrowBox = false, + const ON_Xform* xform = nullptr + ) const; + + // Description: + // Transform the bezier. + // Parameters: + // xform - [in] transformation to apply to bezier + // Returns: + // true if successful. false if bezier is invalid + // and cannot be transformed. + bool Transform( + const ON_Xform& xform + ); + + + // Description: + // Rotates the bezier curve about the specified axis. A positive + // rotation angle results in a counter-clockwise rotation + // about the axis (right hand rule). + // Parameters: + // sin_angle - [in] sine of rotation angle + // cos_angle - [in] sine of rotation angle + // rotation_axis - [in] direction of the axis of rotation + // rotation_center - [in] point on the axis of rotation + // Returns: + // true if bezier curve successfully rotated + // Remarks: + // Uses ON_BezierCurve::Transform() function to calculate the result. + bool Rotate( + double sin_angle, + double cos_angle, + const ON_3dVector& rotation_axis, + const ON_3dPoint& rotation_center + ); + + // Description: + // Rotates the bezier curve about the specified axis. A positive + // rotation angle results in a counter-clockwise rotation + // about the axis (right hand rule). + // Parameters: + // rotation_angle - [in] angle of rotation in radians + // rotation_axis - [in] direction of the axis of rotation + // rotation_center - [in] point on the axis of rotation + // Returns: + // true if bezier curve successfully rotated + // Remarks: + // Uses ON_BezierCurve::Transform() function to calculate the result. + bool Rotate( + double rotation_angle, + const ON_3dVector& rotation_axis, + const ON_3dPoint& rotation_center + ); + + // Description: + // Translates the bezier curve along the specified vector. + // Parameters: + // translation_vector - [in] translation vector + // Returns: + // true if bezier curve successfully translated + // Remarks: + // Uses ON_BezierCurve::Transform() function to calculate the result. + bool Translate( + const ON_3dVector& translation_vector + ); + + // Description: + // Scales the bezier curve by the specified facotor. The scale is + // centered at the origin. + // Parameters: + // scale_factor - [in] scale factor + // Returns: + // true if bezier curve successfully scaled + // Remarks: + // Uses ON_BezierCurve::Transform() function to calculate the result. + bool Scale( + double scale_factor + ); + + // Returns: + // Domain of bezier (always [0,1]). + ON_Interval Domain() const; + + // Description: + // Reverses bezier by reversing the order + // of the control points. + bool Reverse(); + + // Description: + // Evaluate point at a parameter. + // Parameters: + // t - [in] evaluation parameter + // Returns: + // Point (location of curve at the parameter t). + ON_3dPoint PointAt( + double t + ) const; + + // Description: + // Evaluate first derivative at a parameter. + // Parameters: + // t - [in] evaluation parameter + // Returns: + // First derivative of the curve at the parameter t. + // Remarks: + // No error handling. + // See Also: + // ON_Curve::Ev1Der + ON_3dVector DerivativeAt( + double t + ) const; + + // Description: + // Evaluate unit tangent vector at a parameter. + // Parameters: + // t - [in] evaluation parameter + // Returns: + // Unit tangent vector of the curve at the parameter t. + // Remarks: + // No error handling. + // See Also: + // ON_Curve::EvTangent + ON_3dVector TangentAt( + double t + ) const; + + // Description: + // Evaluate the curvature vector at a parameter. + // Parameters: + // t - [in] evaluation parameter + // Returns: + // curvature vector of the curve at the parameter t. + // Remarks: + // No error handling. + // See Also: + // ON_Curve::EvCurvature + ON_3dVector CurvatureAt( + double t + ) const; + + // Description: + // Evaluate point at a parameter with error checking. + // Parameters: + // t - [in] evaluation parameter + // point - [out] value of curve at t + // Returns: + // false if unable to evaluate. + bool EvPoint( + double t, + ON_3dPoint& point + ) const; + + // Description: + // Evaluate first derivative at a parameter with error checking. + // Parameters: + // t - [in] evaluation parameter + // point - [out] value of curve at t + // first_derivative - [out] value of first derivative at t + // Returns: + // false if unable to evaluate. + bool Ev1Der( + double t, + ON_3dPoint& point, + ON_3dVector& first_derivative + ) const; + + // Description: + // Evaluate second derivative at a parameter with error checking. + // Parameters: + // t - [in] evaluation parameter + // point - [out] value of curve at t + // first_derivative - [out] value of first derivative at t + // second_derivative - [out] value of second derivative at t + // Returns: + // false if unable to evaluate. + bool Ev2Der( + double t, + ON_3dPoint& point, + ON_3dVector& first_derivative, + ON_3dVector& second_derivative + ) const; + + /* + Description: + Evaluate unit tangent at a parameter with error checking. + Parameters: + t - [in] evaluation parameter + point - [out] value of curve at t + tangent - [out] value of unit tangent + Returns: + false if unable to evaluate. + See Also: + ON_Curve::TangentAt + ON_Curve::Ev1Der + */ + bool EvTangent( + double t, + ON_3dPoint& point, + ON_3dVector& tangent + ) const; + + /* + Description: + Evaluate unit tangent and curvature at a parameter with error checking. + Parameters: + t - [in] evaluation parameter + point - [out] value of curve at t + tangent - [out] value of unit tangent + kappa - [out] value of curvature vector + Returns: + false if unable to evaluate. + */ + bool EvCurvature( + double t, + ON_3dPoint& point, + ON_3dVector& tangent, + ON_3dVector& kappa + ) const; + + // Description: + // Evaluate a bezier. + // Parameters: + // t - [in] evaluation parameter (usually 0 <= t <= 1) + // der_count - [in] (>=0) number of derivatives to evaluate + // v_stride - [in] (>=m_dim) stride to use for the v[] array + // v - [out] array of length (der_count+1)*v_stride + // bez(t) is returned in (v[0],...,v[m_dim-1]), + // bez'(t) is retuned in (v[v_stride],...,v[v_stride+m_dim-1]), + // bez"(t) is retuned in (v[2*v_stride],...,v[2*v_stride+m_dim-1]), + // etc. + // Returns: + // true if successful + bool Evaluate( + double t, + int der_count, + int v_stride, + double* v + ) const; + + // Description: + // Get ON_NurbsCurve form of a bezier. + // Parameters: + // nurbs_curve - [out] NURBS curve form of a bezier. + // The domain is [0,1]. + // Returns: + // 0 = failure + // 1 = success + int GetNurbForm( + ON_NurbsCurve& nurbs_curve + ) const; + + // Returns: + // true if bezier is rational. + bool IsRational() const; + + // Returns: + // Number of doubles per control vertex. + // (= IsRational() ? Dim()+1 : Dim()) + int CVSize() const; + + // Returns: + // Number of control vertices in the bezier. + // This is always the same as the order of the bezier. + int CVCount() const; + + // Returns: + // Order of the bezier. (order=degree+1) + int Order() const; // order = degree + 1 + + // Returns: + // Degree of the bezier. (degree=order-1) + int Degree() const; + + /* + Description: + Expert user function to get a pointer to control vertex + memory. If you are not an expert user, please use + ON_BezierCurve::GetCV( ON_3dPoint& ) or + ON_BezierCurve::GetCV( ON_4dPoint& ). + Parameters: + cv_index - [in] (0 <= cv_index < m_order) + Returns: + Pointer to control vertex. + Remarks: + If the Bezier curve is rational, the format of the + returned array is a homogeneos rational point with + length m_dim+1. If the Bezier curve is not rational, + the format of the returned array is a nonrational + euclidean point with length m_dim. + See Also + ON_BezierCurve::CVStyle + ON_BezierCurve::GetCV + ON_BezierCurve::Weight + */ + double* CV( + int cv_index + ) const; + + /* + Parameters: + cv_index - [in] + zero based control point index + Returns: + Control point as an ON_4dPoint. + Remarks: + If cv_index or the bezier is not valid, then ON_4dPoint::Nan is returned. + If dim < 3, unused coordinates are zero. + If dim >= 4, the first three coordinates are returned. + If is_rat is false, the weight is 1. + */ + const ON_4dPoint ControlPoint( + int cv_index + ) const; + + /* + Description: + Returns the style of control vertices in the m_cv array. + Returns: + @untitled table + ON::not_rational m_is_rat is false + ON::homogeneous_rational m_is_rat is true + */ + ON::point_style CVStyle() const; + + // Parameters: + // cv_index - [in] control vertex index (0<=i 0). + If c != 1, then the returned bezier will be rational. + Returns: + true if successful. + Remarks: + The reparameterization is performed by composing the input Bezier with + the function lambda: [0,1] -> [0,1] given by + + t -> c*t / ( (c-1)*t + 1 ) + + Note that lambda(0) = 0, lambda(1) = 1, lambda'(t) > 0, + lambda'(0) = c and lambda'(1) = 1/c. + + If the input Bezier has control vertices {B_0, ..., B_d}, then the + output Bezier has control vertices + + (B_0, ... c^i * B_i, ..., c^d * B_d). + + To derive this formula, simply compute the i-th Bernstein polynomial + composed with lambda(). + + The inverse parameterization is given by 1/c. That is, the + cumulative effect of the two calls + + Reparameterize(c) + Reparameterize(1.0/c) + + is to leave the bezier unchanged. + See Also: + ON_Bezier::ScaleConrolPoints + */ + bool Reparameterize( + double c + ); + + // misspelled function name is obsolete + ON_DEPRECATED_MSG("misspelled - use Reparameterize") + bool Reparametrize(double); + + /* + Description: + Scale a rational Bezier's control vertices to set a weight to a + specified value. + Parameters: + i - [in] (0 <= i < order) + w - [in] w != 0.0 + Returns: + True if successful. The i-th control vertex will have weight w. + Remarks: + Each control point is multiplied by w/w0, where w0 is the + input value of Weight(i). + See Also: + ON_Bezier::Reparameterize + ON_Bezier::ChangeWeights + */ + bool ScaleConrolPoints( + int i, + double w + ); + + /* + Description: + Use a combination of scaling and reparameterization to set two + rational Bezier weights to specified values. + Parameters: + i0 - [in] control point index (0 <= i0 < order, i0 != i1) + w0 - [in] Desired weight for i0-th control point + i1 - [in] control point index (0 <= i1 < order, i0 != i1) + w1 - [in] Desired weight for i1-th control point + Returns: + True if successful. The returned bezier has the same locus but + probably has a different parameterization. + Remarks: + The i0-th cv will have weight w0 and the i1-rst cv will have + weight w1. If v0 and v1 are the cv's input weights, + then v0, v1, w0 and w1 must all be nonzero, and w0*v0 + and w1*v1 must have the same sign. + + The equations + + s * r^i0 = w0/v0 + s * r^i1 = w1/v1 + + determine the scaling and reparameterization necessary to + change v0,v1 to w0,w1. + + If the input Bezier has control vertices + + (B_0, ..., B_d), + + then the output Bezier has control vertices + + (s*B_0, ... s*r^i * B_i, ..., s*r^d * B_d). + See Also: + ON_Bezier::Reparameterize + ON_Bezier::ScaleConrolPoints + */ + bool ChangeWeights( + int i0, + double w0, + int i1, + double w1 + ); + + + + + ///////////////////////////////////////////////////////////////// + // Implementation +public: + // NOTE: These members are left "public" so that expert users may efficiently + // create bezier curves using the default constructor and borrow the + // knot and CV arrays from their native NURBS representation. + // No technical support will be provided for users who access these + // members directly. If you can't get your stuff to work, then use + // the constructor with the arguments and the SetKnot() and SetCV() + // functions to fill in the arrays. + + + // dimension of bezier (>=1) + int m_dim; + + // 1 if bezier is rational, 0 if bezier is not rational + int m_is_rat; + + // order = degree+1 + int m_order; + + // Number of doubles per cv ( >= ((m_is_rat)?m_dim+1:m_dim) ) + int m_cv_stride; + + // The i-th cv begins at cv[i*m_cv_stride]. + double* m_cv; + + // Number of doubles in m_cv array. If m_cv_capacity is zero + // and m_cv is not nullptr, an expert user is managing the m_cv + // memory. ~ON_BezierCurve will not deallocate m_cv unless + // m_cv_capacity is greater than zero. + int m_cv_capacity; + +#if 8 == ON_SIZEOF_POINTER + // pad to a multiple of 8 bytes so custom allocators + // will keep m_cv aligned and tail-padding reuse will + // not be an issue. + int m_reserved_ON_BezierCurve; +#endif +}; + + +class ON_CLASS ON_BezierSurface +{ +public: + ON_BezierSurface(); + ON_BezierSurface( + int dim, + bool is_rat, + int order0, + int order1 + ); + + ~ON_BezierSurface(); + ON_BezierSurface(const ON_BezierSurface&); + ON_BezierSurface(const ON_PolynomialSurface&); + ON_BezierSurface& operator=(const ON_BezierSurface&); + ON_BezierSurface& operator=(const ON_PolynomialSurface&); + + bool IsValid() const; + void Dump( ON_TextLog& ) const; // for debugging + int Dimension() const; + + bool Create( + int dim, + bool is_rat, + int order0, + int order1 + ); + + void Destroy(); + void EmergencyDestroy(); // call if memory used by ON_NurbsCurve becomes invalid + + /* + Description: + Loft a bezier surface through a list of bezier curves. + Parameters: + curve_list - [in] list of curves that have the same degree. + Returns: + True if successful. + */ + bool Loft( const ON_ClassArray& curve_list ); + + /* + Description: + Loft a bezier surface through a list of bezier curves. + Parameters: + curve_count - [in] number of curves in curve_list + curve_list - [in] array of pointers to curves that have the same degree. + Returns: + True if successful. + */ + bool Loft( + int count, + const ON_BezierCurve* const* curve_list + ); + + bool GetBBox( // returns true if successful + double*, // minimum + double*, // maximum + bool bGrowBox = false // true means grow box + ) const; + + bool GetBoundingBox( + ON_BoundingBox& bbox, + int bGrowBox + ) const; + + ON_BoundingBox BoundingBox() const; + + bool Transform( + const ON_Xform& + ); + + + // Description: + // Rotates the bezier surface about the specified axis. A positive + // rotation angle results in a counter-clockwise rotation + // about the axis (right hand rule). + // Parameters: + // sin_angle - [in] sine of rotation angle + // cos_angle - [in] sine of rotation angle + // rotation_axis - [in] direction of the axis of rotation + // rotation_center - [in] point on the axis of rotation + // Returns: + // true if bezier surface successfully rotated + // Remarks: + // Uses ON_BezierSurface::Transform() function to calculate the result. + bool Rotate( + double sin_angle, + double cos_angle, + const ON_3dVector& rotation_axis, + const ON_3dPoint& rotation_center + ); + + // Description: + // Rotates the bezier surface about the specified axis. A positive + // rotation angle results in a counter-clockwise rotation + // about the axis (right hand rule). + // Parameters: + // rotation_angle - [in] angle of rotation in radians + // rotation_axis - [in] direction of the axis of rotation + // rotation_center - [in] point on the axis of rotation + // Returns: + // true if bezier surface successfully rotated + // Remarks: + // Uses ON_BezierSurface::Transform() function to calculate the result. + bool Rotate( + double rotation_angle, + const ON_3dVector& rotation_axis, + const ON_3dPoint& rotation_center + ); + + // Description: + // Translates the bezier surface along the specified vector. + // Parameters: + // translation_vector - [in] translation vector + // Returns: + // true if bezier surface successfully translated + // Remarks: + // Uses ON_BezierSurface::Transform() function to calculate the result. + bool Translate( + const ON_3dVector& translation_vector + ); + + // Description: + // Scales the bezier surface by the specified facotor. The scale is + // centered at the origin. + // Parameters: + // scale_factor - [in] scale factor + // Returns: + // true if bezier surface successfully scaled + // Remarks: + // Uses ON_BezierSurface::Transform() function to calculate the result. + bool Scale( + double scale_factor + ); + + ON_Interval Domain( + int // 0 = "u" domain, 1 = "v" domain + ) const; + + bool Reverse( int ); // reverse parameterizatrion + // Domain changes from [a,b] to [-b,-a] + + bool Transpose(); // transpose surface parameterization (swap "s" and "t") + + bool Evaluate( // returns false if unable to evaluate + double, double, // evaluation parameter + int, // number of derivatives (>=0) + int, // array stride (>=Dimension()) + double* // array of length stride*(ndir+1)*(ndir+2)/2 + ) const; + + ON_3dPoint PointAt(double s, double t) const; + + /* + Returns: + 0 = failure. + 1 = success. + */ + int GetNurbForm( ON_NurbsSurface& ) const; + + bool IsRational() const; // true if NURBS curve is rational + + int CVSize() const; // number of doubles per control vertex + // = IsRational() ? Dim()+1 : Dim() + + int Order( // order = degree + 1 + int // dir + ) const; + + int Degree( // degree = order - 1 + int // dir + ) const; + + /* + Description: + Expert user function to get a pointer to control vertex + memory. If you are not an expert user, please use + ON_BezierSurface::GetCV( ON_3dPoint& ) or + ON_BezierSurface::GetCV( ON_4dPoint& ). + Parameters: + cv_index0 - [in] (0 <= cv_index0 < m_order[0]) + cv_index1 - [in] (0 <= cv_index1 < m_order[1]) + Returns: + Pointer to control vertex. + Remarks: + If the Bezier surface is rational, the format of the + returned array is a homogeneos rational point with + length m_dim+1. If the Bezier surface is not rational, + the format of the returned array is a nonrational + euclidean point with length m_dim. + See Also + ON_BezierSurface::CVStyle + ON_BezierSurface::GetCV + ON_BezierSurface::Weight + */ + double* CV( + int cv_index0, + int cv_index1 + ) const; + + /* + Description: + Returns the style of control vertices in the m_cv array. + Returns: + @untitled table + ON::not_rational m_is_rat is false + ON::homogeneous_rational m_is_rat is true + */ + ON::point_style CVStyle() const; + + double Weight( // get value of control vertex weight + int,int // CV index ( >= 0 and < CVCount() ) + ) const; + + bool SetWeight( // set value of control vertex weight + int,int, // CV index ( >= 0 and < CVCount() ) + double + ); + + bool SetCV( // set a single control vertex + int,int, // CV index ( >= 0 and < CVCount() ) + ON::point_style, // style of input point + const double* // value of control vertex + ); + + bool SetCV( // set a single control vertex + int,int, // CV index ( >= 0 and < CVCount() ) + const ON_3dPoint& // value of control vertex + // If NURBS is rational, weight + // will be set to 1. + ); + + bool SetCV( // set a single control vertex + int,int, // CV index ( >= 0 and < CVCount() ) + const ON_4dPoint& // value of control vertex + // If NURBS is not rational, euclidean + // location of homogeneous point will + // be used. + ); + + bool GetCV( // get a single control vertex + int,int, // CV index ( >= 0 and < CVCount() ) + ON::point_style, // style to use for output point + double* // array of length >= CVSize() + ) const; + + bool GetCV( // get a single control vertex + int,int, // CV index ( >= 0 and < CVCount() ) + ON_3dPoint& // gets euclidean cv when NURBS is rational + ) const; + + bool GetCV( // get a single control vertex + int,int, // CV index ( >= 0 and < CVCount() ) + ON_4dPoint& // gets homogeneous cv + ) const; + + bool ZeroCVs(); // zeros control vertices and, if rational, sets weights to 1 + + bool MakeRational(); + + bool MakeNonRational(); + + bool Split( + int, // 0 split at "u"=t, 1= split at "v"=t + double, // t = splitting parameter must 0 < t < 1 + ON_BezierSurface&, // west/south side returned here (can pass *this) + ON_BezierSurface& // east/north side returned here (can pass *this) + ) const; + + bool Trim( + int dir, + const ON_Interval& domain + ); + + // returns the isocurve. + ON_BezierCurve* IsoCurve( + int dir, // 0 first parameter varies and second parameter is constant + // e.g., point on IsoCurve(0,c) at t is srf(t,c) + // 1 first parameter is constant and second parameter varies + // e.g., point on IsoCurve(1,c) at t is srf(c,t) + double c, // value of constant parameter + ON_BezierCurve* iso=nullptr // When nullptr result is constructed on the heap. + ) const; + + bool IsSingular( // true if surface side is collapsed to a point + int // side of parameter space to test + // 0 = south, 1 = east, 2 = north, 3 = west + ) const; + + + ///////////////////////////////////////////////////////////////// + // Tools for managing CV and knot memory + bool ReserveCVCapacity( + int // number of doubles to reserve + ); + + + /* + Description: + Get an estimate of the size of the rectangle that would + be created if the 3d surface where flattened into a rectangle. + Parameters: + width - [out] (corresponds to the first surface parameter) + height - [out] (corresponds to the first surface parameter) + Returns: + true if successful. + */ + bool GetSurfaceSize(double* width, double* height) const; + + ///////////////////////////////////////////////////////////////// + // Implementation +public: + // NOTE: These members are left "public" so that expert users may efficiently + // create bezier curves using the default constructor and borrow the + // knot and CV arrays from their native NURBS representation. + // No technical support will be provided for users who access these + // members directly. If you can't get your stuff to work, then use + // the constructor with the arguments and the SetKnot() and SetCV() + // functions to fill in the arrays. + + + int m_dim; // >= 1 + int m_is_rat; // 0 = no, 1 = yes + int m_order[2]; // order = degree+1 >= 2 + int m_cv_stride[2]; + double* m_cv; + int m_cv_capacity; // if 0, then destructor does not free m_cv +#if 8 == ON_SIZEOF_POINTER + // pad to a multiple of 8 bytes so custom allocators + // will keep m_cv aligned and tail-padding reuse will + // not be an issue. + int m_reserved_ON_BezierSurface; +#endif +}; + + + + +class ON_CLASS ON_BezierCage +{ +public: + ON_BezierCage(); + + ON_BezierCage( + int dim, + bool is_rat, + int order0, + int order1, + int order2 + ); + + + /* + Description: + Construct a bezier volume that maps the unit cube + to a bounding box. + Parameters: + bbox - [in] target bounding box + order0 - [in] + order1 - [in] + order2 - [in] + */ + ON_BezierCage( + const ON_BoundingBox& bbox, + int order0, + int order1, + int order2 + ); + + + /* + Description: + Construct a bezier volume that maps the unit cube + to an eight sided box. + Parameters: + box_corners - [in] 8 points that define corners of the + target volume. + + 7______________6 + |\ |\ + | \ | \ + | \ _____________\ + | 4 | 5 + | | | | + | | | | + 3---|----------2 | + \ | \ | + \ |t \ | + s \ | \ | + \0_____________\1 + r + + order0 - [in] + order1 - [in] + order2 - [in] + */ + ON_BezierCage( + const ON_3dPoint* box_corners, + int order0, + int order1, + int order2 + ); + + ~ON_BezierCage(); + + ON_BezierCage(const ON_BezierCage& src); + + ON_BezierCage& operator=(const ON_BezierCage& src); + + + /* + Description: + Tests class to make sure members are correctly initialized. + Returns: + True if the orders are all >= 2, dimension is positive, + and the rest of the members have settings that are + valid for the orders and dimension. + */ + bool IsValid() const; + + void Dump( ON_TextLog& text_log) const; + + + /* + Description: + The dimension of the image of the bazier volume map. + This is generally three, but can be any positive + integer. + Returns: + Dimesion of the image space. + */ + int Dimension() const; + + + /* + Description: + Creates a bezier volume with specified orders. + Parameters: + dim - [in] + is_rat - [in] + order0 - [in] + order1 - [in] + order2 - [in] + Returns: + True if input was valid and creation succeded. + */ + bool Create( + int dim, + bool is_rat, + int order0, + int order1, + int order2 + ); + + /* + Description: + Create a Bezier volume with corners defined by a bounding box. + Parameters: + bbox - [in] target bounding box - the bezier will + map the unit cube onto this bounding box. + order0 - [in] + order1 - [in] + order2 - [in] + */ + bool Create( + const ON_BoundingBox& bbox, + int order0, + int order1, + int order2 + ); + + /* + Description: + Create a bezier volume from a 3d box + Parameters: + box_corners - [in] 8 points that define corners of the volume + + 7______________6 + |\ |\ + | \ | \ + | \ _____________\ + | 4 | 5 + | | | | + | | | | + 3---|----------2 | + \ | \ | + \ |t \ | + s \ | \ | + \0_____________\1 + r + + */ + bool Create( + const ON_3dPoint* box_corners, + int order0, + int order1, + int order2 + ); + + + /* + Description: + Frees the CV array and sets all members to zero. + */ + void Destroy(); + + /* + Description: + Sets all members to zero. Does not free the CV array + even when m_cv is not nullptr. Generally used when the + CVs were allocated from a memory pool that no longer + exists and the free done in ~ON_BezierCage would + cause a crash. + */ + void EmergencyDestroy(); + + + /* + Description: + Reads the definition of this class from an + archive previously saved by ON_BezierVolue::Write. + Parameters: + archive - [in] target archive + Returns: + True if successful. + */ + bool Read(ON_BinaryArchive& archive); + + /* + Description: + Saves the definition of this class in serial binary + form that can be read by ON_BezierVolue::Read. + Parameters: + archive - [in] target archive + Returns: + True if successful. + */ + bool Write(ON_BinaryArchive& archive) const; + + + /* + Description: + Gets the axis aligned bounding box that contains + the bezier's control points. The bezier volume + maps the unit cube into this box. + Parameters: + boxmin - [in] array of Dimension() doubles + boxmax - [in] array of Dimension() doubles + bGrowBox = [in] if true and the input is a valid box + then the input box is grown to + include this object's bounding box. + Returns: + true if successful. + */ + bool GetBBox( + double* boxmin, + double* boxmax, + bool bGrowBox = false + ) const; + + bool Transform( + const ON_Xform& xform + ); + + + // Description: + // Rotates the bezier surface about the specified axis. A positive + // rotation angle results in a counter-clockwise rotation + // about the axis (right hand rule). + // Parameters: + // sin_angle - [in] sine of rotation angle + // cos_angle - [in] sine of rotation angle + // rotation_axis - [in] direction of the axis of rotation + // rotation_center - [in] point on the axis of rotation + // Returns: + // true if bezier surface successfully rotated + // Remarks: + // Uses ON_BezierCage::Transform() function to calculate the result. + bool Rotate( + double sin_angle, + double cos_angle, + const ON_3dVector& rotation_axis, + const ON_3dPoint& rotation_center + ); + + // Description: + // Rotates the bezier surface about the specified axis. A positive + // rotation angle results in a counter-clockwise rotation + // about the axis (right hand rule). + // Parameters: + // rotation_angle - [in] angle of rotation in radians + // rotation_axis - [in] direction of the axis of rotation + // rotation_center - [in] point on the axis of rotation + // Returns: + // true if bezier surface successfully rotated + // Remarks: + // Uses ON_BezierCage::Transform() function to calculate the result. + bool Rotate( + double rotation_angle, + const ON_3dVector& rotation_axis, + const ON_3dPoint& rotation_center + ); + + // Description: + // Translates the bezier surface along the specified vector. + // Parameters: + // translation_vector - [in] translation vector + // Returns: + // true if bezier surface successfully translated + // Remarks: + // Uses ON_BezierCage::Transform() function to calculate the result. + bool Translate( + const ON_3dVector& translation_vector + ); + + // Description: + // Scales the bezier surface by the specified facotor. The scale is + // centered at the origin. + // Parameters: + // scale_factor - [in] scale factor + // Returns: + // true if bezier surface successfully scaled + // Remarks: + // Uses ON_BezierCage::Transform() function to calculate the result. + bool Scale( + double scale_factor + ); + + ON_Interval Domain( + int // 0 = "u" domain, 1 = "v" domain, 2 = "w" domain + ) const; + + // returns false if unable to evaluate + bool Evaluate( + double r, + double s, + double t, + int der_count, + int v_stride, + double* v // array of length stride*(ndir+1)*(ndir+2)/2 + ) const; + + /* + Description: + Evaluates bezer volume map. + Parameters: + rst - [in] + Returns: + Value of the bezier volume map at (r,s,t). + */ + ON_3dPoint PointAt( + double r, + double s, + double t + ) const; + + /* + Description: + Evaluates bezer volume map. + Parameters: + rst - [in] + Returns: + Value of the bezier volume map at (rst.x,rst.y,rst.z). + */ + ON_3dPoint PointAt( + ON_3dPoint rst + ) const; + + bool IsRational() const; // true if NURBS curve is rational + + bool IsSingular( // true if surface side is collapsed to a point + int // side of parameter space to test + // 0 = south, 1 = east, 2 = north, 3 = west + ) const; + + int CVSize() const; // number of doubles per control vertex + // = IsRational() ? Dim()+1 : Dim() + + int Order( // order = degree + 1 + int // dir + ) const; + + int Degree( // degree = order - 1 + int // dir + ) const; + + /* + Description: + Expert user function to get a pointer to control vertex + memory. If you are not an expert user, please use + ON_BezierCage::GetCV( ON_3dPoint& ) or + ON_BezierCage::GetCV( ON_4dPoint& ). + Parameters: + cv_index0 - [in] (0 <= cv_index0 < m_order[0]) + cv_index1 - [in] (0 <= cv_index1 < m_order[1]) + Returns: + Pointer to control vertex. + Remarks: + If the Bezier surface is rational, the format of the + returned array is a homogeneos rational point with + length m_dim+1. If the Bezier surface is not rational, + the format of the returned array is a nonrational + euclidean point with length m_dim. + See Also + ON_BezierCage::CVStyle + ON_BezierCage::GetCV + ON_BezierCage::Weight + */ + double* CV( + int i, + int j, + int k + ) const; + + /* + Description: + Returns the style of control vertices in the m_cv array. + Returns: + @untitled table + ON::not_rational m_is_rat is false + ON::homogeneous_rational m_is_rat is true + */ + ON::point_style CVStyle() const; + + double Weight( // get value of control vertex weight + int i, + int j, + int k + ) const; + + bool SetWeight( // set value of control vertex weight + int i, + int j, + int k, + double w + ); + + bool SetCV( // set a single control vertex + int i, + int j, + int k, + ON::point_style, // style of input point + const double* // value of control vertex + ); + + // set a single control vertex + // If NURBS is rational, weight + // will be set to 1. + bool SetCV( + int i, + int j, + int k, + const ON_3dPoint& point + ); + + // set a single control vertex + // value of control vertex + // If NURBS is not rational, euclidean + // location of homogeneous point will + // be used. + bool SetCV( + int i, + int j, + int k, + const ON_4dPoint& hpoint + ); + + bool GetCV( // get a single control vertex + int i, + int j, + int k, + ON::point_style, // style to use for output point + double* // array of length >= CVSize() + ) const; + + bool GetCV( // get a single control vertex + int i, + int j, + int k, + ON_3dPoint& // gets euclidean cv when NURBS is rational + ) const; + + bool GetCV( // get a single control vertex + int i, + int j, + int k, + ON_4dPoint& // gets homogeneous cv + ) const; + + bool ZeroCVs(); // zeros control vertices and, if rational, sets weights to 1 + + bool MakeRational(); + + bool MakeNonRational(); + + + ///////////////////////////////////////////////////////////////// + // Tools for managing CV and knot memory + + /* + Description: + cv_capacity - [in] number of doubles to reserve + */ + bool ReserveCVCapacity( + int cv_capacity + ); + + ///////////////////////////////////////////////////////////////// + // Implementation +public: + // NOTE: These members are left "public" so that expert users may efficiently + // create bezier curves using the default constructor and borrow the + // knot and CV arrays from their native NURBS representation. + // No technical support will be provided for users who access these + // members directly. If you can't get your stuff to work, then use + // the constructor with the arguments and the SetKnot() and SetCV() + // functions to fill in the arrays. + + + int m_dim; + bool m_is_rat; + int m_order[3]; + int m_cv_stride[3]; + int m_cv_capacity; + double* m_cv; +}; + + +class ON_CLASS ON_BezierCageMorph : public ON_SpaceMorph +{ +public: + ON_BezierCageMorph(); + virtual ~ON_BezierCageMorph(); + + + /* + Description: + Create a Bezier volume. + Parameters: + P0 - [in] + P1 - [in] + P2 - [in] + P3 - [in] + P0,P1,P2,P3 defines a parallepiped in world space. The morph + maps this parallepiped to the (0,1)x(0,1)x(0,1) unit cube + and then applies the BezierCage map. + + + ______________ + |\ |\ + | \ | \ + | \P3____________\ + | | | | + | | | | + | | | | + P2---|---------- | + \ | \ | + \ |z \ | + y \ | \ | + \P0____________P1 + x + + + point_countX - [in] + point_countY - [in] + point_countZ - [in] + Number of control points in the bezier volume map. The + bezier volume in the returned morph is the identity map + which can be modified as needed. + Returns: + True if resulting morph is valid. + See Also: + ON_BezierCage::SetBezierCage + ON_BezierCage::SetXform + */ + bool Create( + ON_3dPoint P0, + ON_3dPoint P1, + ON_3dPoint P2, + ON_3dPoint P3, + int point_countX, + int point_countY, + int point_countZ + ); + + /* + Description: + Set the world to unit cube map. + Parameters: + world2unitcube - [in] + Tranformation matrix that maps world coordinates + to the unit cube (0,1)x(0,1)x(0,1). + Returns + True if current bezier volum and input transformation + matrix are valid. In all cases, the morph's m_xyz2rst + member is set. + See Also: + ON_BezierCage::Create + ON_BezierCage::SetBezierCage + */ + bool SetXform( ON_Xform world2unitcube ); + + /* + Description: + Set the unit cube to world map. + Parameters: + world2unitcube - [in] + Bezier volume map from the unit cube (0,1)x(0,1)x(0,1) + to world space. + Returns + True if current transformation matrix and input + bezier volume are valid. In all cases, the + morph's m_rst2xyz member is set. + See Also: + ON_BezierCage::Create + ON_BezierCage::SetXform + */ + bool SetBezierCage( ON_BezierCage& unitcube2world ); + + const ON_Xform& WorldToUnitCube() const; + const ON_BezierCage& BezierCage() const; + + bool Read(ON_BinaryArchive& archive); + bool Write(ON_BinaryArchive& archive) const; + + /* + Description: + Transforms the morph by transforming the bezier volume map. + Parameters: + xform - [in] + Returns + True if input is valid. + */ + bool Transform(const ON_Xform& xform); + +private: + bool m_bValid; + + // transforms world (x,y,z) coordinate into + // unit cube. + ON_Xform m_xyz2rst; + + // function that maps unit cube into world + ON_BezierCage m_rst2xyz; +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +#endif + +#endif diff --git a/opennurbs/Include/opennurbs_bitmap.h b/opennurbs/Include/opennurbs_bitmap.h new file mode 100644 index 0000000..feaac0a --- /dev/null +++ b/opennurbs/Include/opennurbs_bitmap.h @@ -0,0 +1,524 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +//////////////////////////////////////////////////////////////// +// +// Defines ON_WindowsBITMAPINFO class that is used to provide OS independent +// serialization of Windows device independent bitmaps (BITMAPINFO) used +// to store preview images. +// +//////////////////////////////////////////////////////////////// + +#if !defined(OPENNURBS_BITMAP_INC_) +#define OPENNURBS_BITMAP_INC_ + +class ON_CLASS ON_Bitmap : public ON_ModelComponent +{ + ON_OBJECT_DECLARE(ON_Bitmap); + +public: + ON_Bitmap() ON_NOEXCEPT; + ~ON_Bitmap() = default; + ON_Bitmap(const ON_Bitmap&); + ON_Bitmap& operator=(const ON_Bitmap&) = default; + + static const ON_Bitmap Unset; + + /* + Parameters: + model_component_reference - [in] + none_return_value - [in] + value to return if ON_Layer::Cast(model_component_ref.ModelComponent()) + is nullptr + Returns: + If ON_Layer::Cast(model_component_ref.ModelComponent()) is not nullptr, + that pointer is returned. Otherwise, none_return_value is returned. + */ + static const ON_Bitmap* FromModelComponentRef( + const class ON_ModelComponentReference& model_component_reference, + const ON_Bitmap* none_return_value + ); + + void Dump( + ON_TextLog& + ) const override; + + bool Write( class ON_BinaryArchive& ) const override; + bool Read( class ON_BinaryArchive& ) override; + + unsigned int SizeOf() const override; + + virtual + int Width() const; + + virtual + int Height() const; // >0 means it's a bottom-up bitmap with origin at lower right + // <0 means it's a top-down bitmap with origin at upper left + virtual + int BitsPerPixel() const; // bits per pixel + + virtual + size_t SizeofScan() const; // number of bytes per scan line + + virtual + size_t SizeofImage() const; // size of current map in bytes + + virtual + unsigned char* Bits( + int scan_line_index + ); + + virtual + const unsigned char* Bits( + int scan_line_index + ) const; + + const ON_FileReference& FileReference() const; + void SetFileReference( + const ON_FileReference& file_reference + ); + void SetFileFullPath( + const wchar_t* file_full_path, + bool bSetContentHash + ); + +private: + ON_FileReference m_file_reference; +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +#endif + +#if !defined(ON_OS_WINDOWS_GDI) + +// These are the values of the Windows defines mentioned +// in the comment below. If you're running on Windows, +// they get defined by Windows system header files. +// If you aren't running on Windows, then you don't +// need them. +//#define BI_RGB 0L +//#define BI_RLE8 1L +//#define BI_RLE4 2L +//#define BI_BITFIELDS 3L + +// Windows sizeof(ON_WindowsRGBQUAD) = 4. +struct ON_WindowsRGBQUAD { + // Mimics Windows RGBQUAD structure. + // For details searh for "RGBQUAD" at http://msdn.microsoft.com/default.asp + unsigned char rgbBlue; // BYTE + unsigned char rgbGreen; // BYTE + unsigned char rgbRed; // BYTE + unsigned char rgbReserved; // BYTE +}; + +// Windows packs BITMAPFILEHEADER +#pragma pack(push,2) +struct ON_WindowsBITMAPFILEHEADER { + unsigned short bfType; // WORD = file type, must be BM + unsigned int bfSize; // DWORD = size, in bytes, of the bitmap file + unsigned short bfReserved1; // WORD Reserved; must be zero + unsigned short bfReserved2; // WORD Reserved; must be zero + unsigned int bfOffBits; // DWORD = offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits +}; +#pragma pack(pop) + +// Mimics Windows BITMAPINFOHEADER structure. +// For details searh for "BITMAPINFOHEADER" at http://msdn.microsoft.com/default.asp +// Windows sizeof(BITMAPINFOHEADER) = 80. +struct ON_WindowsBITMAPINFOHEADER +{ + unsigned int biSize; // DWORD = sizeof(BITMAPINFOHEADER) + int biWidth; // LONG = width (in pixels) of (decompressed) bitmap + int biHeight; // LONG = height (in pixels) of (decompressed) bitmap + // >0 means it's a bottom-up bitmap with origin + // in the lower left corner. + // <0 means it's a top-down bitmap with origin + // in the upper left corner. + unsigned short biPlanes; // WORD = number of planes + // (always 1 in current Windows versions) + unsigned short biBitCount; // WORD = bits per pixel (0,1,4,8,16,24,32 are valid) + // 1 See http://msdn.microsoft.com/default.asp + // 4 See http://msdn.microsoft.com/default.asp + // 8 The bitmap has a maximum of 256 colors, + // and the bmiColors member contains up + // to 256 entries. In this case, each byte + // in the array represents a single pixel. + // 16 See http://msdn.microsoft.com/default.asp + // 24 If biClrUsed=0 and biCompression=BI_RGB(0), + // then each 3-byte triplet in the bitmap + // array represents the relative intensities + // of blue, green, and red, respectively, for + // a pixel. For other possibilities, see + // http://msdn.microsoft.com/default.asp + // 32 If biClrUsed=0 and biCompression=BI_RGB(0), + // then each 4-byte DWORD in the bitmap + // array represents the relative intensities + // of blue, green, and red, respectively, for + // a pixel. The high byte in each DWORD is not + // used. + // If biClrUsed=3, biCompression=BITFIELDS(3), + // biColors[0] = red mask (0x00FF0000), + // biColors[1] = green mask (0x0000FF00), and + // biColors[2] = blue mask (0x000000FF), + // then tese masks are used with each 4-byte + // DWORD in the bitmap array to determine + // the pixel's relative intensities. // + // For other possibilities, see + // http://msdn.microsoft.com/default.asp + unsigned int biCompression; // DWORD Currently, Windows defines the following + // types of compression. + // =0 BI_RGB (no compression) + // =1 BI_RLE8 (run length encoded used for 8 bpp) + // =2 BI_RLE4 (run length encoded used for 4 bpp) + // =3 BI_BITFIELDS Specifies that the bitmap is + // not compressed and that the color table + // consists of three DWORD color masks that + // specify the red, green, and blue components, + // respectively, of each pixel. This is valid + // when used with 16- and 32-bit-per-pixel + // bitmaps. + // =4 BI_JPEG (not supported in Win 95/NT4) + // + unsigned int biSizeImage; // DWORD = bytes in image + int biXPelsPerMeter; // LONG + int biYPelsPerMeter; // LONG + unsigned int biClrUsed; // DWORD = 0 or true length of bmiColors[] array. If 0, + // then the value of biBitCount determines the + // length of the bmiColors[] array. + unsigned int biClrImportant; // DWORD +}; + +struct ON_WindowsBITMAPINFO +{ + // Mimics Windows BITMAPINFO structure. + // For details searh for "BITMAPINFO" at http://msdn.microsoft.com/default.asp + ON_WindowsBITMAPINFOHEADER bmiHeader; + ON_WindowsRGBQUAD bmiColors[1]; // The "[1]" is for the compiler. In + // practice this array commonly has + // length 0, 3, or 256 and a BITMAPINFO* + // points to a contiguous piece of memory + // that contains + // + // BITMAPINFOHEADER + // RGBQUAD[length determined by flags] + // unsigned char[biSizeImage] + // + // See the ON_WindowsBITMAPINFOHEADER comments + // and http://msdn.microsoft.com/default.asp + // for more details. +}; + +#endif + +class ON_CLASS ON_WindowsBitmap : public ON_Bitmap +{ + ON_OBJECT_DECLARE(ON_WindowsBitmap); + // Uncompressed 8 bpp, 24 bpp, or 32 bpp Windows device + // independent bitmaps (DIB) +public: + ON_WindowsBitmap() = default; + ~ON_WindowsBitmap(); + ON_WindowsBitmap(const ON_WindowsBitmap&); + ON_WindowsBitmap& operator=(const ON_WindowsBitmap&); + + static const ON_WindowsBitmap Unset; + + /* + Parameters: + width - [in] + height - [in] + bits_per_pixel - [in] + 1, 2, 4, 8, 16, 24, or 32 + */ + bool Create( + int width, + int height, + int bits_per_pixel + ); + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + bool IsEmpty() const; + + bool Write( ON_BinaryArchive& ) const override; // writes compressed image + bool Read( ON_BinaryArchive& ) override; // reads compressed image + unsigned int SizeOf() const override; + +public: + bool WriteCompressed( ON_BinaryArchive& ) const; + bool ReadCompressed( ON_BinaryArchive& ); + bool WriteUncompressed( ON_BinaryArchive& ) const; + bool ReadUncompressed( ON_BinaryArchive& ); + +public: + int Width() const override; + int Height() const override; // >0 means it's a bottom-up bitmap with origin at lower right + // <0 means it's a top-down bitmap with origin at upper left + + int PaletteColorCount() const; // number of colors in palette + int SizeofPalette() const; // number of bytes in palette + + int BitsPerPixel() const override; + size_t SizeofScan() const override; // number of bytes per scan line + size_t SizeofImage() const override; // number of bytes in image + + unsigned char* Bits( + int // index of scan line + ) override; + const unsigned char* Bits( + int // index of scan line + ) const override; + + //int PaletteIndex( ON_Color ) const; // for 8bpp bitmaps + + ON_Color Pixel( + int, // 0 <= i < width + int // 0 <= j < height + ) const; + ON_Color Pixel( + int, // 0 <= i < width + const unsigned char* // value of Bits( j ) + ) const; + + //bool SetColor( // sets entire map to specified color + // ON_Color + // ); + +#if defined(ON_OS_WINDOWS_GDI) + + /* + Description: + Create an ON_WindowsBitmap from a contiguous bitmap. + Copies src. + Parameters: + src - [in] contiguous Windows device independent bitmap. + Remarks: + If the current Windows BITMAPINFO is identical to ON_WindowsBITMAPINFO, + then the result of this call is identical to + + int color_count = number of colors in bitmap's palette; + ON_WindowsBitmap::Create( &src, &src.bmiColors[color_count], true ). + + See Also: + ON_WindowsBitmap::Create + */ + ON_WindowsBitmap( const BITMAPINFO& src ); + + /* + Description: + Create an ON_WindowsBitmap from a contiguous bitmap. + Shares bitmap memory with src. + Parameters: + src - [in] contiguous Windows device independent bitmap. + See Also: + ON_WindowsBitmap::Create + Remarks: + ~ON_WindowsBitmap will not delete src. + */ + ON_WindowsBitmap( const BITMAPINFO* src ); + + /* + Description: + Create an ON_WindowsBitmap from a contiguous bitmap. + Copies src. + Parameters: + src - [in] contiguous Windows device independent bitmap. + See Also: + ON_WindowsBitmap::Create + */ + ON_WindowsBitmap& operator=( const BITMAPINFO& src ); + + /* + Description: + Create and ON_WindowsBitmap from a Windows BITMAPINFO pointer + and a pointer to the bits. + + This is intended to make it easy to write compressed bimaps. + For ON_WindowsBitmap classes created with ON_WindowsBitmap::Share, + ON_WindowsBitmap::Destroy and ~ON_WindowsBitmap will + not free the bmi and bits memory. + + Parameters: + bmi - [in] valid BITMAPINFO + bits - [in] bits for BITMAPINFO + bCopy - [in] If true, the bmi and bits are copied into a contiguous + bitmap that will be deleted by ~ON_WindowsBitmap. + If false, the m_bmi and m_bits pointers on this class + are simply set to bmi and bits. In this case, + ~ON_WindowsBitmap will not free the bmi or bits + memory. + + Example: + + ON_BinaryArchive archive = ...; + BITMAPINFO* bmi = 0; + unsigned char* bits = 0; + int color_count = ...; // number of colors in palette + + int sizeof_palette = sizeof(bmi->bmiColors[0]) * color_count; + + BITMAPINFO* bmi = (LPBITMAPINFO)calloc( 1, sizeof(*bmi) + sizeof_palette ); + + bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader); + bmi->bmiHeader.biWidth = width; + bmi->bmiHeader.biHeight = height; + bmi->bmiHeader.biPlanes = 1; + bmi->bmiHeader.biBitCount = (USHORT)color_depth; + bmi->bmiHeader.biCompression = BI_RGB; + bmi->bmiHeader.biXPelsPerMeter = 0; + bmi->bmiHeader.biYPelsPerMeter = 0; + bmi->bmiHeader.biClrUsed = 0; + bmi->bmiHeader.biClrImportant = 0; + bmi->bmiHeader.biSizeImage = GetStorageSize(); + + // initialize palette + ... + + HBITMAP hbm = ::CreateDIBSection( nullptr, bmi, ..., (LPVOID*)&bits, nullptr, 0); + + { + // Use ON_WindowsBitmap to write a compressed bitmap to + // archive. Does not modify bmi or bits. + ON_WindowsBitmap onbm; + onbm.Create(bmi,bit,false); + onbm.Write( arcive ); + } + + */ + bool Create( + const BITMAPINFO* bmi, + const unsigned char* bits, + bool bCopy + ); + +#endif + + /* + Returns: + True if m_bmi and m_bits are in a single contiguous + block of memory. + False if m_bmi and m_bits are in two blocks of memory. + */ + bool IsContiguous() const; + +#if defined(ON_OS_WINDOWS_GDI) + BITMAPINFO* m_bmi = nullptr; +#else + struct ON_WindowsBITMAPINFO* m_bmi = nullptr; + + /* +Description: + Create an ON_WindowsBitmap from a contiguous bitmap ON_WindowsBITMAPINFO. + Parameters: + src - [in] + A contiguous Windows device independent bitmap. This means that the + "bits" in the bitmap begin at the memory location &m_bits->bmiColors[0]. + See Also: + Remarks: + ~ON_WindowsBitmap will not delete src. + */ + bool Create ( + const struct ON_WindowsBITMAPINFO* src + ); +#endif + + unsigned char* m_bits = nullptr; + +private: + int m_bFreeBMI = 0; // 0 m_bmi and m_bits are not freed by ON_WindowsBitmap::Destroy + // 1 m_bmi memory is freed by ON_WindowsBitmap::Destroy + // 2 m_bits memory is freed by ON_WindowsBitmap::Destroy + // 3 m_bmi and m_bits memory is freed by ON_WindowsBitmap::Destroy + +private: + bool Internal_WriteV5( ON_BinaryArchive& ) const; + bool Internal_ReadV5( ON_BinaryArchive& ); + +protected: + void Internal_Destroy(); + void Internal_Copy( + const ON_WindowsBitmap& src + ); +}; + +/* +Description: + ON_WindowsBitmapEx is identical to ON_WindowsBitmap except that + it's Read/Write functions save bitmap names. +*/ +class ON_CLASS ON_WindowsBitmapEx : public ON_WindowsBitmap +{ + ON_OBJECT_DECLARE(ON_WindowsBitmapEx); +public: + ON_WindowsBitmapEx() = default; + ~ON_WindowsBitmapEx() = default; + ON_WindowsBitmapEx(const ON_WindowsBitmapEx&) = default; + ON_WindowsBitmapEx& operator=(const ON_WindowsBitmapEx&) = default; + + static const ON_WindowsBitmapEx Unset; + + bool Write( ON_BinaryArchive& ) const override; // writes compressed image + bool Read( ON_BinaryArchive& ) override; // reads compressed image + +private: + bool Internal_WriteV5( ON_BinaryArchive& ) const; // writes compressed image + bool Internal_ReadV5( ON_BinaryArchive& ); // reads compressed image +}; + +class ON_CLASS ON_EmbeddedBitmap : public ON_Bitmap +{ + ON_OBJECT_DECLARE(ON_EmbeddedBitmap); +public: + ON_EmbeddedBitmap() = default; + ~ON_EmbeddedBitmap(); + ON_EmbeddedBitmap(const ON_EmbeddedBitmap&); + ON_EmbeddedBitmap& operator=(const ON_EmbeddedBitmap&); + + static const ON_EmbeddedBitmap Unset; + + void Create( + size_t sizeof_buffer + ); + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + bool Write( ON_BinaryArchive& ) const override; + bool Read( ON_BinaryArchive& ) override; + unsigned int SizeOf() const override; + + size_t SizeofImage() const override; + unsigned char* Bits(int) override; + const unsigned char* Bits(int) const override; + + const void* m_buffer = nullptr; + size_t m_sizeof_buffer = 0; + bool m_managed_buffer = false; // true means the ON_EmbeddedBitmap class manages m_buffer memory. + ON__UINT32 m_buffer_crc32 = 0; // 32 bit crc from ON_CRC32 + +private: + bool Internal_WriteV5( ON_BinaryArchive& ) const; + bool Internal_ReadV5( ON_BinaryArchive& ); + +private: + void Internal_Destroy(); + void Internal_Copy( + const ON_EmbeddedBitmap& src + ); +}; + +#endif diff --git a/opennurbs/Include/opennurbs_bounding_box.h b/opennurbs/Include/opennurbs_bounding_box.h new file mode 100644 index 0000000..76aee6f --- /dev/null +++ b/opennurbs/Include/opennurbs_bounding_box.h @@ -0,0 +1,914 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_BOUNDING_BOX_INC_) +#define ON_BOUNDING_BOX_INC_ + +//////////////////////////////////////////////////////////////// +// +// ON_BoundingBox - axis aligned bounding box +// + +class ON_CLASS ON_BoundingBox +{ +public: + static const ON_BoundingBox EmptyBoundingBox; // ((1.0,0.0,0.0),(-1.0,0.0,0.0)) + static const ON_BoundingBox UnsetBoundingBox; // all coordinates are ON_UNSET_VALUE + static const ON_BoundingBox NanBoundingBox; // all coordinates are ON_DBL_QNAN + + ON_BoundingBox() ON_NOEXCEPT; // creates EmptyBoundingBox + ~ON_BoundingBox() = default; + ON_BoundingBox(const ON_BoundingBox&) = default; + ON_BoundingBox& operator=(const ON_BoundingBox&) = default; + + explicit ON_BoundingBox( + const ON_3dPoint&, // min corner of axis aligned bounding box + const ON_3dPoint& // max corner of axis aligned bounding box + ); + + + // OBSOLETE + // temporary - use ON_ClippingRegion - this function will be removed soon. + int IsVisible( + const ON_Xform& bbox2c + ) const; + + + // OBSOLETE + void Destroy(); // set this = ON_BoundingBox::EmptyBoundingBox + + // operator[] returns min if index <= 0 and max if indes >= 1 + ON_3dPoint& operator[](int); + const ON_3dPoint& operator[](int) const; + + ON_3dPoint Min() const; + ON_3dPoint Max() const; + ON_3dVector Diagonal() const; // max corner - min corner + ON_3dPoint Center() const; + ON_3dPoint Corner( // 8 corners of box + int, // x_index 0 = Min().x, 1 = Max().x + int, // y_index 0 = Min().y, 1 = Max().y + int // z_index 0 = Min().z, 1 = Max().z + ) const; + bool GetCorners( + ON_3dPointArray& box_corners // returns list of 8 corner points + ) const; + bool GetCorners( + ON_3dPoint box_corners[8] // returns list of 8 corner points + ) const; + + /* + Parameters: + edges[] - out + 12 edge lines. If the bounding box has no height, width or depth, + then the corresponding edges will have the same "from" and "to" + points. + Returns: + If the bounding box is valid, then true is returned and + 12 line segments, some possibly a single point, are returned. + Otherwise false is returned and 12 line segments with "from" + and "to" points set to ON_3dPoint::UnsetPoint are returned. + */ + bool GetEdges( + ON_Line edges[12] // returns list of 12 edge segments + ) const; + + // OBSOLETE IsValid() = IsNotEmpty() + bool IsValid() const; // empty boxes are not valid + + bool IsSet() const; // every coordinate is a finite, valid double, not ON_UNSET_VALUE and not ON_UNSET_POSITIVE_VALUE + bool IsUnset() const; // some coordinate is ON_UNSET_VALUE or ON_UNSET_POSITIVE_VALUE + bool IsNan() const; // some coordinate is a NAN + bool IsUnsetOrNan() const; // = IsUnset() or IsNan() + + bool IsEmpty() const; // (m_min.x > m_max.x || m_min.y > m_max.y || m_min.z > m_max.z) && IsSet(); + bool IsNotEmpty() const; // (m_min.x <= m_max.x && m_min.y <= m_max.y && m_min.z <= m_max.z) && IsSet() + bool IsPoint() const; // (m_min.x == m_max.x && m_min.y == m_max.y && m_min.z == m_max.z) && IsSet() + + void Dump(class ON_TextLog&) const; + + /* + Description: + Test a bounding box to see if it is degenerate (flat) + in one or more directions. + Parameters: + tolerance - [in] Distances <= tolerance will be considered + to be zero. If tolerance is negative (default), then + a scale invarient tolerance is used. + Returns: + @untitled table + 0 box is not degenerate + 1 box is a rectangle (degenerate in one direction) + 2 box is a line (degenerate in two directions) + 3 box is a point (degenerate in three directions) + 4 box is not valid + */ + int IsDegenerate( + double tolerance = ON_UNSET_VALUE + ) const; + + + ////////// + // ON_BoundingBox::Transform() updates the bounding box + // to be the smallest axis aligned bounding box that contains + // the transform of the eight corner points of the input + // bounding box. + bool Transform( const ON_Xform& ); + + double Tolerance() const; // rough guess at a tolerance to use for comparing + // objects in this bounding box + + + // All of these Set() functions set or expand a box to enclose the points in the arguments + // If bGrowBox is true, the existing box is expanded, otherwise it is only set to the current point list + bool Set( + int dim, + bool is_rat, + int count, + int stride, + const double* point_array, + int bGrowBox = false + ); + + bool Set( + const ON_3dPoint& point, + int bGrowBox = false + ); + + bool Set( + const ON_2dPoint& point, + int bGrowBox = false + ); + + bool Set( + const ON_SimpleArray& point_array, + int bGrowBox = false + ); + + bool Set( + const ON_SimpleArray& point_array, + int bGrowBox = false + ); + + bool Set( + const ON_SimpleArray& point_array, + int bGrowBox = false + ); + + bool Set( + int dim, + bool is_rat, + int count, + int stride, + const float* point_array, + int bGrowBox = false + ); + + bool Set( + const ON_3fPoint& point, + int bGrowBox = false + ); + + bool Set( + const ON_2fPoint& point, + int bGrowBox = false + ); + + bool Set( + const ON_SimpleArray& point_array, + int bGrowBox = false + ); + + bool Set( + const ON_SimpleArray& point_array, + int bGrowBox = false + ); + + bool Set( + const ON_SimpleArray& point_array, + int bGrowBox = false + ); + + bool IsPointIn( + const ON_3dPoint& test_point, // point to test + int bStrictlyIn = false + // true to test for strict ( min < point < max ) + // false to test for (min <= point <= max) + // + ) const; + + ////////// + // Point on or in the box that is closest to test_point. + // If test_point is in or on the box, the test_point is returned. + ON_3dPoint ClosestPoint( + const ON_3dPoint& test_point + ) const; + + + /* + Description: + Quickly find a lower bound on the distance + between the point and this bounding box. + Parameters: + P - [in] + Returns: + A distance that is less than or equal to the shortest + distance from the line to this bounding box. + Put another way, if Q is any point in this bounding box, + then P.DistanceTo(Q) >= MinimumDistanceTo(bbox). + */ + double MinimumDistanceTo( const ON_3dPoint& P ) const; + + /* + Description: + Quickly find an upper bound on the distance + between the point and this bounding box. + Parameters: + P - [in] + Returns: + A distance that is greater than or equal to the + longest distance from the point P to this bounding box. + Put another way, if Q is any point in this bounding box, + then P.DistanceTo(Q) <= MaximumDistanceTo(bbox). + */ + double MaximumDistanceTo( const ON_3dPoint& P ) const; + + + /* + Description: + Quickly find a lower bound on the distance + between this and the other bounding box. + Parameters: + other - [in] + Returns: + A distance that is less than or equal to the shortest + distance between the bounding boxes. + Put another way, if Q is any point in this bounding box + and P is any point in the other bounding box, + then P.DistanceTo(Q) >= MinimumDistanceTo(bbox). + */ + double MinimumDistanceTo( const ON_BoundingBox& other ) const; + + /* + Description: + Quickly find an upper bound on the distance + between this and the other bounding box. + Parameters: + other - [in] + Returns: + A distance that is greater than or equal to the longest + distance between the bounding boxes. + Put another way, if Q is any point in this bounding box + and P is any point in the other bounding box, + then P.DistanceTo(Q) <= MaximumDistanceTo(bbox). + */ + double MaximumDistanceTo( const ON_BoundingBox& other ) const; + + /* + Description: + Quickly find a lower bound on the distance + between the line segment and this bounding box. + Parameters: + line - [in] + Returns: + A distance that is less than or equal to the shortest + distance from the line to this bounding box. + Put another way, if Q is any point on line + and P is any point in this bounding box, then + P.DistanceTo(Q) >= MinimumDistanceTo(bbox). + */ + double MinimumDistanceTo( const ON_Line& line ) const; + + /* + Description: + Quickly find a tight lower bound on the distance + between the plane and this bounding box. + Parameters: + plane - [in] + Returns: + The minimum distance between a point on the plane + and a point on the bounding box. + See Also: + ON_PlaneEquation::MimimumValueAt + ON_PlaneEquation::MaximumValueAt + */ + double MinimumDistanceTo( const ON_Plane& plane ) const; + double MinimumDistanceTo( const ON_PlaneEquation& plane_equation ) const; + + /* + Description: + Quickly find an upper bound on the distance + between the line segment and this bounding box. + Parameters: + line - [in] + Returns: + A distance that is greater than or equal to the + longest distance from the line to this bounding box. + Put another way, if Q is any point on the line + and P is any point in this bounding box, then + P.DistanceTo(Q) <= MaximumDistanceTo(bbox). + */ + double MaximumDistanceTo( const ON_Line& line ) const; + + /* + Description: + Quickly find a tight upper bound on the distance + between the plane and this bounding box. + Parameters: + plane - [in] + Returns: + A distance that is equal to the longest distance from + the plane to this bounding box. Put another way, + if Q is any point on the plane and P is any point + in this bounding box, then + P.DistanceTo(Q) <= MaximumDistanceTo(bbox) and there + is at least one point on the bounding box where the + distance is equal to the returned value. + See Also: + ON_PlaneEquation::MaximumValueAt + */ + double MaximumDistanceTo( const ON_Plane& plane ) const; + double MaximumDistanceTo( const ON_PlaneEquation& plane_equation ) const; + + + /* + Description: + Quickly determine if the shortest distance from + the point P to the bounding box is greater than d. + Parameters: + d - [in] distance (> 0.0) + P - [in] + Returns: + True if if the shortest distance from the point P + to the bounding box is greater than d. + */ + bool IsFartherThan( double d, const ON_3dPoint& P ) const; + + /* + Description: + Quickly determine if the shortest distance from the line + to the bounding box is greater than d. + Parameters: + d - [in] distance (> 0.0) + line - [in] + Returns: + True if the shortest distance from the line + to the bounding box is greater than d. It is not the + case that false means that the shortest distance + is less than or equal to d. + */ + bool IsFartherThan( double d, const ON_Line& line ) const; + + /* + Description: + Quickly determine if the shortest distance from the plane + to the bounding box is greater than d. + Parameters: + d - [in] distance (> 0.0) + plane - [in] + Returns: + True if the shortest distance from the plane + to the bounding box is greater than d, and false + if the shortest distance is less than or equal to d. + */ + bool IsFartherThan( double d, const ON_Plane& plane ) const; + + /* + Description: + Quickly determine if the shortest distance from the plane + to the bounding box is greater than d. + Parameters: + d - [in] distance (> 0.0) + plane_equation - [in] (the first three coefficients + are assumed to be a unit vector. + If not, adjust your d accordingly.) + Returns: + True if the shortest distance from the plane + to the bounding box is greater than d, and false + if the shortest distance is less than or equal to d. + */ + bool IsFartherThan( double d, const ON_PlaneEquation& plane_equation ) const; + + /* + Description: + Quickly determine if the shortest distance this bounding + box to another bounding box is greater than d. + Parameters: + d - [in] distance (> 0.0) + other - [in] other bounding box + Returns: + True if if the shortest distance from this bounding + box to the other bounding box is greater than d. + */ + bool IsFartherThan( double d, const ON_BoundingBox& other ) const; + + + // Description: + // Get point in a bounding box that is closest to a line + // segment. + // Parameters: + // line - [in] line segment + // box_point - [out] point in box that is closest to line + // segment point at t0. + // t0 - [out] parameter of point on line that is closest to + // the box. + // t1 - [out] parameter of point on line that is closest to + // the box. + // Returns: + // 3 success - line segments intersects box in a segment + // from line(t0) to line(t1) (t0 < t1) + // 2 success - line segments intersects box in a single point + // at line(t0) (t0==t1) + // 1 success - line segment does not intersect box. Closest + // point on the line is at line(t0) (t0==t1) + // 0 failure - box is invalid. + // Remarks: + // The box is treated as a solid box. If the intersection + // of the line segment, then 3 is returned. + int GetClosestPoint( + const ON_Line&, // line + ON_3dPoint&, // box_point + double*, // t0 + double* // t1 + ) const; + + ////////// + // Get points on bounding boxes that are closest to each other. + // If the boxes intersect, then the point at the centroid of the + // intersection is returned for both points. + bool GetClosestPoint( + const ON_BoundingBox&, // "other" bounding box + ON_3dPoint&, // point on "this" box that is closest to "other" box + ON_3dPoint& // point on "other" box that is closest to "this" box + ) const; + + ////////// + // Point on the box that is farthest from the test_point. + ON_3dPoint FarPoint( + const ON_3dPoint& // test_point + ) const; + + ////////// + // Get points on bounding boxes that are farthest from each other. + bool GetFarPoint( + const ON_BoundingBox&, // "other" bounding box + ON_3dPoint&, // point on "this" box that is farthest from "other" box + ON_3dPoint& // point on "other" box that is farthest from "this" box + ) const; + + /* + Description: + Intersect this with other_bbox and save intersection in this. + Parameters: + other_bbox - [in] + Returns: + True if this-intesect-other_bbox is a non-empty valid bounding box + and this is set. False if the intersection is empty, in which case + "this" is set to an invalid bounding box. + Remarks: + If "this" or other_bbox is invalid, they are treated as + the empty set, and false is returned. + */ + bool Intersection( + const ON_BoundingBox& other_bbox + ); + + /* + Description: + Set "this" to the intersection of bbox_A and bbox_B. + Parameters: + bbox_A - [in] + bbox_B - [in] + Returns: + True if the "this" is a non-empty valid bounding box. + False if the intersection is empty, in which case + "this" is set to an invalid bounding box. + Remarks: + If bbox_A or bbox_B is invalid, they are treated as + the empty set, and false is returned. + */ + bool Intersection( // this = intersection of two args + const ON_BoundingBox& bbox_A, + const ON_BoundingBox& bbox_B + ); + + bool Intersection( //Returns true when intersect is non-empty. + const ON_Line&, //Infinite Line segment to intersect with + double* =nullptr , // t0 parameter of first intersection point + double* =nullptr // t1 parameter of last intersection point (t0<=t1) + ) const; + + /* + Description: + Test a box to see if it is contained in this box. + Parameters: + other - [in] box to test + bProperSubSet - [in] if true, then the test is for a proper inclusion. + Returns: + If bProperSubSet is false, then the result is true when + this->m_min[i] <= other.m_min[i] and other.m_max[i] <= this->m_max[i]. + for i=0,1 and 2. + If bProperSubSet is true, then the result is true when + the above condition is true and at least one of the inequalities is strict. + */ + bool Includes( + const ON_BoundingBox& other, + bool bProperSubSet = false + ) const; + + double Volume() const; + + double Area() const; + + // Union() returns true if union is not empty. + // Invalid boxes are treated as the empty set. + bool Union( // this = this union arg + const ON_BoundingBox& + ); + + bool Union( // this = union of two args + const ON_BoundingBox&, + const ON_BoundingBox& + ); + + /* + Description: + Test to see if "this" and other_bbox are disjoint (do not intersect). + Parameters: + other_bbox - [in] + Returns: + True if "this" and other_bbox are disjoint. + Remarks: + If "this" or other_bbox is invalid, then true is returned. + */ + bool IsDisjoint( + const ON_BoundingBox& other_bbox + ) const; + + /* + Description: + Test to see if "this" and line are disjoint (do not intersect or line is included). + Parameters: + line - [in] + infinite - [in] if false or not provided, then the line is considered bounded by start and end points. + Returns: + True if "this" and line are disjoint. + */ + bool IsDisjoint(const ON_Line& line) const; + bool IsDisjoint(const ON_Line& line, bool infinite) const; + + bool SwapCoordinates( int, int ); + + /* + Description: + Expand the box by adding delta to m_max and subtracting + it from m_min. So, when delta is positive and the interval is + increasing this function expands the box on each side. + Returns: + true if the result is Valid. + */ + bool Expand(ON_3dVector delta); + + ON_3dPoint m_min; + ON_3dPoint m_max; +}; + +/* +Returns: + True if lhs and rhs are identical. +*/ +ON_DECL +bool operator==( const ON_BoundingBox& lhs, const ON_BoundingBox& rhs ); + +/* +Returns: + True if lhs and rhs are not equal. +*/ +ON_DECL +bool operator!=( const ON_BoundingBox& lhs, const ON_BoundingBox& rhs ); + +class ON_CLASS ON_BoundingBoxAndHash +{ +public: + ON_BoundingBoxAndHash() = default; + ~ON_BoundingBoxAndHash() = default; + ON_BoundingBoxAndHash(const ON_BoundingBoxAndHash&) = default; + ON_BoundingBoxAndHash& operator=(const ON_BoundingBoxAndHash&) = default; + +public: + // This hash depends on the context and is a hash + // of the information used to calculte the bounding box. + // It is not the hash of the box values + + void Set( + const ON_BoundingBox& bbox, + const ON_SHA1_Hash& hash + ); + + const ON_BoundingBox& BoundingBox() const; + + const ON_SHA1_Hash& Hash() const; + + /* + Returns: + True if bounding box IsSet() is true and hash is not EmptyContentHash. + */ + bool IsSet() const; + + bool Write( + class ON_BinaryArchive& archive + ) const; + + bool Read( + class ON_BinaryArchive& archive + ); + + private: + ON_BoundingBox m_bbox = ON_BoundingBox::UnsetBoundingBox; + ON_SHA1_Hash m_hash = ON_SHA1_Hash::EmptyContentHash; +}; + +/* +A class that caches 8 bounding box - hash pairs and keeps the most frequently +used bounding boxes. +*/ +class ON_CLASS ON_BoundingBoxCache +{ +public: + ON_BoundingBoxCache() = default; + ~ON_BoundingBoxCache() = default; + ON_BoundingBoxCache(const ON_BoundingBoxCache&) = default; + ON_BoundingBoxCache& operator=(const ON_BoundingBoxCache&) = default; + +public: + /* + Description: + Add a bounding box that can be found from a hash value. + Parameters: + bbox - [in] + hash - [in] + A hash of the information needed to create this bounding box. + */ + void AddBoundingBox( + const ON_BoundingBox& bbox, + const ON_SHA1_Hash& hash + ); + + void AddBoundingBox( + const ON_BoundingBoxAndHash& bbox_and_hash + ); + + /* + Description: + Get a cached bounding box. + Parameters: + hash - [in] + bbox - [out] + If the hash identifies a bounding box in the cache, then + that bounding box is returned. Otherwise ON_BoundingBox::NanBoundingBox + is returned. + Returns: + true - cached bounding box returned + false - bounding box not in cache. + */ + bool GetBoundingBox( + const ON_SHA1_Hash& hash, + ON_BoundingBox& bbox + ) const; + + /* + Description: + Remove a bounding box that can be found from a hash value. + Parameters: + hash - [in] + Returns: + true - hash was in the cache and removed. + false - hash was not in the cache. + Remarks: + If the hash values you are using are correctly computed and include + all information that the bouding box depends on, then + you never need to remove bounding boxes. Unused ones will get + removed as new ones are added. + */ + bool RemoveBoundingBox( + const ON_SHA1_Hash& hash + ); + + /* + Description: + Removes all bounding boxes. + Remarks: + If the hash values you are using are correctly computed and include + all information that the bouding box depends on, then + you never need to remove bounding boxes. Unused ones will get + removed as new ones are added. + If the hash does not include all information required to compute + the bounding boxes, then call RemoveAllBoundingBoxes() when the + non-hashed information changes. + */ + void RemoveAllBoundingBoxes(); + + /* + Returns: + Number of cached boxes. + */ + unsigned int BoundingBoxCount() const; + + bool Write( + class ON_BinaryArchive& archive + ) const; + + bool Read( + class ON_BinaryArchive& archive + ); + +private: + // number of boxes set in m_cache[] + unsigned int m_count = 0; + + // capacity of m_cache[] - set when needed + unsigned int m_capacity = 0; + + // Bounding box cache. Most recently used boxes are first. + mutable ON_BoundingBoxAndHash m_cache[8]; + + /* + Returns: + m_cache[] array index of box with the hash. + ON_UNSET_UINT_INDEX if hash is not present in m_cache[] array. + */ + unsigned int Internal_CacheIndex(const ON_SHA1_Hash& hash) const; +}; + +#if defined(ON_DLL_TEMPLATE) + +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; + +#endif + +/* +Description: + Get a tight bounding box that contains the points. +Parameters: + dim - [in] (>=1) + is_rat - [in] true if points are rational + count - [in] number of points + stride - [in] stride between points + point_list - [in] + bbox - [in/out] + bGrowBox - [in] (default = false) + If the input bbox is valid and bGrowBox is true, + then the output bbox is the union of the input + bbox and the bounding box of the point list. + xform - [in] (default = nullptr) + If not null, the bounding box of the transformed + points is calculated. The points are not modified. +Returns: + True if the output bbox is valid. +*/ +ON_DECL +bool ON_GetPointListBoundingBox( + int dim, + bool is_rat, + int count, + int stride, + const double* point_list, + ON_BoundingBox& bbox, + int bGrowBox = false, + const ON_Xform* xform = 0 + ); + +ON_DECL +bool ON_GetPointListBoundingBox( + int dim, + bool is_rat, + int count, + int stride, + const float* point_list, + ON_BoundingBox& bbox, + int bGrowBox = false, + const ON_Xform* xform = 0 + ); + +ON_DECL +bool ON_GetPointListBoundingBox( + int dim, + bool is_rat, + int count, + int stride, + const double* point_list, + double* boxmin, // min[dim] + double* boxmax, // max[dim] + int bGrowBox + ); + +ON_DECL +ON_BoundingBox ON_PointListBoundingBox( + int dim, + bool is_rat, + int count, + int stride, + const double* point_list + ); + +ON_DECL +bool ON_GetPointListBoundingBox( + int dim, + bool is_rat, + int count, + int stride, + const float* point_list, + float* boxmin, // min[dim] + float* boxmax, // max[dim] + int bGrowBox + ); + +ON_DECL +ON_BoundingBox ON_PointListBoundingBox( // low level workhorse function + int dim, + bool is_rat, + int count, + int stride, + const float* point_list + ); + +ON_DECL +bool ON_GetPointGridBoundingBox( + int dim, + bool is_rat, + int point_count0, int point_count1, + int point_stride0, int point_stride1, + const double* point_grid, + double* boxmin, // min[dim] + double* boxmax, // max[dim] + int bGrowBox + ); + +ON_DECL +ON_BoundingBox ON_PointGridBoundingBox( + int dim, + bool is_rat, + int point_count0, int point_count1, + int point_stride0, int point_stride1, + const double* point_grid + ); + +ON_DECL +double ON_BoundingBoxTolerance( + int dim, + const double* bboxmin, + const double* bboxmax + ); + +/* +Description: + Determine if an object is too large or too far + from the origin for single precision coordinates + to be useful. +Parameters: + bbox - [in] + Bounding box of an object with single precision + coordinates. An ON_Mesh is an example of an + object with single precision coordinates. + xform - [out] + If this function returns false and xform is not + null, then the identity transform is returned. + If this function returns true and xform is not + null, then the transform moves the region + contained in bbox to a location where single + precision coordinates will have enough + information for the object to be useful. +Returns: + true: + The region contained in bbox is too large + or too far from the origin for single + precision coordinates to be useful. + false: + A single precision object contained in bbox + will be satisfactory for common calculations. +*/ +ON_DECL +bool ON_BeyondSinglePrecision( const ON_BoundingBox& bbox, ON_Xform* xform ); + +ON_DECL +bool ON_WorldBBoxIsInTightBBox( + const ON_BoundingBox& tight_bbox, + const ON_BoundingBox& world_bbox, + const ON_Xform* xform + ); + +#endif diff --git a/opennurbs/Include/opennurbs_box.h b/opennurbs/Include/opennurbs_box.h new file mode 100644 index 0000000..32e25f9 --- /dev/null +++ b/opennurbs/Include/opennurbs_box.h @@ -0,0 +1,120 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_BOX_INC_) +#define ON_BOX_INC_ + +class ON_CLASS ON_Box +{ +public: + ON_Plane plane; + // intervals are finite and increasing when the box is valid + ON_Interval dx; + ON_Interval dy; + ON_Interval dz; + + ON_Box(); + ON_Box( const ON_BoundingBox& bbox ); + ~ON_Box(); + + bool IsValid() const; + + bool Create( const ON_BoundingBox& bbox ); + + void Destroy(); + + ON_3dPoint Center() const; + bool GetCorners( ON_3dPoint* corners ) const; + bool GetCorners( ON_SimpleArray& corners ) const; + + ON_BoundingBox BoundingBox() const; + + ON_3dPoint PointAt( + double r, + double s, + double t + ) const; + + bool ClosestPointTo( + ON_3dPoint point, + double* r, + double* s, + double* t + ) const; + + // returns point on box that is closest to given point + ON_3dPoint ClosestPointTo( + ON_3dPoint test_point + ) const; + + // rotate sphere about its origin + bool Rotate( + double sin_angle, // sin(angle) + double cos_angle, // cos(angle) + const ON_3dVector& axis_of_rotation // axis of rotation + ); + + bool Rotate( + double angle_radians, // angle in radians + const ON_3dVector& axis_of_rotation // axis of rotation + ); + + // rotate sphere about a point and axis + bool Rotate( + double sin_angle, // sin(angle) + double cos_angle, // cos(angle) + const ON_3dVector& axis_of_rotation, // axis of rotation + const ON_3dPoint& center_of_rotation // center of rotation + ); + + bool Rotate( + double angle_radians, // angle in radians + const ON_3dVector& axis_of_rotation, // axis of rotation + const ON_3dPoint& center_of_rotation // center of rotation + ); + + bool Translate( + const ON_3dVector& + ); + + bool Transform( const ON_Xform& ); + + /* + Description: + Test the box to see if it is degenerate (flat) + in one or more directions. + Parameters: + tolerance - [in] Distances <= tolerance will be considered + to be zero. If tolerance is negative (default), then + a scale invarient tolerance is used. + Returns: + @untitled table + 0 box is not degenerate + 1 box is a rectangle (degenerate in one direction) + 2 box is a line (degenerate in two directions) + 3 box is a point (degenerate in three directions) + 4 box is not valid + */ + int IsDegenerate( + double tolerance = ON_UNSET_VALUE + ) const; + + double Volume() const; + + double Area() const; +}; + +#endif diff --git a/opennurbs/Include/opennurbs_brep.h b/opennurbs/Include/opennurbs_brep.h new file mode 100644 index 0000000..4e7cd09 --- /dev/null +++ b/opennurbs/Include/opennurbs_brep.h @@ -0,0 +1,4811 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +//////////////////////////////////////////////////////////////// +// +// Definition of b-rep and its parts +// +//////////////////////////////////////////////////////////////// + +#if !defined(OPENNURBS_BREP_INC_) +#define OPENNURBS_BREP_INC_ + +class ON_BrepTrim; +class ON_BrepEdge; +class ON_BrepLoop; +class ON_BrepFace; + + +// TEMPORARY DEFINES SO I DON'T BREAK THE BUILD +//#define m_vertex_user_i m_vertex_user.i +//#define m_trim_user_i m_trim_user.i +//#define m_edge_user_i m_edge_user.i +//#define m_loop_user_i m_loop_user.i +//#define m_face_user_i m_face_user.i + +// Description: +// Brep vertex information is stored in ON_BrepVertex classes. +// ON_Brep.m_V[] is an array of all the vertices in the brep. +// +// If a vertex is a point on a face, then brep.m_E[m_ei] +// will be an edge with no 3d curve. This edge will have +// a single trim with type ON_BrepTrim::ptonsrf. There +// will be a loop containing this single trim. +// Use ON_Brep::NewPointOnFace() to create vertices that are +// points on faces. +class ON_CLASS ON_BrepVertex : public ON_Point +{ + ON_OBJECT_DECLARE(ON_BrepVertex); + +public: + // Union available for application use. + // The constructor zeros m_vertex_user. + // The value is of m_vertex_user is not saved in 3DM + // archives and may be changed by some computations. + mutable ON_U m_vertex_user; + +public: + mutable ON_ComponentStatus m_status = ON_ComponentStatus::NoneSet; + +private: + ON__UINT16 m_reserved1 = 0U; + +public: + // index of the vertex in the ON_Brep.m_V[] array + int m_vertex_index = -1; + + ///////////////////////////////////////////////////////////////// + // Construction + // + // In general, you should not directly create ON_BrepVertex classes. + // Use ON_Brep::NewVertex instead. + ON_BrepVertex(); + ON_BrepVertex( + int // vertex index + ); + ON_BrepVertex& operator=(const ON_BrepVertex&); + + // virtual ON_Object::SizeOf override + unsigned int SizeOf() const override; + + // virtual ON_Object::DataCRC override + ON__UINT32 DataCRC(ON__UINT32 current_remainder) const override; + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + // virtual ON_Object::Dump() override + void Dump( ON_TextLog& ) const override; // for debugging + + // virtual ON_Object::Write() override + bool Write( ON_BinaryArchive& ) const override; + + // virtual ON_Object::Read() override + bool Read( ON_BinaryArchive& ) override; + + // virtual ON_Geometry::ComponentIndex() override + ON_COMPONENT_INDEX ComponentIndex() const override; + + ///////////////////////////////////////////////////////////////// + // Interface + + // Description: + // Set vertex location. + // Parameters: + // point - [in] 3d vertex location + bool SetPoint( + const ON_3dPoint& // point + ); + + // Returns: + // Vertex location. + ON_3dPoint Point() const; + + // Returns: + // value of ON_BrepVertex::m_tolerance + // Remarks: + // Use ON_Brep::SetVertexTolerance( ON_BrepVertex& ) to set tolerances. + double Tolerance() const; + + // Returns: + // number of edges that begin or end at this vertex. + int EdgeCount() const; + + + ///////////////////////////////////////////////////////////////// + // Implementation + + // indices of edges starting/ending at this vertex + // + // For closed edges, edge.m_vi[0] = edge.m_vi[1] and + // edge.m_edge_index appears twice in the m_ei[] array. + // The first occurrence of edge.m_edge_index in m_ei[] + // is for the closed edge starting the vertex. + // The second occurrence of edge,m_edge_index in m_ei[] + // is for the closed edge ending at the vertex. + // C.f. ON_Brep::Next/PrevEdge(). + ON_SimpleArray m_ei; + + // accuracy of vertex point (>=0.0 or ON_UNSET_VALUE) + // + // A value of ON_UNSET_VALUE indicates that the + // tolerance should be computed. + // + // A value of 0.0 indicates that the distance + // from the vertex to any applicable edge or trim + // end is <= ON_ZERO_TOLERANCE + // + // If an edge begins or ends at this vertex, + // then the distance from the vertex's + // 3d point to the appropriate end of the + // edge's 3d curve must be <= this tolerance. + // + // If a trim begins or ends at this vertex, + // then the distance from the vertex's 3d point + // to the 3d point on the surface obtained by + // evaluating the surface at the appropriate + // end of the trimming curve must be <= this + // tolerance. + double m_tolerance = ON_UNSET_VALUE; + +private: + ON_BrepVertex( const ON_BrepVertex& ) = delete; +}; + +/* +Description: + Brep edge information is stored in ON_BrepEdge classes. + ON_Brep.m_E[] is an array of all the edges in the brep. + + An ON_BrepEdge is derived from ON_CurveProxy so the the + edge can supply easy to use evaluation tools via + the ON_Curve virtual member functions. + + Note well that the domains and orientations of the curve + m_C3[edge.m_c3i] and the edge as a curve may not + agree. +*/ + +// April 24, 2017 Dale Lear +// ON_Curve::Trim(const ON_Interval&) is a virtual function and ON_BrepEdge derives +// from ON_CurveProxy which derives from ON_Curve. The ON_Brep::Trim(int) function was +// added and mistakenly named "Trim". This all happened about twenty years ago. +// +// Both the virtual ON_Curve::Trim(const ON_Interval&) and ON_BrepEdge::Trim(int) functions +// are widely used. At some point the functionON_Brep::Trim() will be deprecated and the 4263 +// warning ON_Brep::Trim(int) generates will be disabled for the definition of class ON_BrepEdge. +// In version 7, ON_Brep::Trim(int) will be deleted and the warning will no longer be disabled. +#pragma ON_PRAGMA_WARNING_PUSH +#pragma ON_PRAGMA_WARNING_DISABLE_MSC(4263) +#pragma ON_PRAGMA_WARNING_DISABLE_MSC(4264) + +class ON_CLASS ON_BrepEdge : public ON_CurveProxy +{ + ON_OBJECT_DECLARE(ON_BrepEdge); + +public: + + // Union available for application use. + // The constructor zeros m_edge_user. + // The value is of m_edge_user is not saved in 3DM + // archives and may be changed by some computations. + mutable ON_U m_edge_user; + +public: + mutable ON_ComponentStatus m_status = ON_ComponentStatus::NoneSet; + +private: + ON__UINT16 m_reserved1 = 0U; + +public: + // index of edge in ON_Brep.m_E[] array + int m_edge_index = -1; + + + // virtual ON_Curve::IsClosed override + bool IsClosed() const override; + + ///////////////////////////////////////////////////////////////// + // Construction + // + // In general, you should not directly create ON_BrepEdge classes. + // Use ON_Brep::NewVertex instead. + ON_BrepEdge(); + ON_BrepEdge(int); // edge index + ON_BrepEdge& operator=(const ON_BrepEdge&); + + // virtual ON_Object function + // The ON_BrepEdge override returns ON::curve_object. + ON::object_type ObjectType() const override; + + /* + Returns: + Brep this edge belongs to. + */ + ON_Brep* Brep() const; + + + /* + Parameters: + eti - [in] index into the edge's m_ti[] array. + Returns: + The trim brep.m_T[edge.m_ti[eti]]; + Remarks: + This version of "Trim" hides the virtual function ON_CurveProxy::Trim(const ON_Interval&), + which is a good thing. Special care must be taken when changing the geometry + of a brep edge to insure vertex, trim, and edge information remains valid. + */ + ON_BrepTrim* Trim( int eti ) const; + + /* + Returns: + Number of trims attached to this edge. + */ + int TrimCount() const; + + /* + Parameters: + evi - [in] 0 or 1 + Returns: + Brep vertex at specified end of the edge. + */ + ON_BrepVertex* Vertex(int evi) const; + + // virtual ON_Object::SizeOf override + unsigned int SizeOf() const override; + + // virtual ON_Object::DataCRC override + ON__UINT32 DataCRC(ON__UINT32 current_remainder) const override; + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + // virtual ON_Object::Dump() override + void Dump( ON_TextLog& ) const override; // for debugging + + // virtual ON_Object::Write() override + bool Write( ON_BinaryArchive& ) const override; + + // virtual ON_Object::Read() override + bool Read( ON_BinaryArchive& ) override; + + // virtual ON_Geometry::ComponentIndex() override + ON_COMPONENT_INDEX ComponentIndex() const override; + + // virtual ON_Curve::Reverse override + bool Reverse() override; + + /* Not necessary. Base class does the right thing. ON_CurveProxy does not have an override. + // virtual ON_Curve::SetStartPoint override + bool SetStartPoint( + ON_3dPoint start_point + ); + + // virtual ON_Curve::SetEndPoint override + bool SetEndPoint( + ON_3dPoint end_point + ); + */ + + + ///////////////////////////////////////////////////////////////// + // Implementation + + /* + Returns: + brep.m_C3[] index of the 3d curve geometry used by this edge + or -1. + */ + int EdgeCurveIndexOf() const; + + /* + Returns: + 3d curve geometry used by this edge or nullptr. + */ + const ON_Curve* EdgeCurveOf() const; + + /* + Description: + Expert user tool that replaces the 3d curve geometry + of an edge + Parameters; + c3i - [in] brep 3d curve index of new curve + Returns: + True if successful. + Example: + + ON_Curve* pCurve = ...; + int c3i = brep.AddEdgeCurve(pCurve); + edge.ChangeEdgeCurve(c3i); + + Remarks: + Sets m_c3i, calls SetProxyCurve, cleans runtime caches. + */ + bool ChangeEdgeCurve( + int c3i + ); + + /* + Description: + When an edge is modified, the m_pline[].e values need + to be set to ON_UNSET_VALUE by calling UnsetPlineEdgeParameters(). + */ + void UnsetPlineEdgeParameters(); + + + // index of 3d curve in m_C3[] array + // (edge.m_curve also points to m_C3[m_c3i]) + int m_c3i = -1; + + // indices of starting/ending vertex + // + // For closed edges, m_vi[0] = m_vi[1] and m_edge_index + // appears twice in the m_V[m_vi[0]].m_ei[] array. + // The first occurrence of m_edge_index in m_V[m_vi[0]].m_ei[] + // is for the closed edge starting the vertex. The second + // occurrence of m_edge_index in m_V[m_vi[0]].m_ei[] + // is for the closed edge edge ending at the vertex. + // C.f. ON_Brep::Next/PrevEdge(). + int m_vi[2]; + + // indices of Trims that use this edge + ON_SimpleArray m_ti; + + // accuracy of edge curve (>=0.0 or ON_UNSET_VALUE) + // + // A value of ON_UNSET_VALUE indicates that the + // tolerance should be computed. + // + // The maximum distance from the edge's 3d curve + // to any surface of a face that has this edge as + // a portion of its boundary must be <= this + // tolerance. + double m_tolerance = ON_UNSET_VALUE; + +private: + friend class ON_Brep; + ON_Brep* m_brep = nullptr; // so isolated edge class edge can get at it's 3d curve + ON_BrepEdge( const ON_BrepEdge& ) = delete; +}; + +#pragma ON_PRAGMA_WARNING_POP + +struct ON_BrepTrimPoint +{ + ON_2dPoint p; // 2d surface parameter space point + double t; // corresponding trim curve parameter + double e; // corresponding edge curve parameter (ON_UNSET_VALUE if unknown) +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +#endif + + +/* +Description: + Brep trim information is stored in ON_BrepTrim classes. + ON_Brep.m_T[] is an array of all the trim in the brep. + + An ON_BrepTrim is derived from ON_CurveProxy so the the + trim can supply easy to use evaluation tools via + the ON_Curve virtual member functions. + + Note well that the domains and orientations of the curve + m_C2[trim.m_c2i] and the trim as a curve may not + agree. +*/ +class ON_CLASS ON_BrepTrim : public ON_CurveProxy +{ + ON_OBJECT_DECLARE(ON_BrepTrim); + +public: + void DestroyRuntimeCache( bool bDelete = true ) override; + + // virtual ON_Object::SizeOf override + unsigned int SizeOf() const override; + + // Union available for application use. + // The constructor zeros m_trim_user. + // The value is of m_trim_user is not saved in 3DM + // archives and may be changed by some computations. + mutable ON_U m_trim_user; + +public: + mutable ON_ComponentStatus m_status = ON_ComponentStatus::NoneSet; + +private: + ON__UINT16 m_reserved1 = 0U; + +public: + int m_trim_index = -1; // index of trim in ON_Brep.m_T[] array + + // types of trim - access through m_type member. Also see m_iso and ON_Surface::ISO + enum TYPE + { + unknown = 0, + boundary = 1, // trim is connected to an edge, is part of an outer, + // inner or slit loop, and is the only trim connected + // to the edge. + mated = 2, // trim is connected to an edge, is part of an outer, + // inner or slit loop, no other trim from the same + // loop is connected to the edge, and at least one + // trim from a different loop is connected to the edge. + seam = 3, // trim is connected to an edge, is part of an outer, + // inner or slit loop, and one other trim from the + // same loop is connected to the edge. + // (There can be other mated trims that are also + // connected to the edge. For example, the non-manifold + // edge that results when a surface edge lies in the + // middle of another surface.) Non-manifold "cuts" + // have seam trims too. + singular = 4, // trim is part of an outer loop, the trim's 2d curve + // runs along the singular side of a surface, and the + // trim is NOT connected to an edge. (There is no 3d + // edge because the surface side is singular.) + crvonsrf = 5, // trim is connected to an edge, is the only trim in + // a crfonsrf loop, and is the only trim connected to + // the edge. + ptonsrf = 6, // trim is a point on a surface, trim.m_pbox is records + // surface parameters, and is the only trim + // in a ptonsrf loop. This trim is not connected + // to an edge and has no 2d curve. + slit = 7, // 17 Nov 2006 - reserved for future use + // currently an invalid value + trim_type_count = 8, + force_32_bit_trim_type = 0xFFFFFFFF + }; + + ///////////////////////////////////////////////////////////////// + // Construction + // + // In general, you should not directly create ON_BrepTrim classes. + // Use ON_Brep::NewTrim instead. + ON_BrepTrim(); + ON_BrepTrim(int); // trim index + ON_BrepTrim& operator=(const ON_BrepTrim&); + + /* + Returns: + Brep that this trim belongs to. + */ + ON_Brep* Brep() const; + + /* + Returns: + Brep loop that this trim belongs to. + */ + ON_BrepLoop* Loop() const; + + /* + Returns: + Brep face this trim belongs to. + */ + ON_BrepFace* Face() const; + + /* + Returns: + Brep edge this trim uses or belongs to. This will + be nullptr for singular trims. + */ + ON_BrepEdge* Edge() const; + + /* + Parameters: + tvi - [in] 0 or 1 + Returns: + Brep vertex at specified end of the trim. + */ + ON_BrepVertex* Vertex(int tvi) const; + + ///////////////////////////////////////////////////////////////// + // ON_Object overrides + // + // (Trims are purely topological - geometry queries should be + // directed at the trim's 2d curve or the trim's edge's 3d curve.) + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + void Dump( ON_TextLog& ) const override; // for debugging + + bool Write( ON_BinaryArchive& ) const override; + + bool Read( ON_BinaryArchive& ) override; + + // virtual ON_Geometry::ComponentIndex() override + ON_COMPONENT_INDEX ComponentIndex() const override; + + // virtual ON_Curve::Reverse override + // Reverses curve - caller must make sure trim's m_bRev3d + // flags are properly updated. Use + // ON_Brep::FlipTrim to reverse and trim and update all + // m_bRev3d information. + bool Reverse() override; + + /* Not necessary Base class does the same. + // virtual ON_Curve::SetStartPoint override + bool SetStartPoint( + ON_3dPoint start_point + ) override; + + // virtual ON_Curve::SetEndPoint override + bool SetEndPoint( + ON_3dPoint end_point + ) override; +*/ + ///////////////////////////////////////////////////////////////// + // Interface + + /* + Description: + Expert user tool that replaces the 2d curve geometry + of a trim + Parameters; + c2i - [in] brep 2d curve index of new curve + Returns: + True if successful. + Example: + + ON_Curve* pCurve = ...; + int c2i = brep.AddTrimCurve(pCurve); + trim.ChangeTrimCurve(c2i); + + Remarks: + Sets m_c2i, calls SetProxyCurve, cleans runtime caches, + and updates m_pbox. + */ + bool ChangeTrimCurve( int c2i ); + + /* + Description: + Destroy parameter space information. + Currently, this involves destroying m_pline + and m_pbox. Parameter space information should + be destroyed when the location of a trim + curve is changed. + */ + void DestroyPspaceInformation(); + + /* + Description: + Expert user function. + Removes a trim from an edge. + Parameters: + bRemoveFromStartVertex - [in] if true, the trim + is removed from its start vertex by setting + m_vi[0] to -1. + bRemoveFromEndVertex - [in] if true, the trim + is removed from its start vertex by setting + m_vi[1] to -1. + Remarks: + If the trim is attached to an edge (m_ei>=0), then + the trim is removed from the edge and the edge's + m_ti[] list. The trim's m_bRev3d and tolerance values + are not changed. + */ + bool RemoveFromEdge( + bool bRemoveFromStartVertex, + bool bRemoveFromEndVertex + ); + + /* + Description: + Expert user function. + Attaches a trim to an edge. + Parameters: + edge_index - [in] index of an edge. + bRev3d - [in] value for trim's m_bRev3d field. + Remarks: + If the trim is attached to an edge (m_ei>=0), then + the trim is removed from the edge and the edge's + m_ti[] list. The trim's tolerance values are not + changed. + */ + bool AttachToEdge( + int edge_index, + bool bRev3d + ); + + /* + Returns: + 2d curve geometry used by this trim or nullptr + */ + const ON_Curve* TrimCurveOf() const; + + /* + Returns: + 3d curve geometry used by this trim or nullptr. + */ + const ON_Curve* EdgeCurveOf() const; + + /* + Returns: + 3d surface geometry used by this trim or nullptr + */ + const ON_Surface* SurfaceOf() const; + + /* + Returns: + brep.m_C2[] 2d curve index of the 2d curve geometry used by + this trim or -1. + */ + int TrimCurveIndexOf() const; + + /* + Returns: + brep.m_C3[] 3d curve index of the 3d curve geometry used by + this trim or -1. + */ + int EdgeCurveIndexOf() const; + + /* + Returns: + brep.m_S[] surface index of the 3d surface geometry used by + this trim or -1. + */ + int SurfaceIndexOf() const; + + /* + Returns: + brep.m_F[] face index of the face used by this trim or -1. + */ + int FaceIndexOf() const; + + /* + Returns: + True if the trim satisfies these four criteria. + 1) is part of a loop + 2) is connected to a 3d edge + 3) one other trim from the same loop is connected to the edge + 4) The 2d trim curve for the other trim is the reverse + of the 2d trim curve for this trim. + Remarks: + In order for IsSlit() to work correctly, the m_type and m_iso + fields must be set correctly. In V4 SR1, this function will + be removed and ON_BrepTrim::slit will be added as a type. + */ + bool IsSlit() const; + + /* + Returns: + True if the trim satisfies these four criteria. + 1) is part of a loop + 2) is connected to a 3d edge + 3) one other trim from the same loop is connected to the edge + 4) the 2d trim curve for this trim lies along the side of + the face's parameter space and the 2d curve for the other + trim lies on the opposite side of the face's parameter + space. + Remarks: + In order for IsSeam() to work correctly, the m_type and m_iso + fields must be set correctly. In V4 SR1, this function will + be removed and ON_BrepTrim::slit will be added as a type. + */ + bool IsSeam() const; + + /* + Description: + Expert user tool that transforms all the parameter space (2d) + trimming curves in this loop. Only 2d curve geometry is + changed. The caller is responsible for reversing loops, + toggle m_bRev, flags, etc. + Parameters: + xform - [in] Transformation applied to 2d curve geometry. + Returns + True if successful. If false is returned, the brep + may be invalid. + */ + bool TransformTrim( const ON_Xform& xform ); + + // index of the 2d parameter space trimming curve + int m_c2i = -1; + + // index of 3d edge (-1 if ON_BrepTrim is singular) + int m_ei = -1; + + // Indices of start/end vertices. Trims along singular + // sides and trims that correspond to closed 3d edges + // have m_vi[0] = m_vi[1]. Note that singular trims + // and trims on the closed edge of a closed surface can + // have an open 2d trimming curve and still have + // m_vi[0] = m_vi[1]. + int m_vi[2]; + + // true if the 2d trim and 3d edge have opposite orientations. + bool m_bRev3d = false; + + TYPE m_type = ON_BrepTrim::unknown; + ON_Surface::ISO m_iso = ON_Surface::not_iso; + + // index of loop that uses this trim + int m_li = -1; + + // The values in m_tolerance[] record the accuracy of + // the parameter space trimming curves. + // + // Remarks: + // m_tolerance[0] = accuracy of parameter space curve + // in first ( "u" ) parameter + // + // m_tolerance[1] = accuracy of parameter space curve + // in second ( "v" ) parameter + // + // A value of ON_UNSET_VALUE indicates that the + // tolerance should be computed. If the value >= 0.0, + // then the tolerance is set. If the value is + // ON_UNSET_VALUE, then the tolerance needs to be + // computed. + // + // If the trim is not singular, then the trim must + // have an edge. If P is a 3d point on the edge's + // curve and surface(u,v) = Q is the point on the + // surface that is closest to P, then there must + // be a parameter t in the interval [m_t[0], m_t[1]] + // such that + // + // |u - curve2d(t)[0]| <= m_tolerance[0] + // + // and + // + // |v - curve2d(t)[1]| <= m_tolerance[1] + // + // If P is the 3d point for the vertex brep.m_V[m_vi[k]] + // and (uk,vk) is the corresponding end of the trim's + // parameter space curve, then there must be a surface + // parameter (u,v) such that: + // + // * the distance from the 3d point surface(u,v) to P + // is <= brep.m_V[m_vi[k]].m_tolerance, + // * |u-uk| <= m_tolerance[0]. + // * |v-vk| <= m_tolerance[1]. + double m_tolerance[2]; + + // Runtime polyline approximation of trimming curve. + // This information is not saved in 3DM archives. + ON_SimpleArray m_pline; + + /* + Description: + When an edge is modified, the m_pline[].e values need + to be set to ON_UNSET_VALUE by calling UnsetPlineEdgeParameters(). + */ + void UnsetPlineEdgeParameters(); + + // Runtime parameter space trimming curve bounding box. + // This information is not saved in 3DM archives. + ON_BoundingBox m_pbox; + +public: + // values stored in legacy file formats - ignore + + void m__legacy_flags_Set(int,int); // used internally - ignore + bool m__legacy_flags_Get(int*,int*) const; // used internally - ignore + double m__legacy_2d_tol = ON_UNSET_VALUE; // used internally - ignore + double m__legacy_3d_tol = ON_UNSET_VALUE; // used internally - ignore + int m__legacy_flags = 0; // used internally - ignore + +private: + friend class ON_Brep; + ON_Brep* m_brep = nullptr; // so isolated edge class edge can get at it's 3d curve + ON_BrepTrim( const ON_BrepTrim& ) = delete; +}; + +class ON_CLASS ON_BrepLoop : public ON_Geometry +{ + ON_OBJECT_DECLARE(ON_BrepLoop); + +public: + void DestroyRuntimeCache( bool bDelete = true ) override; + + // virtual ON_Geometry overrides + // A loop is derived from ON_Geometry so that is can + // be passed around to things that expect ON_Geometry + // pointers. It is not a very useful stand-alone object. + + /* + Description: + virtual ON_Geometry::Dimension() override. + Returns: + 2 + */ + int Dimension() const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + // virtual ON_Geometry::Transform() override. + bool Transform( + const ON_Xform& xform + ) override; +public: + /* + Returns: + Brep that the loop belongs to. + */ + ON_Brep* Brep() const; + + /* + Returns: + Brep face this loop belongs to. + */ + ON_BrepFace* Face() const; + + /* + Parameters: + lti - [in] index into the loop's m_ti[] array. + Returns: + The trim brep.m_T[loop.m_ti[lti]]; + */ + ON_BrepTrim* Trim( int lti ) const; + + /* + Returns: + Number of trims in this loop. + */ + int TrimCount() const; + + // Union available for application use. + // The constructor zeros m_loop_user. + // The value is of m_loop_user is not saved in 3DM + // archives and may be changed by some computations. + mutable ON_U m_loop_user; + +public: + mutable ON_ComponentStatus m_status = ON_ComponentStatus::NoneSet; + +private: + ON__UINT16 m_reserved1 = 0U; + +public: + int m_loop_index = -1; // index of loop in ON_Brep.m_L[] array + + enum TYPE { + unknown = 0, + outer = 1, // 2d loop curves form a simple closed curve with a counterclockwise orientation + inner = 2, // 2d loop curves form a simple closed curve with a clockwise orientation + slit = 3, // always closed - used internally during splitting operations + crvonsrf = 4, // "loop" is a curveonsrf made from a single + // (open or closed) trim that is has type ON_BrepTrim::crvonsrf. + ptonsrf = 5, // "loop" is a ptonsrf made from a single + // trim that is has type ON_BrepTrim::ptonsrf. + type_count = 6 + }; + + ON_BrepLoop(); + ON_BrepLoop(int); // loop index + ON_BrepLoop& operator=(const ON_BrepLoop&); + + ///////////////////////////////////////////////////////////////// + // ON_Object overrides + // + // (Loops and trims are purely topological - geometry queries should be + // directed at the trim's 2d curve or the trim's edge's 3d curve.) + + // virtual ON_Object::SizeOf override + unsigned int SizeOf() const override; + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + void Dump( ON_TextLog& ) const override; // for debugging + + bool Write( ON_BinaryArchive& ) const override; + + bool Read( ON_BinaryArchive& ) override; + + // virtual ON_Geometry::ComponentIndex() override + ON_COMPONENT_INDEX ComponentIndex() const override; + + ///////////////////////////////////////////////////////////////// + // Interface + + ////////// + // Returns the index i such that loop.m_ti[i] = trim.m_trim_index. + // Returns -1 if the trim is not in this loop + int IndexOfTrim( const ON_BrepTrim& ) const; + + /* + Returns: + brep.m_S[] surface index of the 3d surface geometry used by + this loop or -1. + */ + int SurfaceIndexOf() const; + + /* + Returns: + Pointer to the surface geometry used by the loop. + */ + const ON_Surface* SurfaceOf() const; + + /* + Description: + Expert user tool that transforms all the parameter space (2d) + trimming curves in this loop. Only 2d curve geometry is + changed. The caller is responsible for reversing loops, + toggle m_bRev, flags, etc. + Parameters: + xform - [in] Transformation applied to 2d curve geometry. + Returns + True if successful. If false is returned, the brep + may be invalid. + */ + bool TransformTrim( const ON_Xform& xform ); + + ON_SimpleArray m_ti; // trim indices + TYPE m_type = ON_BrepLoop::unknown; + int m_fi = -1; // index of face that uses this loop + + ////////// + // parameter space trimming loop bounding box + // runtime information - not saved + ON_BoundingBox m_pbox; +private: + friend class ON_Brep; + ON_Brep* m_brep = nullptr; + ON_BrepLoop(const ON_BrepLoop&) = delete; +}; + + +class ON_CLASS ON_BrepFace : public ON_SurfaceProxy +{ + ON_OBJECT_DECLARE(ON_BrepFace); + +public: + void DestroyRuntimeCache( bool bDelete = true ) override; + + // Union available for application use. + // The constructor zeros m_face_user. + // The value is of m_face_user is not saved in 3DM + // archives and may be changed by some computations. + mutable ON_U m_face_user; + +public: + mutable ON_ComponentStatus m_status = ON_ComponentStatus::NoneSet; + +private: + // the 4 byte pack id is stored as 2 ON__UINT16 values to prevent breaking the C++ SDK. + ON__UINT16 m_pack_id_low = 0; // PackId() = 0x10000*m_pack_id_high + m_pack_id_low; + +public: + int m_face_index = -1; // index of face in ON_Brep.m_F[] array + + ON_BrepFace(); + ~ON_BrepFace(); + ON_BrepFace(int); + ON_BrepFace& operator=(const ON_BrepFace&); + + /* + Returns: + Brep that the face belongs to. + */ + ON_Brep* Brep() const; + + /* + Parameters: + fli - [in] index into the face's m_li[] array. + Returns: + The loop brep.m_L[face.m_li[fli]]; + */ + ON_BrepLoop* Loop( int fli ) const; + + /* + Returns: + Number of loops in this face. + */ + int LoopCount() const; + + /* + Returns: + Outer boundary loop for this face. + */ + ON_BrepLoop* OuterLoop() const; + + /* + Parameters: + dir + 1: side with underlying surface normal + pointing into the topology region + -1: side with underlying surface normal + pointing out of the topology region + Returns: + Brep region topology face side. If the region + topology has not be created by calling + ON_Brep::RegionToplogy(), then nullptr is returned. + */ + class ON_BrepFaceSide* FaceSide(int dir) const; + + + ///////////////////////////////////////////////////////////////// + // ON_Object overrides + // + // (Faces are purely topological - geometry queries should be + // directed at the face's 3d surface.) + + // virtual ON_Object::SizeOf override + unsigned int SizeOf() const override; + + // virtual ON_Object::DataCRC override + ON__UINT32 DataCRC(ON__UINT32 current_remainder) const override; + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + void Dump( ON_TextLog& ) const override; // for debugging + + bool Write( ON_BinaryArchive& ) const override; + + bool Read( ON_BinaryArchive& ) override; + + // virtual ON_Geometry::ComponentIndex() override + ON_COMPONENT_INDEX ComponentIndex() const override; + + // virtual ON_Geometry::ClearBoundingBox() override + void ClearBoundingBox() override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + + /* + Description: + This is an override of the virtual ON_Surface::Reverse + function. It toggles the face's m_bRev flag so the abstract + orientation of the face does not change. + Parameters: + dir - [in] 0 = reverse "s" parameter, 1 = reverse "t" parameter + The domain changes from [a,b] to [-a,-b] + Returns: + True if successful. + Remarks: + The range of the face's trimming curves and the orientation direction + of then loops are changed so that the resulting face is still valid. + */ + bool Reverse( + int dir + ) override; + + /* + Description: + This is an override of the virtual ON_Surface::Transpose + function. It toggles the face's m_bRev flag so the abstract + orientation of the face does not change. + Returns: + True if successful. + Remarks: + The range of the face's trimming curves and the orientation direction + of then loops are changed so that the resulting face is still valid. + */ + bool Transpose() override; + + /* + Description: + This is an override of the virtual ON_Surface::SetDomain + function. + Parameters: + dir - [in] 0 = set "u" domain, 1 = set "v" domain. + t0 - [in] + t1 - [in] t0 < t1 The new domain is the interval (t0,t1) + Returns: + True if successful. + */ + bool SetDomain( + int dir, + double t0, + double t1 + ) override; + + /* + ////////// + // Change the domain of a face + // This changes the parameterization of the face's surface and transforms + // the "u" and "v" coordinates of all the face's parameter space trimming + // curves. The locus of the face is not changed. + */ + bool SetDomain( + ON_Interval udom, + ON_Interval vdom + ); + + ///////////////////////////////////////////////////////////////// + // Rendering Interface + //int MaterialIndex() const; // if -1, use parent's material definition + //void SetMaterialIndex(int); + + // If true is returned, then ~ON_BrepFace will delete mesh. + bool SetMesh( ON::mesh_type, ON_Mesh* mesh ); + + const ON_Mesh* Mesh( ON::mesh_type mesh_type ) const; + + /* + Description: + Destroy meshes used to render and analyze surface and polysurface objects. + Parameters: + mesh_type - [in] type of mesh to destroy + bDeleteMesh - [in] if true, cached mesh is deleted. + If false, pointer to cached mesh is just set to nullptr. + See Also: + CRhinoObject::GetMeshes + CRhinoObject::MeshCount + CRhinoObject::IsMeshable + */ + void DestroyMesh( ON::mesh_type mesh_type, bool bDeleteMesh = true ); + + ///////////////////////////////////////////////////////////////// + // "Expert" Interface + + /* + Description: + Expert user tool that transforms all the parameter space (2d) + trimming curves on this face. Only 2d curve geometry is + changed. The caller is responsible for reversing loops, + toggle m_bRev, flags, etc. + Parameters: + xform - [in] Transformation applied to 2d curve geometry. + Returns + True if successful. If false is returned, the brep + may be invalid. + */ + bool TransformTrim( const ON_Xform& xform ); + + + /* + Returns: + brep.m_S[] surface index of the 3d surface geometry used by + this face or -1. + */ + int SurfaceIndexOf() const; + + /* + Returns: + Pointer to the surface geometry used by the face. + */ + const ON_Surface* SurfaceOf() const; + + + + ON_SimpleArray m_li; // loop indices (outer loop is m_li[0]) + int m_si = -1; // index of surface in b-rep m_S[] array + bool m_bRev = false; // true if face orientation is opposite + // of natural surface orientation + + + /* + Returns: + 0: unset pack id. + > 0: set pack id. + Remarks: + PackId values assigned to brep faces are inheritied from the PackId values + assigned to subd faces when a subd is converted into a brep. + These faces are "trivially trimmed" which means the boundary of the face + is identical to the boundary of the underlying surface. + There are two types of face packs in a subd, quad grid packs and singleton packs. + A subd quad grid pack is a set of subd quads that form a rectangular grid. + A subd singleton pack is a single face, quad or n-gon, that is not part of + a quad grid pack. + There are three types of face packs in a brep created from a subd, + grid packs, star packs and singleton packs. + A brep "grid pack" comes from a rectangular grid of subd quads. A grid pack of brep faces can + be converted into a single larger trivially trimmed brep face. + A brep "star pack" of brep faces comes from a singel subd n-gon (n = 3, 5 or more). The star pack + will have n faces with a star center vertex and shared edges radiating from the star center. + A brep "singleton" pack comes from a single subd quad that could not be grouped into a larger + subd quad grid pack. + */ + unsigned int PackId() const; + + /* + Description: + Sets PackId() to zero. + */ + void ClearPackId(); + + /* + Description: + Used by ON_SubD functions that create breps to transmit the subd face ON_SubDFace.PackId() value + to the brep face or faces generated from the subd face. + Unless you are an expert and doing something very carefully and very fancy, to not call this function. + Remarks: + PackId values assigned to brep faces are inheritied from the PackId values + assigned to subd faces when a subd is converted into a brep. + These faces are "trivially trimmed" which means the boundary of the face + is identical to the boundary of the underlying surface. + There are two types of face packs in a subd, quad grid packs and singleton packs. + A subd quad grid pack is a set of subd quads that form a rectangular grid. + A subd singleton pack is a single face, quad or n-gon, that is not part of + a quad grid pack. + There are three types of face packs in a brep created from a subd, + grid packs, star packs and singleton packs. + A brep "grid pack" comes from a rectangular grid of subd quads. A grid pack of brep faces can + be converted into a single larger trivially trimmed brep face. + A brep "star pack" of brep faces comes from a singel subd n-gon (n = 3, 5 or more). The star pack + will have n faces with a star center vertex and shared edges radiating from the star center. + A brep "singleton" pack comes from a single subd quad that could not be grouped into a larger + subd quad grid pack. + */ + void SetPackIdForExperts( + unsigned int pack_id + ); + +private: + ON__UINT8 m_reserved2 = 0; + +private: + // the 4 byte pack id is stored as 2 ON__UINT16 values to prevent breaking the C++ SDK. + ON__UINT16 m_pack_id_high = 0; // PackId() = 0x10000*m_pack_id_high + m_pack_id_low; + +public: + // The application specifies a base ON_Material used to render the brep this face belongs to. + // If m_material_channel_index > 0 AND face_material_id = base.MaterialChannelIdFromIndex(m_material_channel_index) + // is not nil, then face_material_id identifies an override rendering material for this face. + // Otherwise base will be used to render this face. + int m_face_material_channel = 0; + +public: + /* + Description: + Set this face's rendering material channel index. + + Parameters: + material_channel_index - [in] + A value between 0 and ON_Material::MaximumMaterialChannelIndex, inclusive. + This value is typically 0 or the value returned from ON_Material::MaterialChannelIndexFromId(). + + Remarks: + If base_material is the ON_Material assigned to render this brep and + ON_UUID face_material_id = base_material.MaterialChannelIdFromIndex( material_channel_index ) + is not nil, then face_material_id identifies an override rendering material for this face. + Otherwise base_material is used to render this face. + */ + void SetMaterialChannelIndex(int material_channel_index) const; + + /* + Description: + Remove per face rendering material channel index setting. The face will use the material assigned to the brep object. + */ + void ClearMaterialChannelIndex() const; + + /* + Returns: + This face's rendering material channel index. + + Remarks: + If base_material is the ON_Material assigned to render this subd, MaterialChannelIndex() > 0, + and ON_UUID face_material_id = base_material.MaterialChannelIdFromIndex( face.MaterialChannelIndex() ) + is not nil, then face_material_id identifies an override rendering material for this face. + Otherwise base_material is used to render this face. + */ + int MaterialChannelIndex() const; + + /* + Description: + Set per face color. + + Parameters: + color - [in] + */ + void SetPerFaceColor( + ON_Color color + ) const; + + /* + Description: + Remove per face color setting. The face will use the color assigned to the brep object. + */ + void ClearPerFaceColor() const; + + /* + Returns: + Per face color. A value of ON_Color::UnsetColor indicates the face uses the color assigned to the brep object. + */ + const ON_Color PerFaceColor() const; + +public: + + // Persistent id for this face. Default is ON_nil_uuid. + ON_UUID m_face_uuid = ON_nil_uuid; + +private: + // RH-37306 + // 30 Mar 2020: Space reserved for future implementation. + mutable ON_Color m_per_face_color = ON_Color::UnsetColor; + +private: + ON_BoundingBox m_bbox; // 3d bounding box (should be declared mutable and const_cast<> is used to make it fake mutable) + ON_Interval m_domain[2]; // rectangular bounds of 2d curves + ON_Mesh* m_render_mesh = nullptr; + ON_Mesh* m_analysis_mesh = nullptr; + ON_Mesh* m_preview_mesh = nullptr; + //int m_material_index; // if 0 (default), ON_Brep's object attributes + // // determine material. +private: + friend class ON_Brep; + ON_Brep* m_brep = nullptr; + ON_BrepFace( const ON_BrepFace& ) = delete; + +private: + /* + Parameters: + bLazy - [in] + If true and if ON_BrepFace.m_bbox is not empty, then ON_BrepFace.m_bbox is returned. + In all other cases the bbox is calculated from scratch. + bUpdateCachedBBox - [in] + If true and the bounding box is calculated, then the value is saved in ON_BrepFace.m_bbox + so future lazy evaluations can use the value. + */ + const ON_BoundingBox InternalFaceBoundingBox(bool bLazy, bool bUpdateCachedBBox) const; +}; + +class ON_CLASS ON_BrepFaceSide : public ON_Object +{ + ON_OBJECT_DECLARE(ON_BrepFaceSide); +public: + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + // Union available for application use. + // The constructor zeros m_faceside_user. + // The value is of m_faceside_user is not saved in 3DM + // archives and may be changed by some computations. + mutable ON_U m_faceside_user; + + // index of face side in ON_BrepRegionTopology.m_FS[] array + int m_faceside_index; + + ON_BrepFaceSide(); + ~ON_BrepFaceSide(); + ON_BrepFaceSide& operator=(const ON_BrepFaceSide&); + + bool Write(ON_BinaryArchive& binary_archive) const override; + bool Read(ON_BinaryArchive& binary_archive) override; + + + /* + Returns: + Brep this face side belongs to. + */ + const class ON_Brep* Brep() const; + + /* + Returns: + Region topology this face side belongs to. + */ + const class ON_BrepRegionTopology* RegionTopology() const; + + /* + Returns: + Region the face side belongs to. + */ + const class ON_BrepRegion* Region() const; + + /* + Returns: + Face this side belongs to. + */ + const class ON_BrepFace* Face() const; + + /* + Returns: + +1: underlying geometric surface normal points + into region. + -1: underlying geometric surface normal points + out of region. + */ + int SurfaceNormalDirection() const; + +public: + int m_ri; // region index + // m_ri = -1 indicates this face side overlaps + // another face side. Generally this is a flaw + // in an ON_Brep. + int m_fi; // face index + int m_srf_dir; // 1 ON_BrepFace's surface normal points into region + // -1 ON_BrepFace's surface normal points out of region + +private: + friend class ON_Brep; + friend class ON_BrepRegionTopology; + ON_BrepRegionTopology* m_rtop; + ON_BrepFaceSide( const ON_BrepFaceSide& ); +}; + +class ON_CLASS ON_BrepRegion : public ON_Object +{ + ON_OBJECT_DECLARE(ON_BrepRegion); +public: + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + // Union available for application use. + // The constructor zeros m_region_user. + // The value is of m_region_user is not saved in 3DM + // archives and may be changed by some computations. + mutable ON_U m_region_user; + + // index of region in ON_BrepRegionTopology.m_R[] array + int m_region_index; + + ON_BrepRegion(); + ~ON_BrepRegion(); + ON_BrepRegion& operator=(const ON_BrepRegion&); + + bool Write(ON_BinaryArchive& binary_archive) const override; + bool Read(ON_BinaryArchive& binary_archive) override; + + /* + Returns: + Brep this region belongs to. + */ + const ON_Brep* Brep() const; + + /* + Returns: + Region topology this region belongs to. + */ + class ON_BrepRegionTopology* RegionTopology() const; + + /* + Parameter: + rfsi - [in] index into the region's m_fsi[] array. + Returns: + The face side in rtop.m_FS[m_fsi[rsi]], where + rtop is the ON_BrepRegionTopology class this + region belongs to. + */ + ON_BrepFaceSide* FaceSide(int rfsi) const; + + /* + Returns: + True if the region is finite. + */ + bool IsFinite() const; + + /* + Returns: + Region bounding box. + */ + const ON_BoundingBox& BoundingBox() const; + + ON_SimpleArray m_fsi; // indices of face sides + int m_type; // 0 = infinite, 1 = bounded + ON_BoundingBox m_bbox; + + /* + Description: + Get the boundary of a region as a brep object. + If the region is finite, the boundary will be a closed + manifold brep. The boundary may have more than one + connected component. + Parameters: + brep - [in] if not nullptr, the brep form is put into + this brep. + Returns: the region boundary as a brep or nullptr if the + calculation fails. + */ + ON_Brep* RegionBoundaryBrep( ON_Brep* brep = nullptr ) const; + + +private: + friend class ON_Brep; + friend class ON_BrepRegionTopology; + ON_BrepRegionTopology* m_rtop; + ON_BrepRegion( const ON_BrepRegion& ); +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray; +#endif + +class ON_CLASS ON_BrepVertexArray : public ON_ObjectArray +{ +public: + ON_BrepVertexArray(); + ~ON_BrepVertexArray(); + + bool Read( ON_BinaryArchive& ); + bool Write( ON_BinaryArchive& ) const; + + unsigned int SizeOf() const; +}; + +class ON_CLASS ON_BrepEdgeArray : public ON_ObjectArray +{ +public: + ON_BrepEdgeArray(); + ~ON_BrepEdgeArray(); + bool Read( ON_BinaryArchive& ); + bool Write( ON_BinaryArchive& ) const; + + unsigned int SizeOf() const; +}; + +class ON_CLASS ON_BrepTrimArray : public ON_ObjectArray +{ +public: + ON_BrepTrimArray(); + ~ON_BrepTrimArray(); + bool Read( ON_BinaryArchive& ); + bool Write( ON_BinaryArchive& ) const; + + unsigned int SizeOf() const; +}; + +class ON_CLASS ON_BrepLoopArray : public ON_ObjectArray +{ +public: + ON_BrepLoopArray(); + ~ON_BrepLoopArray(); + bool Read( ON_BinaryArchive& ); + bool Write( ON_BinaryArchive& ) const; + + unsigned int SizeOf() const; +}; + +class ON_CLASS ON_BrepFaceArray : public ON_ObjectArray +{ +public: + ON_BrepFaceArray(); + ~ON_BrepFaceArray(); + bool Read( ON_BinaryArchive& ); + bool Write( ON_BinaryArchive& ) const; + + unsigned int SizeOf() const; +}; + +class ON_CLASS ON_BrepFaceSideArray : public ON_ObjectArray +{ +public: + ON_BrepFaceSideArray(); + ~ON_BrepFaceSideArray(); + + bool Read( ON_BinaryArchive& ); + bool Write( ON_BinaryArchive& ) const; + + unsigned int SizeOf() const; + +private: + bool Internal_ReadV5( ON_BinaryArchive& ); + bool Internal_ReadV6( ON_BinaryArchive& ); + + bool Internal_WriteV5( ON_BinaryArchive& ) const; + bool Internal_WriteV6( ON_BinaryArchive& ) const; +}; + +class ON_CLASS ON_BrepRegionArray : public ON_ObjectArray +{ +public: + ON_BrepRegionArray(); + ~ON_BrepRegionArray(); + + bool Read( ON_BinaryArchive& ); + bool Write( ON_BinaryArchive& ) const; + + unsigned int SizeOf() const; + +private: + bool Internal_ReadV5( ON_BinaryArchive& ); + bool Internal_ReadV6( ON_BinaryArchive& ); + + bool Internal_WriteV5( ON_BinaryArchive& ) const; + bool Internal_WriteV6( ON_BinaryArchive& ) const; +}; + +class ON_CLASS ON_BrepRegionTopology +{ +public: + ON_BrepRegionTopology(); + ON_BrepRegionTopology(const ON_BrepRegionTopology& src); + ~ON_BrepRegionTopology(); + ON_BrepRegionTopology& operator=(const ON_BrepRegionTopology&); + + ON_BrepFaceSideArray m_FS; + ON_BrepRegionArray m_R; + + + const ON_Brep* Brep() const; + bool IsValid( ON_TextLog* text_log = 0 ) const; + bool Read( ON_BinaryArchive& ); + bool Write( ON_BinaryArchive& ) const; + + unsigned int SizeOf() const; + + bool Transform( + const ON_Xform& xform + ); + + +private: + friend class ON_V5_BrepRegionTopologyUserData; + friend class ON_Brep; + const ON_Brep* m_brep = nullptr; +}; + +class ON_CLASS ON_Brep : public ON_Geometry +{ + ON_OBJECT_DECLARE(ON_Brep); + +public: + + ///////////////////////////////////////////////////////////////// + // + // Component status interface + // + // + + //virtual + unsigned int ClearComponentStates( + ON_ComponentStatus states_to_clear + ) const override; + + //virtual + unsigned int GetComponentsWithSetStates( + ON_ComponentStatus states_filter, + bool bAllEqualStates, + ON_SimpleArray< ON_COMPONENT_INDEX >& components + ) const override; + + //virtual + unsigned int SetComponentStates( + ON_COMPONENT_INDEX component_index, + ON_ComponentStatus states_to_set + ) const override; + + //virtual + unsigned int ClearComponentStates( + ON_COMPONENT_INDEX component_index, + ON_ComponentStatus states_to_clear + ) const override; + + //virtual + unsigned int SetComponentStatus( + ON_COMPONENT_INDEX component_index, + ON_ComponentStatus status_to_copy + ) const override; + + //virtual + ON_AggregateComponentStatus AggregateComponentStatus() const override; + + //virtual + void MarkAggregateComponentStatusAsNotCurrent() const override; + + // virtual ON_Object::DestroyRuntimeCache override + void DestroyRuntimeCache( bool bDelete = true ) override; + + // virtual ON_Object::SizeOf override + unsigned int SizeOf() const override; + + // virtual ON_Object::DataCRC override + ON__UINT32 DataCRC(ON__UINT32 current_remainder) const override; + + // virtual ON_Geometry override + bool EvaluatePoint( const class ON_ObjRef& objref, ON_3dPoint& P ) const override; + +public: + + + /* + Description: + Use ON_Brep::New() instead of new ON_Brep() when writing + Rhino plug-ins (or when openNURBS is used as a Microsoft + DLL and you need to create a new ON_Brep in a different + .EXE or .DLL). + Example: + + // bad - ON_Brep* pBrep = new ON_Brep(); + ON_Brep* pBrep = ON_Brep::New(); // good + ... + delete pBrep; + pBrep = nullptr; + + Returns: + Pointer to an ON_Brep. Destroy by calling delete. + Remarks: + When openNURBS is used as a Microsoft DLL, the CL.EXE + compiler uses local vtables for classes that are new-ed + in other executables but uses the ordinary vtable for + for classes that are allocated in functions like + ON_BrepCylinder(), ON_NurbsSurfaceQuadrilateral(), + ON_Cylinder::RevSurfaceForm(nullptr), etc. + Using static New() functions like ON_Brep::New() insures + that identical classes has the same vtable and makes + all code run identically. + */ + static ON_Brep* New(); + + /* + Description: + Use ON_Brep::New(const ON_Brep& src) instead + of new ON_Brep(const ON_Brep& src). + Returns: + Pointer to an ON_Brep. Destroy by calling delete. + Remarks: + See static ON_Brep* ON_Brep::New() for details. + */ + static ON_Brep* New(const ON_Brep&); + + // Construction + ON_Brep(); + ~ON_Brep(); + ON_Brep(const ON_Brep&); + ON_Brep& operator=(const ON_Brep&); + + // Override of virtual ON_Object::MemoryRelocate + void MemoryRelocate() override; + + + /* + Description: + Does nothing. Will be deleted in next version. + */ + ON_DEPRECATED_MSG("Does nothing. Delete call.") + bool IsDuplicate( + const ON_Brep& other, + double tolerance = ON_ZERO_TOLERANCE + ) const; + + ///////////////////////////////////////////////////////////////// + // construction/destruction helpers + + // returns Brep to state it has after default construction + void Destroy(); + + // call if memory pool used by b-rep members becomes invalid + void EmergencyDestroy(); + + /* + Description: + Calculates polygon mesh approximation of the brep + and appends one mesh for each face to the mesh_list[] + array. + Parameters: + mp - [in] meshing parameters + mesh_list - [out] meshes are appended to this array. + Returns: + Number of meshes appended to mesh_list[] array. + */ + int CreateMesh( + const ON_MeshParameters& mp, + ON_SimpleArray& mesh_list + ) const; + + /* + Description: + Destroy meshes used to render and analyze brep. + Parameters: + mesh_type - [in] type of mesh to destroy + bDeleteMesh - [in] if true, cached meshes are deleted. + If false, pointers to cached meshes are just set to nullptr. + See Also: + ON_Brep::GetMesh + ON_BrepFace::DestroyMesh + ON_BrepFace::Mesh + ON_BrepFace::SetMesh + */ + void DestroyMesh( ON::mesh_type mesh_type, bool bDeleteMesh = true ); + + /* + Description: + Get cached meshes used to render and analyze brep. + Parameters: + mesh_type - [in] type of mesh to get + meshes - [out] meshes are appended to this array. The ON_Brep + owns these meshes so they cannot be modified. + Returns: + Number of meshes added to array. (Same as m_F.Count()) + See Also: + ON_Brep::DestroyMesh + ON_BrepFace::DestroyMesh + ON_BrepFace::Mesh + ON_BrepFace::SetMesh + */ + int GetMesh( ON::mesh_type mesh_type, ON_SimpleArray< const ON_Mesh* >& meshes ) const; + + + + /* + Description: + Create a brep from a surface. The resulting surface has an outer + boundary made from four trims. The trims are ordered so that + they run along the south, east, north, and then west side of the + surface's parameter space. + Parameters: + pSurface - [in] pointer to a surface. The brep will manage this + pointer and delete it in ~ON_Brep. + Returns: + @untitled table + true successful + When true is returned, the pSurface pointer is added to the + brep's m_S[] array and it will be deleted by the brep's + destructor. + false + brep cannot be created from this surface. + When false is returned, then the caller is responsible + for deleting pSurface unless it was previously added + to the brep's m_S[] array. + Remarks: + The surface class must be created with new so that the + delete in ~ON_Brep will not cause a crash. + */ + bool Create( + ON_Surface*& pSurface + ); + + bool Create( + ON_NurbsSurface*& pNurbsSurface + ); + + bool Create( + ON_PlaneSurface*& pPlaneSurface + ); + + bool Create( + ON_RevSurface*& pRevSurface + ); + + bool Create( + ON_SumSurface*& pSumSurface + ); + + /* + Description: + Check for corrupt data values that are likely to cause crashes. + Parameters: + bRepair - [in] + If true, const_cast<> will be used to change the corrupt data + so that crashes are less likely. + bSilentError - [in] + If true, ON_ERROR will not be called when corruption is detected. + text_log - [out] + If text_log is not null, then a description of corruption + is printed using text_log. + Remarks: + Ideally, IsCorrupt() would be a virtual function on ON_Object, + but doing that at this point would break the public SDK. + */ + bool IsCorrupt( + bool bRepair, + bool bSilentError, + class ON_TextLog* text_log + ) const; + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + /* + Description: + Tests the brep to see if its topology information is + valid. + Parameters: + text_log - [in] if the brep topology is not valid and + text_log is not nullptr, then a brief English + description of the problem is appended to the log. + The information appended to text_log is suitable for + low-level debugging purposes by programmers and is + not intended to be useful as a high level user + interface tool. + Returns: + @untitled table + true brep topology is valid + false brep topology is not valid + Remarks: + ON_Brep::IsValidTopology can be called at any time. + See Also: + ON_Brep::IsValid + ON_Brep::IsValidGeometry + ON_Brep::IsValidTolerancesAndFlags + */ + bool IsValidTopology( ON_TextLog* text_log = nullptr ) const; + + + /* + Description: + Expert user function that tests the brep to see if its + geometry information is valid. The value of + brep.IsValidTopology() must be true before + brep.IsValidGeometry() can be safely called. + Parameters: + text_log - [in] if the brep geometry is not valid and + text_log is not nullptr, then a brief English + description of the problem is appended to the log. + The information appended to text_log is suitable for + low-level debugging purposes by programmers and is + not intended to be useful as a high level user + interface tool. + Returns: + @untitled table + true brep geometry is valid + false brep geometry is not valid + Remarks: + ON_Brep::IsValidTopology must be true before you can + safely call ON_Brep::IsValidGeometry. + See Also: + ON_Brep::IsValid + ON_Brep::IsValidTopology + ON_Brep::IsValidTolerancesAndFlags + */ + bool IsValidGeometry( ON_TextLog* text_log = nullptr ) const; + + /* + Description: + Expert user function that tests the brep to see if its + tolerances and flags are valid. The values of + brep.IsValidTopology() and brep.IsValidGeometry() must + be true before brep.IsValidTolerancesAndFlags() can + be safely called. + Parameters: + text_log - [in] if the brep tolerance or flags are not + valid and text_log is not nullptr, then a brief English + description of the problem is appended to the log. + The information appended to text_log is suitable for + low-level debugging purposes by programmers and is + not intended to be useful as a high level user + interface tool. + Returns: + @untitled table + true brep tolerance and flags are valid + false brep tolerance and flags are not valid + Remarks: + ON_Brep::IsValidTopology and ON_Brep::IsValidGeometry + must be true before you can safely call + ON_Brep::IsValidTolerancesAndFlags. + See Also: + ON_Brep::IsValid + ON_Brep::IsValidTopology + ON_Brep::IsValidGeometry + */ + bool IsValidTolerancesAndFlags( ON_TextLog* text_log = nullptr ) const; + + // Description: + // Tests brep to see if it is valid for + // saving in V2 3DM archives. + // Returns: + // true if brep is valid for V2 3DM archives. + // Remarks: + // V2 breps could not have dangling curves. + bool IsValidForV2() const; + bool IsValidForV2( const ON_BrepTrim& ) const; + bool IsValidForV2( const ON_BrepEdge& ) const; + + + // virtual ON_Objet::Dump() override + void Dump( ON_TextLog& ) const override; // for debugging + + // virtual ON_Objet::Write() override + bool Write( ON_BinaryArchive& ) const override; + + // virtual ON_Objet::Read() override + bool Read( ON_BinaryArchive& ) override; + + // virtual ON_Objet::ObjectType() override + ON::object_type ObjectType() const override; + + // virtual ON_Geometry::Dimension() override + int Dimension() const override; + + // virtual ON_Geometry::ClearBoundingBox() override + void ClearBoundingBox() override; + + // virtual ON_Geometry GetTightBoundingBox override + bool GetTightBoundingBox( class ON_BoundingBox& tight_bbox, bool bGrowBox = false, const class ON_Xform* xform = nullptr ) const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + // virtual ON_Geometry::Transform() override + bool Transform( + const ON_Xform& + ) override; + + + // virtual ON_Geometry::SwapCoordinates() override + bool SwapCoordinates( + int, int // indices of coordinates to swap + ) override; + + + // virtual ON_Geometry::HasBrepForm() override + bool HasBrepForm() const override; // returns true + + /* + Description: + If possible, BrepForm() creates a brep form of the + ON_Geometry. + Parameters: + brep - [in] if not nullptr, brep is used to store the brep + form of the geometry. + Result: + If brep is not nullptr, then brep = this, otherwise + a duplicate of this is returned. + Remarks: + Override of virtual ON_Geometry::BrepForm + */ + ON_Brep* BrepForm( ON_Brep* brep = nullptr ) const override; + + ///////////////////////////////////////////////////////////////// + // Creation Interface + + // These add a new geometry piece to the b-rep and return the + // index that should be used to reference the geometry. + // -1 is returned if the input is not acceptable. + // ~ON_Brep() will delete the geometry. + int AddTrimCurve( ON_Curve* ); // 2d curve used by ON_BrepTrim + int AddEdgeCurve( ON_Curve* ); // 3d curve used by ON_BrepEdge + int AddSurface( ON_Surface* ); // 3d surface used by ON_BrepFace + + // Description: + // Set 3d curve geometry used by a b-rep edge. + // Parameters: + // edge - [in] + // c3_index - [in] index of 3d curve in m_C3[] array + // sub_domain - [in] if not nullptr, sub_domain is an increasing + // sub interval of m_C3[c3_index]->Domain(). + // Returns: + // true if successful. + bool SetEdgeCurve( + ON_BrepEdge& edge, + int c3_index, + const ON_Interval* sub_domain = nullptr + ); + + // Description: + // Set 2d curve geometry used by a b-rep trim. + // Parameters: + // trim - [in] + // c2_index - [in] index of 2d curve in m_C2[] array + // sub_domain - [in] if not nullptr, sub_domain is an increasing + // sub interval of m_C2[c2_index]->Domain(). + // Returns: + // true if successful. + bool SetTrimCurve( + ON_BrepTrim& trim, + int c2_index, + const ON_Interval* sub_domain = nullptr + ); + + // These add a new topology piece to the b-rep and return a + // reference that is intended to be used for initialization. + ON_BrepVertex& NewVertex(); + ON_BrepVertex& NewVertex( + ON_3dPoint vertex_point, + double vertex_tolerance = ON_UNSET_VALUE + ); + + ON_BrepEdge& NewEdge( + int = -1 // 3d curve index + ); + ON_BrepEdge& NewEdge( + ON_BrepVertex&, // start vertex + ON_BrepVertex&, // end vertex + int = -1, // 3d curve index + const ON_Interval* = nullptr, // sub_domain + double edge_tolerance = ON_UNSET_VALUE + ); + + /* + Description: + Add a new face to a brep. An incomplete face is added. + The caller must create and fill in the loops used by + the face. + Parameters: + si - [in] index of surface in brep's m_S[] array + Returns: + Reference to new face. + Remarks: + Adding a new face may grow the dynamic m_F array. When + this happens pointers and references to memory in the + previous m_F[] array may become invalid. Use face indices + if this is an issue. + Example: + See ON_BrepBox and ON_BrepSphere source code. + See Also: + ON_Brep::AddSurface + */ + ON_BrepFace& NewFace( + int si = -1 + ); + + /* + Description: + Add a new face to a brep. This creates a complete face with + new vertices at the surface corners, new edges along the surface + boundary, etc. The loop of the returned face has four trims that + correspond to the south, east, north, and west side of the + surface in that order. If you use this version of NewFace to + add an exiting brep, then you are responsible for using a tool + like ON_Brep::JoinEdges() to hook the new face to its + neighbors. + Parameters: + surface - [in] surface is copied. + Returns: + Pointer to new face. + Remarks: + Adding a new face may grow the dynamic arrays used to store + vertices, edges, faces, loops, and trims. When these dynamic + arrays are grown, any pointers and references to memory in + the previous arrays may become invalid. Use indices + if this is an issue. + See Also: + ON_Brep::JoinEdges + ON_Brep::AddSurface + */ + ON_BrepFace* NewFace( + const ON_Surface& surface + ); + + /* + Description: + Add a new face to brep. This version is for expert users. + Parameters: + pSurface - [in] the returned face will have an outer loop + that goes around the edges of the surface. + vid - [in/out] four vertex indices that specify the vertices at + the (sw,se,nw,ne) corners. If the input value + of a vertex index is -1, then the vertex will be + created. + eid - [in/out] four edge indices that specify the edges for + the (south,east,north,west) sides. If the input value + of an edge index is -1, then the edge will be created. + bRev3d - [in/out] four values of the trim m_bRev3d flags of + the (south,east,north,west) sides. + Returns: + Pointer to the new face or nullptr if input is not valid. + If null is returned, then the caller must delete pSurace + unless it was previously added to the brep's m_S[] array. + Remarks: + Adding a new face may grow the dynamic m_F array. When + this happens pointers and references to memory in the + previous m_F[] array may become invalid. Use face indices + if this is an issue. + Example: + See ON_BrepBox and ON_BrepSphere source code. + See Also: + ON_Brep::AddSurface + ON_Brep::AddFace( int si ) + ON_Brep::Create( ON_Surface*& ) + */ + ON_BrepFace* NewFace( + ON_Surface* pSurface, + int vid[4], + int eid[4], + bool bRev3d[4] + ); + + /* + Description: + Add a new face to the brep whose surface geometry is a + ruled surface between two edges. + Parameters: + edgeA - [in] The south side of the face's surface will + run along edgeA. + bRevEdgeA - [in] true if the new face's outer boundary + orientation along edgeA is opposite the orientation + of edgeA. + edgeB - [in] The north side of the face's surface will + run along edgeA. + bRevEdgeB - [in] true if the new face's outer boundary + orientation along edgeB is opposite the orientation + of edgeB. + Returns: + A pointer to the new face or a nullptr if the new face could + not be created. + */ + ON_BrepFace* NewRuledFace( + const ON_BrepEdge& edgeA, + bool bRevEdgeA, + const ON_BrepEdge& edgeB, + bool bRevEdgeB + ); + + /* + Description: + Add a new face to the brep whose surface geometry is a + ruled cone with the edge as the base and the vertex as + the apex point. + Parameters: + vertex - [in] The apex of the cone will be at this vertex. + The north side of the surface's parameter + space will be a singular point at the vertex. + edge - [in] The south side of the face's surface will + run along this edge. + bRevEdge - [in] true if the new face's outer boundary + orientation along the edge is opposite the + orientation of edge. + Returns: + A pointer to the new face or a nullptr if the new face could + not be created. + */ + ON_BrepFace* NewConeFace( + const ON_BrepVertex& vertex, + const ON_BrepEdge& edge, + bool bRevEdge + ); + + /* + Description: + Create a new empty boundary loop. The new loop will not be part of a face and + will not include any trim curves. + Returns: + New boundary loop. + */ + ON_BrepLoop& NewLoop( ON_BrepLoop::TYPE ); + + /* + Description: + Create a new boundary loop on a face. After you get this + ON_BrepLoop, you still need to create the vertices, edges, + and trims that define the loop. + Returns: + New loop that needs to be filled in. + */ + ON_BrepLoop& NewLoop( ON_BrepLoop::TYPE loop_type, ON_BrepFace& face ); + + /* + Description: + Create a new outer boundary loop that runs along the sides + of the face's surface. All the necessary trims, edges, + and vertices are created and added to the brep. + Parameters: + face_index - [in] index of face that needs an outer boundary + that runs along the sides of its surface. + Returns: + New outer boundary loop that is complete. + */ + ON_BrepLoop* NewOuterLoop( int face_index ); + + /* + Description: + Add a new face to brep. This version is for expert users. + Parameters: + face_index - [in] index of face that will get a new outer + loop running around the sides of the face's + underlying surface. + vid - [in/out] four vertex indices that specify the vertices at + the (sw,se,nw,ne) corners. If the input value + of a vertex index is -1, then the vertex will be + created. + eid - [in/out] four edge indices that specify the edges for + the (south,east,north,west) sides. If the input value + of an edge index is -1, then the edge will be created. + bRev3d - [in/out] four values of the trim m_bRev3d flags of + the (south,east,north,west) sides. + Returns: + Pointer to the new loop or nullptr if input is not valid. + Remarks: + Adding a new loop may grow the dynamic m_L array. When + this happens pointers and references to memory in the + previous m_L[] array may become invalid. Use face indices + if this is an issue. + See Also: + ON_Brep::NewFace + */ + ON_BrepLoop* NewOuterLoop( + int face_index, + int vid[4], + int eid[4], + bool bRev3d[4] + ); + + /* + Description: + Add a planar trimming loop to a planar face. + Parameters: + face_index - [in] index of planar face. The underlying + surface must be an ON_PlaneSurface. + loop_type - [in] type of loop to add. If loop_type is + ON_BrepLoop::unknown, then the loop direction is tested + and the the new loops type will be set to + ON_BrepLoop::outer or ON_BrepLoop::inner. If the loop_type + is ON_BrepLoop::outer, then the direction of the new loop + is tested and flipped if it is clockwise. If the loop_type + is ON_BrepLoop::inner, then the direction of the new loop + is tested and flipped if it is counter-clockwise. + boundary - [in] a list of 3d curves that form a simple (no self + intersections) closed curve. These curves define the 3d + edge geometry and should be near the planar surface. + bDuplicateCurves - [in] If true, then duplicates of the curves + in the boundary array are added to the brep. If false, the + curves in the boundary array are added to the brep and will + be deleted by ON_Brep::~ON_Brep. + Returns: + true if successful. The new loop will be brep.m_L.Last(). + */ + bool NewPlanarFaceLoop( + int face_index, + ON_BrepLoop::TYPE loop_type, + ON_SimpleArray& boundary, + bool bDuplicateCurves = true + ); + + + /* + Description: + Add a new trim that will be part of an inner, outer, or slit loop + to the brep. + Parameters: + c2i - [in] index of 2d trimming curve + Returns: + new trim + Example: + int c2i = brep->AddTrimCurve( p2dCurve ); + ON_BrepTrim& trim = NewTrim( edge, bRev3d, loop, c2i ); + trim.m_ei = ...; + trim.m_li = ...; + trim.m_tolerance[0] = ...; + trim.m_tolerance[1] = ...; + trim.m_type = ...; + trim.m_iso = ...; + Remarks: + You should set the trim's ON_BrepTrim::m_tolerance, ON_BrepTrim::m_type, + ON_BrepTrim::m_iso, ON_BrepTrim::m_li, and ON_BrepTrim::m_ei values. + In general, you should try to use the + ON_BrepTrim::NewTrim( edge, bRev3d, loop, c2i ) version of NewTrim. + If you want to add a singular trim, use ON_Brep::NewSingularTrim. + If you want to add a crvonsrf trim, use ON_Brep::NewCurveOnFace. + If you want to add a ptonsrf trim, use ON_Brep::NewPointOnFace. + See Also: + ON_Brep::SetTrimTypeFlags + ON_Brep::SetTrimIsoFlags + ON_Brep::NewSingularTrim + ON_Brep::NewPointOnFace + ON_Brep::NewCurveOnFace + */ + ON_BrepTrim& NewTrim( + int c2i = -1 + ); + + /* + Description: + Add a new trim that will be part of an inner, outer, or slit loop + to the brep. + Parameters: + bRev3d - [in] ON_BrepTrim::m_bRev3d value. true if the + edge and trim have opposite directions. + loop - [in] trim is appended to this loop + c2i - [in] index of 2d trimming curve + Returns: + new trim + Example: + int c2i = brep->AddTrimCurve( p2dCurve ); + ON_BrepTrim& trim = NewTrim( edge, bRev3d, loop, c2i ); + trim.m_ei = ...; + trim.m_tolerance[0] = ...; + trim.m_tolerance[1] = ...; + trim.m_type = ...; + trim.m_iso = ...; + Remarks: + You should set the trim's ON_BrepTrim::m_tolerance, ON_BrepTrim::m_type, + ON_BrepTrim::m_iso, and ON_BrepTrim::m_ei values. + In general, you should try to use the + ON_BrepTrim::NewTrim( edge, bRev3d, loop, c2i ) version of NewTrim. + If you want to add a singular trim, use ON_Brep::NewSingularTrim. + If you want to add a crvonsrf trim, use ON_Brep::NewCurveOnFace. + If you want to add a ptonsrf trim, use ON_Brep::NewPointOnFace. + See Also: + ON_Brep::SetTrimTypeFlags + ON_Brep::SetTrimIsoFlags + ON_Brep::NewSingularTrim + ON_Brep::NewPointOnFace + ON_Brep::NewCurveOnFace + */ + ON_BrepTrim& NewTrim( + bool bRev3d, + ON_BrepLoop& loop, + int c2i = -1 + ); + + /* + Description: + Add a new trim that will be part of an inner, outer, or slit loop + to the brep. + Parameters: + edge - [in] 3d edge associated with this trim + bRev3d - [in] ON_BrepTrim::m_bRev3d value. true if the + edge and trim have opposite directions. + c2i - [in] index of 2d trimming curve + Returns: + new trim + Example: + int c2i = brep->AddTrimCurve( p2dCurve ); + ON_BrepTrim& trim = NewTrim( edge, bRev3d, c2i ); + trim.m_li = ...; + trim.m_tolerance[0] = ...; + trim.m_tolerance[1] = ...; + trim.m_type = ...; + trim.m_iso = ...; + Remarks: + You should set the trim's ON_BrepTrim::m_tolerance, + ON_BrepTrim::m_type, ON_BrepTrim::m_iso, + and ON_BrepTrim::m_li values. + In general, you should try to use the + ON_BrepTrim::NewTrim( edge, bRev3d, loop, c2i ) version of NewTrim. + If you want to add a singular trim, use ON_Brep::NewSingularTrim. + If you want to add a crvonsrf trim, use ON_Brep::NewCurveOnFace. + If you want to add a ptonsrf trim, use ON_Brep::NewPointOnFace. + See Also: + ON_Brep::SetTrimTypeFlags + ON_Brep::SetTrimIsoFlags + ON_Brep::NewSingularTrim + ON_Brep::NewPointOnFace + ON_Brep::NewCurveOnFace + */ + ON_BrepTrim& NewTrim( + ON_BrepEdge& edge, + bool bRev3d, + int c2i = -1 + ); + + /* + Description: + Add a new trim that will be part of an inner, outer, or slit loop + to the brep. + Parameters: + edge - [in] 3d edge associated with this trim + bRev3d - [in] ON_BrepTrim::m_bRev3d value. true if the + edge and trim have opposite directions. + loop - [in] trim is appended to this loop + c2i - [in] index of 2d trimming curve + Returns: + new trim + Example: + int c2i = brep->AddTrimCurve( p2dCurve ); + ON_BrepTrim& trim = brep->NewTrim( edge, bRev3d, loop, c2i ); + trim.m_tolerance[0] = ...; + trim.m_tolerance[1] = ...; + Remarks: + You should set the trim's ON_BrepTrim::m_tolerance values. + If c2i is -1, you must set the trim's ON_BrepTrim::m_iso values. + This version of NewTrim sets the trim.m_type value. If the + input edge or loop are not currently valid, then you may + need to adjust the trim.m_type value. + If you want to add a singular trim, use ON_Brep::NewSingularTrim. + If you want to add a crvonsrf trim, use ON_Brep::NewCurveOnFace. + If you want to add a ptonsrf trim, use ON_Brep::NewPointOnFace. + See Also: + ON_Brep::SetTrimTypeFlags + ON_Brep::SetTrimIsoFlags + ON_Brep::NewSingularTrim + ON_Brep::NewPointOnFace + ON_Brep::NewCurveOnFace + */ + ON_BrepTrim& NewTrim( + ON_BrepEdge& edge, + bool bRev3d, + ON_BrepLoop& loop, + int c2i = -1 + ); + + /* + Description: + Add a new singular trim to the brep. + Parameters: + vertex - [in] vertex along collapsed surface edge + loop - [in] trim is appended to this loop + iso - [in] one of ON_Surface::S_iso, ON_Surface::E_iso, + ON_Surface::N_iso, or ON_Surface::W_iso. + c2i - [in] index of 2d trimming curve + Returns: + new trim + See Also: + ON_Brep::NewTrim + */ + ON_BrepTrim& NewSingularTrim( + const ON_BrepVertex& vertex, + ON_BrepLoop& loop, + ON_Surface::ISO iso, + int c2i = -1 + ); + + /* + Description: + Adds a new point on face to the brep. + Parameters: + face - [in] face that vertex lies on + s,t - [in] surface parameters + Returns: + new vertex that represents the point on face. + Remarks: + If a vertex is a point on a face, then brep.m_E[m_ei] + will be an edge with no 3d curve. This edge will have + a single trim with type ON_BrepTrim::ptonsrf. There + will be a loop containing this single trim. + */ + ON_BrepVertex& NewPointOnFace( + ON_BrepFace& face, + double s, + double t + ); + + /* + Description: + Add a new curve on face to the brep. + Parameters: + face - [in] face that curve lies on + edge - [in] 3d edge associated with this curve on surface + bRev3d - [in] true if the 3d edge and the 2d parameter space + curve have opposite directions. + c2i - [in] index of 2d curve in face's parameter space + Returns: + new trim that represents the curve on surface + Remarks: + You should set the trim's ON_BrepTrim::m_tolerance and + ON_BrepTrim::m_iso values. + */ + ON_BrepTrim& NewCurveOnFace( + ON_BrepFace& face, + ON_BrepEdge& edge, + bool bRev3d = false, + int c2i = -1 + ); + + // appends a copy of brep to this and updates + // indices of appended brep parts. Duplicates are not removed. + void Append( + const ON_Brep& // brep + ); + + // This function can be used to compute vertex information for a + // b-rep when everything but the m_V array is properly filled in. + // It is intended to be used when creating a ON_Brep from a + // definition that does not include explicit vertex information. + void SetVertices(void); + + // This function can be used to set the ON_BrepTrim::m_iso + // flag. It is intended to be used when creating a ON_Brep from + // a definition that does not include compatible parameter space + // type information. + // See Also: ON_BrepSetFlagsAndTolerances + bool SetTrimIsoFlags(); // sets all trim iso flags + bool SetTrimIsoFlags( ON_BrepFace& ); + bool SetTrimIsoFlags( ON_BrepLoop& ); + bool SetTrimIsoFlags( ON_BrepTrim& ); + + + /* + Description: + Calculate the type (singular, mated, boundary, etc.) of + an ON_BrepTrim object. + Parameters: + trim - [in] + bLazy - [in] if true and trim.m_type is set to something other + than ON_BrepTrim::unknown, then no calculation is + performed and the value of trim.m_type is returned. + If false, the value of trim.m_type is ignored and is calculated. + Returns: + Type of trim. + Remarks: + The trim must be connected to a valid loop. + See Also: + ON_Brep::SetTrimTypeFlags + */ + ON_BrepTrim::TYPE TrimType( + const ON_BrepTrim& trim, + bool bLazy = true + ) const; + + // This function can be used to set the ON_BrepTrim::m_type + // flag. If the optional bLazy argument is true, then only + // trims with m_type = unknown are set. + // See Also: ON_BrepSetFlagsAndTolerances + bool SetTrimTypeFlags( bool bLazy = false ); // sets all trim iso flags + bool SetTrimTypeFlags( ON_BrepFace&, bool bLazy = false ); + bool SetTrimTypeFlags( ON_BrepLoop&, bool bLazy = false ); + bool SetTrimTypeFlags( ON_BrepTrim&, bool bLazy = false ); + + // GetTrim2dStart() evaluates the start of the + // parameter space (2d) trim curve. + bool GetTrim2dStart( + int trim_index, // index of ON_BrepTrim in m_T[] array + ON_2dPoint& + ) const; + + // GetTrim2dEnd() evaluates end of the + // parameter space (2d) trim curve. + bool GetTrim2dEnd( + int, // index of ON_BrepTrim in m_T[] array + ON_2dPoint& + ) const; + + // GetTrim3dStart() evaluates the 3d surface at the start of the + // parameter space (2d) trim curve. + bool GetTrim3dStart( + int, // index of ON_BrepTrim in m_T[] array + ON_3dPoint& + ) const; + + // GetTrim3dEnd() evaluates the 3d surface at the end of the + // parameter space (2d) trim curve. + bool GetTrim3dEnd( + int, // index of ON_BrepTrim in m_T[] array + ON_3dPoint& + ) const; + + // This function examines the 2d parameter space curves and returns + // the loop's type based on their orientation. Use this function for + // debugging loop orientation problems. + ON_BrepLoop::TYPE ComputeLoopType( const ON_BrepLoop& ) const; + + // These set the various tolerances. The optional bool argument + // is called bLazy. If bLazy is false, the tolerance is recomputed + // from its definition. If bLazy is true, the tolerance is computed + // only if its current value is negative. + bool SetVertexTolerance( ON_BrepVertex& vertex, bool bLazy = false ) const; + virtual + bool SetTrimTolerance( ON_BrepTrim& trim, bool bLazy = false ) const; + virtual + bool SetEdgeTolerance( ON_BrepEdge& edge, bool bLazy = false ) const; + + /* + Description: + Set the brep's vertex tolerances. + Parameters: + bLazy - [in] if true, only vertex tolerances with the value + ON_UNSET_VALUE will be set. If false, the vertex tolerance + is recomputed from the geometry in the brep. + Returns: + true if successful. + See Also: + ON_Brep::SetVertexTolerance + ON_Brep::SetTrimTolerance + ON_Brep::SetEdgeTolerance + ON_Brep::SetVertexTolerances + ON_Brep::SetTrimTolerances + ON_Brep::SetEdgeTolerances + ON_Brep::SetTolerancesAndFlags + */ + bool SetVertexTolerances( bool bLazy = false ); + + /* + Description: + Set the brep's trim tolerances. + Parameters: + bLazy - [in] if true, only trim tolerances with the value + ON_UNSET_VALUE will be set. If false, the trim tolerance + is recomputed from the geometry in the brep. + Returns: + true if successful. + See Also: + ON_Brep::SetVertexTolerance + ON_Brep::SetTrimTolerance + ON_Brep::SetEdgeTolerance + ON_Brep::SetVertexTolerances + ON_Brep::SetTrimTolerances + ON_Brep::SetEdgeTolerances + ON_Brep::SetTolerancesAndFlags + */ + bool SetTrimTolerances( bool bLazy = false ); + + /* + Description: + Set the brep's edge tolerances. + Parameters: + bLazy - [in] if true, only edge tolerances with the value + ON_UNSET_VALUE will be set. If false, the edge tolerance + is recomputed from the geometry in the brep. + Returns: + true if successful. + See Also: + ON_Brep::SetVertexTolerance + ON_Brep::SetTrimTolerance + ON_Brep::SetEdgeTolerance + ON_Brep::SetVertexTolerances + ON_Brep::SetTrimTolerances + ON_Brep::SetEdgeTolerances + ON_Brep::SetTolerancesAndFlags + */ + bool SetEdgeTolerances( bool bLazy = false ); + + + /* + Description: + Set the trim parameter space bounding box (trim.m_pbox). + Parameters: + trim - [in] + bLazy - [in] if true and trim.m_pbox is valid, then + the box is not set. + Returns: + true if trim ends up with a valid bounding box. + */ + virtual + bool SetTrimBoundingBox( ON_BrepTrim& trim, bool bLazy=false ); + + /* + Description: + Set the loop parameter space bounding box (loop.m_pbox). + Parameters: + loop - [in] + bLazy - [in] if true and loop trim trim.m_pbox is valid, + then that trim.m_pbox is not recalculated. + Returns: + true if loop ends up with a valid bounding box. + */ + virtual + bool SetTrimBoundingBoxes( ON_BrepLoop& loop, bool bLazy=false ); + + + /* + Description: + Set the loop and trim parameter space bounding boxes + for every loop and trim in the face + Parameters: + face - [in] + bLazy - [in] if true and trim trim.m_pbox is valid, + then that trim.m_pbox is not recalculated. + Returns: + true if all the face's loop and trim parameter space bounding + boxes are valid. + */ + virtual + bool SetTrimBoundingBoxes( ON_BrepFace& face, bool bLazy=false ); + + /* + Description: + Set the loop and trim parameter space bounding boxes + for every loop and trim in the brep. + Parameters: + bLazy - [in] if true and trim trim.m_pbox is valid, + then that trim.m_pbox is not recalculated. + Returns: + true if all the loop and trim parameter space bounding boxes + are valid. + */ + virtual + bool SetTrimBoundingBoxes( bool bLazy=false ); + + /* + Description: + Set tolerances and flags in a brep + Parameters: + bLazy - [in] if true, only flags and tolerances that are not + set will be calculated. + bSetVertexTolerances - [in] true to compute vertex.m_tolerance values + bSetEdgeTolerances - [in] true to compute edge.m_tolerance values + bSetTrimTolerances - [in] true to compute trim.m_tolerance[0,1] values + bSetTrimIsoFlags - [in] true to compute trim.m_iso values + bSetTrimTypeFlags - [in] true to compute trim.m_type values + bSetLoopTypeFlags - [in] true to compute loop.m_type values + bSetTrimBoxes - [in] true to compute trim.m_pbox values + See Also: + ON_Brep::SetVertexTolerance + ON_Brep::SetEdgeTolerance + ON_Brep::SetTrimTolerance + ON_Brep::SetTrimTypeFlags + ON_Brep::SetTrimIsoFlags + ON_Brep::ComputeLoopType + ON_Brep::SetTrimBoundingBox + ON_Brep::SetTrimBoundingBoxes + */ + void SetTolerancesBoxesAndFlags( + bool bLazy = false, + bool bSetVertexTolerances = true, + bool bSetEdgeTolerances = true, + bool bSetTrimTolerances = true, + bool bSetTrimIsoFlags = true, + bool bSetTrimTypeFlags = true, + bool bSetLoopTypeFlags = true, + bool bSetTrimBoxes = true + ); + + + ///////////////////////////////////////////////////////////////// + // Query Interface + + /* + Description: + Determine how many brep faces reference m_S[surface_index]. + Parameters: + surface_index - [in] index of the surface in m_S[] array + max_count - [in] counting stops if max_count > 0 and + at least max_count faces use the surface. + Returns: + Number of brep faces that reference the surface. + */ + int SurfaceUseCount( + int surface_index, + int max_count=0 ) + const; + /* + Description: + Determine how many brep edges reference m_C3[c3_index]. + Parameters: + c3_index - [in] index of the 3d curve in m_C3[] array + max_count - [in] counting stops if max_count > 0 and + at least max_count edges use the 3d curve. + Returns: + Number of brep edges that reference the 3d curve. + */ + int EdgeCurveUseCount( + int c3_index, + int max_count=0 ) + const; + + /* + Description: + Determine how many brep trims reference m_C2[c2_index]. + Parameters: + c2_index - [in] index of the 2d curve in m_C2[] array + max_count - [in] counting stops if max_count > 0 and + at least max_count trims use the 2d curve. + Returns: + Number of brep trims that reference the 2d curve. + */ + int TrimCurveUseCount( + int c2_index, + int max_count=0 ) + const; + + /* + Description: + Get a single 3d curve that traces the entire loop + Parameters: + loop - [in] loop whose 3d curve should be duplicated + bRevCurveIfFaceRevIsTrue - [in] If false, the returned + 3d curve has an orientation compatible with the + 2d curve returned by Loop2dCurve(). + If true and the m_bRev flag of the loop's face + is true, then the returned curve is reversed. + Returns: + A pointer to a 3d ON_Curve. The caller must delete + this curve. + */ + ON_Curve* Loop3dCurve( + const ON_BrepLoop& loop, + bool bRevCurveIfFaceRevIsTrue = false + ) const; + + /* + Description: + Get a list of 3d curves that trace the non-seam edge + portions of an entire loop + Parameters: + loop - [in] loop whose 3d curve should be duplicated + curve_list - [out] 3d curves are appended to this list + bRevCurveIfFaceRevIsTrue - [in] If false, the returned + 3d curves have an orientation compatible with the + 2d curve returned by Loop2dCurve(). + If true and the m_bRev flag of the loop's face + is true, then the returned curves are reversed. + Returns: + Number of curves appended to curve_list. + */ + int Loop3dCurve( + const ON_BrepLoop& loop, + ON_SimpleArray& curve_list, + bool bRevCurveIfFaceRevIsTrue = false + ) const; + + + /* + Description: + Get a 3d curve that traces the entire loop + Parameters: + loop - [in] loop whose 2d curve should be duplicated + Returns: + A pointer to a 2d ON_Curve. The caller must delete + this curve. + */ + ON_Curve* Loop2dCurve( const ON_BrepLoop& loop ) const; + + /* + Description: + Determine orientation of a brep. + Returns: + @untitle table + +2 brep is a solid but orientation cannot be computed + +1 brep is a solid with outward facing normals + -1 brep is a solid with inward facing normals + 0 brep is not a solid + Remarks: + The base class implementation returns 2 or 0. This + function is overridden in the Rhino SDK and returns + +1, -1, or 0. + See Also: + ON_Brep::IsSolid + */ + virtual + int SolidOrientation() const; + + /* + Description: + Test brep to see if it is a solid. (A "solid" is + a closed oriented manifold.) + Returns: + If the brep is a solid, true is returned. Otherwise false is returned. + See Also: + ON_Brep::SolidOrientation + ON_Brep::IsManifold + */ + bool IsSolid() const; + + /* + Description: + Test brep to see if it is an oriented manifold. + Parameters: + pbIsOriented - [in] if not null, *pbIsOriented is set + to true if b-rep is an oriented manifold and false + if brep is not an oriented manifold. + pbHasBoundary - [in] if not null, *pbHasBoundary is set + to true if b-rep has a boundary edge and false if + brep does not have a boundary edge. + Returns: + If the brep is a manifold, true is returned. Otherwise false is returned. + See Also: + ON_Brep::IsSolid + */ + bool IsManifold( // returns true if b-rep is an oriented manifold + bool* pbIsOriented = nullptr, + bool* pbHasBoundary = nullptr + ) const; + + + /* + Description: + When an expert is 100% certain of a brep's solid orientation, this function + can be used to set the SolidOrientation() property. + Parameters: + solid_orientation - [in] + 0: not solid, + 1: oriented manifold solid (no boundary) with outward facing normals. + -1: oriented manifold solid (no boundary) with inward facing normals. + */ + void SetSolidOrientationForExperts( + int solid_orientation + ); + + + /* + Description: + Determine if P is inside Brep. This question only makes sense + when the brep is a closed manifold. This function does not + not check for closed or manifold, so result is not valid in + those cases. Intersects a line through P with brep, finds + the intersection point Q closest to P, and looks at face + normal at Q. If the point Q is on an edge or the intersection + is not transverse at Q, then another line is used. + Parameters: + P - [in] 3d point + tolerance - [in] 3d distance tolerance used for intersection + and determining strict inclusion. + bStrictlInside - [in] If bStrictlInside is true, then this + function will return false if the distance from P is within + tolerance of a brep face. + Returns: + True if P is in, false if not. See parameter bStrictlyIn. + */ + bool IsPointInside( + ON_3dPoint P, + double tolerance, + bool bStrictlyInside + ) const; + + + bool IsSurface() const; // returns true if the b-rep has a single face + // and that face is geometrically the same + // as the underlying surface. I.e., the face + // has trivial trimming. In this case, the + // surface is m_S[0]. + // The flag m_F[0].m_bRev records + // the correspondence between the surface's + // natural parametric orientation and the + // orientation of the b-rep. + + + bool FaceIsSurface( // returns true if the face has a single + int // index of face // outer boundary and that boundary runs + ) const; // along the edges of the underlying surface. + // In this case the geometry of the surface + // is the same as the geometry of the face. + // If FaceIsSurface() is true, then + // m_S[m_F[face_index].m_si] is the surface. + // The flag m_F[face_index].m_bRev records + // the correspondence between the surface's + // natural parametric orientation and the + // orientation of face in the b-rep. + + bool LoopIsSurfaceBoundary( // returns true if the loop's trims all run + int // index of loop // along the edge's of the underlying surface's + ) const; // parameter space. + + ///////////////////////////////////////////////////////////////// + // Modification Interface + + ////////// + // Clears all ON_BrepFace.m_bRev flags by ON_BrepFace::Transpose + // on each face with a true m_bRev. + bool FlipReversedSurfaces(); + + ////////// + // Change the domain of a trim's 2d curve. This changes only the + // parameterization of the 2d trimming curve; the locus of the + // 2d trimming curve is not changed. + bool SetTrimDomain( + int, // index of trim in m_T[] array + const ON_Interval& + ); + + ////////// + // Change the domain of an edge. This changes only the + // parameterization of the 3d edge curve; the locus of the + // 3d edge curve is not changed. + bool SetEdgeDomain( + int, // index of edge in m_E[] array + const ON_Interval& + ); + + // Reverses entire brep orientation of all faces by toggling + // value of all face's ON_BrepFace::m_bRev flag. + void Flip(); + + // reverses orientation of a face by toggling ON_BrepFace::m_bRev + void FlipFace(ON_BrepFace&); + + // Reverses orientation of trimming loop. + // This function is intended to be used by brep experts and does + // does NOT modify ON_BrepLoop::m_type. You should make sure + // ON_BrepLoop::m_type jibes with the loop's direction. (Outer loops + // should be counter-clockwise and inner loops should be clockwise.) + // You can use ON_Brep::LoopDirection() to determine the direction of + // a loop. + void FlipLoop(ON_BrepLoop&); // reverses orientation of trimming loop + + // LoopDirection() examines the 2d trimming curve geometry that defines + // the loop and returns + // + // @untitled table + // +1 the loop is a counter-clockwise loop. + // -1 the loop is a clockwise loop. + // 0 the loop is not a continuous closed loop. + // + // Since LoopDirection() calculates its result based on the 2d trimming + // curve geometry, it can be use to set ON_BrepLoop::m_type to outer/inner + // when translating from data definition where this distinction is murky. + int LoopDirection( const ON_BrepLoop& ) const; + + + /* + Description: + Sort the face.m_li[] array by loop type + (outer, inner, slit, crvonsrf, ptonsrf) + Parameters: + face - [in/out] face whose m_li[] array should be sorted. + Returns: + @untitled table + true success + false failure - no loops or loops with unset loop.m_type + See Also: + ON_Brep::ComputeLoopType + ON_Brep::LoopDirection + */ + bool SortFaceLoops( ON_BrepFace& face ) const; + + + + /* + Description: + Expert user function. + Turn an edge into a series of naked or seam edges. + One for each trim at the original edge that comes from a unique face. + These edges will share the 3d curve of the original edge. The original edge will + still be valid and will have m_ti[0] unchanged. + */ + bool DisconnectEdgeFaces(int eid); + + /* + Description: + Expert user function. + See Also: + ON_Brep::JoinEdges + */ + bool CombineCoincidentVertices(ON_BrepVertex&, ON_BrepVertex&); // moves information to first vertex and deletes second + + /* + Description: + Expert user function. + See Also: + ON_Brep::JoinEdges + */ + bool CombineCoincidentEdges(ON_BrepEdge&, ON_BrepEdge&); // moves information to first edge and deletes second + + /* + Description: + Expert user function. + Combines contiguous edges into a single edge. The edges + must share a common vertex, then angle between the edge + tangents are the common vertex must be less than or + equal to angle_tolerance_radians, and any associated + trims must be contiguous in there respective boundaries. + Parameters; + edge_index0 - [in] + edge_index1 - [in] + angle_tolerance_radians - [in] + Returns: + Pointer to the new edge or nullptr if the edges cannot + be combined into a single edge. + Remarks: + The input edges are deleted but are still in the + brep's m_E[] arrays. Use ON_Brep::Compact to remove + the unused edges. + */ + ON_BrepEdge* CombineContiguousEdges( + int edge_index0, + int edge_iindex1, + double angle_tolerance_radians = ON_PI/180.0 + ); + + + // These remove a topology piece from a b-rep but do not + // rearrange the arrays that hold the brep objects. The + // deleted objects have their indices set to -1. Deleting + // an object that is connected to other objects will + // modify those objects. + void DeleteVertex(ON_BrepVertex& vertex); + void DeleteEdge(ON_BrepEdge& edge, bool bDeleteEdgeVertices); // pass true to delete vertices used only by edge + void DeleteTrim(ON_BrepTrim& trim, bool bDeleteTrimEdges); // pass true to delete edges and vertices used only by trim + void DeleteLoop(ON_BrepLoop& loop, bool bDeleteLoopEdges); // pass true to delete edges and vertices used only by trim + void DeleteFace(ON_BrepFace& face, bool bDeleteFaceEdges); // pass true to delete edges and vertices used only by face + void DeleteSurface(int s_index); + void Delete2dCurve(int c2_index); + void Delete3dCurve(int c3_index); + + // Description: + // Set m_vertex_user.i, m_edge_user.i, m_face_user.i, m_loop_user.i, + // and m_trim_user.i values of faces of component including + // m_F[face_index] to label. Numbering starts at 1. + // Parameters: + // face_index - [in] index of face in component + // label - [in] value for m_*_user.i + // Returns: + // Remarks: + // Chases through trim lists of face edges to find adjacent faces. + // Does NOT check for vertex-vertex connections + void LabelConnectedComponent( + int face_index, + int label + ) const; + + /* + Description: + Set m_vertex_user.i, m_edge_user.i, m_face_user.i, m_loop_user.i, + and m_trim_user.i values values to distinguish connected components. + Parameters: + Returns: + number of connected components + Remarks: + For each face in the i-th component, sets m_face_user.i to i>0. + Chases through trim lists of face edges to find adjacent faces. + Numbering starts at 1. Does NOT check for vertex-vertex connections. + See Also: + ON_Brep::GetConnectedComponents + */ + int LabelConnectedComponents() const; + + /* + Description: + If this brep has two or more connected components, + then duplicates of the connected components are appended + to the components[] array. + Parameters: + components - [out] connected components are appended to this array. + bDuplicateMeshes - [in] if true, any meshes on this brep are copied + to the output breps. + Returns: + Number of connected components appended to components[] or zero + if this brep has only one connected component. + See Also: + ON_Brep::GetConnectedComponents + */ + int GetConnectedComponents( + ON_SimpleArray< ON_Brep* >& components, + bool bDuplicateMeshes + ) const; + + + /* + Description: + Copy a subset of this brep. + Parameters: + subfi_count - [in] length of sub_fi[] array. + sub_fi - [in] array of face indices in this + brep to copy. (If any values inf sub_fi[] + are out of range or if sub_fi[] contains + duplicates, this function will return null.) + sub_brep - [in] if this pointer is not null, + then the sub-brep will be created in this + class. + Returns: + If the input is valid, a pointer to the + sub-brep is returned. If the input is not + valid, null is returned. The faces in + in the sub-brep's m_F array are in the same + order as they were specified in sub_fi[]. + */ + ON_Brep* SubBrep( + int subfi_count, + const int* sub_fi, + ON_Brep* sub_brep = 0 + ) const; + + /////////////////////////////////////////////////////////////////////// + // + // region topology + // + bool HasRegionTopology() const; + + /* + Description: + Get region topology information: + In order to keep the ON_Brep class efficient, rarely used + region topology information is not maintained. If you + require this information, call RegionTopology(). + */ + const ON_BrepRegionTopology& RegionTopology() const; + + /* + Description: + Destroy region topology information. + */ + void DestroyRegionTopology(); + + // Description: + // Duplicate a single brep face. + // Parameters: + // face_index - [in] index of face to duplicate + // bDuplicateMeshes - [in] if true, any attached meshes are duplicated + // Returns: + // Single face brep. + // Remarks: + // The m_vertex_user.i, m_edge_user.i, m_face_user.i, m_loop_user.i, + // and m_trim_user.i values of the returned brep are are set to the + // indices of the objects they duplicate. + // See Also: + // ON_Brep::DeleteFace, ON_Brep::ExtractFace + ON_Brep* DuplicateFace( + int face_index, + bool bDuplicateMeshes + ) const; + + // Description: + // Duplicate a a subset of a brep + // Parameters: + // face_count - [in] length of face_index[] array + // face_index - [in] array of face indices + // bDuplicateMeshes - [in] if true, any attached meshes are duplicated + // Returns: + // A brep made by duplicating the faces listed in the face_index[] array. + // Remarks: + // The m_vertex_user.i, m_edge_user.i, m_face_user.i, m_loop_user.i, + // and m_trim_user.i values of the returned brep are are set to the + // indices of the objects they duplicate. + // See Also: + // ON_Brep::DuplicateFace + ON_Brep* DuplicateFaces( + int face_count, + const int* face_index, + bool bDuplicateMeshes + ) const; + + // Description: + // Extract a face from a brep. + // Parameters: + // face_index - [in] index of face to extract + // Returns: + // Single face brep. + // See Also: + // ON_Brep::DeleteFace, ON_Brep::DuplicateFace + ON_Brep* ExtractFace( + int face_index + ); + + + /* + Description: + Standardizes the relationship between an ON_BrepEdge + and the 3d curve it uses. When done, the edge will + be the only edge that references its 3d curve, the + domains of the edge and 3d curve will be the same, + and the edge will use the entire locus of the 3d curve. + Parameters: + edge_index - [in] index of edge to standardize. + bAdjustEnds - [in] if true, move edge curve endpoints to vertices + See Also: + ON_Brep::StandardizeEdgeCurves + ON_Brep::Standardize + */ + bool StandardizeEdgeCurve( int edge_index, bool bAdjustEnds ); + + + /* + Description: + Expert user only. Same as above, but to be used when the edge + curve use count is known for the edge. + Standardizes the relationship between an ON_BrepEdge + and the 3d curve it uses. When done, the edge will + be the only edge that references its 3d curve, the + domains of the edge and 3d curve will be the same, + and the edge will use the entire locus of the 3d curve. + Parameters: + edge_index - [in] index of edge to standardize. + bAdjustEnds - [in] if true, move edge curve endpoints to vertices + EdgeCurveUse - [in] if > 1, then the edge curve for this edge is used by more than one + edge. if 1, then the edge curve is used only for this edge. + If <= 0, then use count is unknown. + See Also: + ON_Brep::StandardizeEdgeCurves + ON_Brep::Standardize + */ + bool StandardizeEdgeCurve( int edge_index, bool bAdjustEnds, int EdgeCurveUse ); + + + /* + Description: + Standardize all edges in the brep. + Parameters: + bAdjustEnds - [in] if true, move edge curve endpoints to vertices + See Also: + ON_Brep::StandardizeEdgeCurve + ON_Brep::Standardize + */ + void StandardizeEdgeCurves( bool bAdjustEnds ); + + /* + Description: + Standardizes the relationship between an ON_BrepTrim + and the 2d curve it uses. When done, the trim will + be the only trim that references its 2d curve, the + domains of the trim and 2d curve will be the same, + and the trim will use the entire locus of the 2d curve. + Parameters: + trim_index - [in] index of trim to standardize. + See Also: + ON_Brep::StandardizeTrimCurves + ON_Brep::Standardize + */ + bool StandardizeTrimCurve( int trim_index ); + + /* + Description: + Standardize all trims in the brep. + See Also: + ON_Brep::StandardizeTrimCurve + ON_Brep::Standardize + */ + void StandardizeTrimCurves(); + + /* + Description: + Standardizes the relationship between an ON_BrepFace + and the 3d surface it uses. When done, the face will + be the only face that references its 3d surface, and + the orientations of the face and 3d surface will be + the same. + Parameters: + face_index - [in] index of face to standardize. + See Also: + ON_Brep::StardardizeFaceSurfaces + ON_Brep::Standardize + */ + bool StandardizeFaceSurface( int face_index ); + + /* + Description: + Standardize all faces in the brep. + See Also: + ON_Brep::StandardizeFaceSurface + ON_Brep::Standardize + */ + void StandardizeFaceSurfaces(); + + /* + Description: + Standardize all trims, edges, and faces in the brep. + Remarks: + After standardizing, there may be unused curves and surfaces + in the brep. Call ON_Brep::Compact to remove these unused + curves and surfaces. + See Also: + ON_Brep::StandardizeTrimCurves + ON_Brep::StandardizeEdgeCurves + ON_Brep::StandardizeFaceSurface + ON_Brep::Compact + */ + void Standardize(); + + + /* + Description: + Sometimes the ON_Surface used by a face extends far + beyond the face's outer boundary. ShrinkSurface uses + ON_Surface::Trim to remove portions of the surface that + extend beyond the face's outer boundary loop. + Parameters: + face - [in] face to test and whose surface should be shrunk. + DisableSide - [in] This is a bit field. A set bit indicates not to shrink + the surface on a given side. The default of 0 enables shrinking + on all four sides. + @table + value meaning + 0x0001 Don't shrink on the west side of domain. + 0x0002 Don't shrink on the south side of domain. + 0x0004 Don't shrink on the east side of domain. + 0x0008 Don't shrink on the north side of domain. + Returns: + @untitled table + true successful + false failure + Remarks: + If a surface needs to be shrunk it is copied. After shrinking, + you may want to call ON_Brep::CullUnusedSurfaces to remove + any unused surfaces. + See Also: + ON_Brep::ShrinkSurfaces + ON_Brep::CullUnusedSurfaces + */ + bool ShrinkSurface( ON_BrepFace& face, int DisableSide=0 ); + + /* + Description: + Sometimes the ON_Surface used by a face extends far + beyond the face's outer boundary. ShrinkSurfaces calls + ON_Shrink::ShrinkSurface on each face to remove portions + of surfaces that extend beyond their face's outer boundary + loop. + Returns: + @untitled table + true successful + false failure + Remarks: + If a surface needs to be shrunk it is copied. After shrinking, + you may want to call ON_Brep::CullUnusedSurfaces to remove + any unused surfaces. + See Also: + ON_Brep::ShrinkSurface + ON_Brep::CullUnusedSurfaces + */ + bool ShrinkSurfaces(); + + /* + Description: + Uses the CullUnused*() members to delete any unreferenced + objects from arrays, reindexes as needed, and shrinks + arrays to minimum required size. + See Also: + ON_Brep::CullUnusedFaces + ON_Brep::CullUnusedLoops + ON_Brep::CullUnusedTrims + ON_Brep::CullUnusedEdges + ON_Brep::CullUnusedVertices + ON_Brep::CullUnused3dCurves + ON_Brep::CullUnused2dCurves + ON_Brep::CullUnusedSurfaces + */ + bool Compact(); + + bool CullUnusedFaces(); // culls faces with m_face_index == -1 + bool CullUnusedLoops(); // culls loops with m_loop_index == -1 + bool CullUnusedTrims(); // culls trims with m_trim_index == -1 + bool CullUnusedEdges(); // culls edges with m_edge_index == -1 + bool CullUnusedVertices(); // culls vertices with m_vertex_index == -1 + bool CullUnused3dCurves(); // culls 2d curves not referenced by a trim + bool CullUnused2dCurves(); // culls 3d curves not referenced by an edge + bool CullUnusedSurfaces(); // culls surfaces not referenced by a face + + ///////////////////////////////////////////////////////////////// + // Navigation Interface + + // for moving around loops - returns trim index of previous/next trim in loop + int PrevTrim( + int // index of current trim (m_trim_index) + ) const; + int NextTrim( + int // index of current trim (m_trim_index) + ) const; + + //Same as NextTrim and PrevTrim, but skips over trims with type singular + int PrevNonsingularTrim( + int // index of current trim (m_trim_index) + ) const; + int NextNonsingularTrim( + int // index of current trim (m_trim_index) + ) const; + + /* + Description: + This is a simple tool for getting running through the edges + that begin and end at a vertex. + Parameters: + current_edge_index - [in] + endi - [in] 0 = use the edge start vertex, 1 = use the edge end vertex + prev_endi - [out] 0 if previous edge begins at the vertex, + 1 if previous edge ends at the vertex + Returns: + edge index of the previous edge or -1 if there is only one edge + that begins or ends at the vertex. + Remarks: + This is a tool that simplifies searching through the + ON_BrepVertex.m_ei[] array. + The edges are in no particular order. + See Also: + ON_Brep::NextEdge + */ + int PrevEdge( + int current_edge_index, + int endi, + int* prev_endi = nullptr + ) const; + + /* + Description: + This is a simple tool for getting running through the edges + that begin and end at a vertex. + Parameters: + current_edge_index - [in] + endi - [in] 0 = use the edge start vertex, 1 = use the edge end vertex + next_endi - [out] 0 if next edge begins at the vertex, + 1 if next edge ends at the vertex + Returns: + edge index of the next edge or -1 if there is only one edge + that begins or ends at the vertex. + Remarks: + This is a tool that simplifies searching through the + ON_BrepVertex.m_ei[] array. + The edges are in no particular order. + See Also: + ON_Brep::NextEdge + */ + int NextEdge( + int current_edge_index, + int endi, + int* next_endi = nullptr + ) const; + + /* + Description: + Get a brep component from its index. + Parameters: + component_index - [in] + Returns: + A const pointer to the component. Do not delete + the returned object. It points to an object managed + by this brep. + See Also: + ON_Brep::Face + ON_Brep::Edge + ON_Brep::Loop + ON_Brep::Trim + ON_Brep::Vertex + */ + const ON_Geometry* BrepComponent( + ON_COMPONENT_INDEX ci + ) const; + + /* + Description: + Get vertex from trim index or component index. + Parameters: + vertex_index - [in] either an index into m_V[] or a component index + of type brep_vertex. + Returns: + If the index is a valid vertex index or a valid vertex component + index, then a pointer to the ON_BrepVertex is returned. Otherwise + nullptr is returned. + See Also + ON_Brep::Component( const ON_BrepVertex& ) + */ + ON_BrepVertex* Vertex( int vertex_index ) const; + ON_BrepVertex* Vertex( ON_COMPONENT_INDEX vertex_index ) const; + + /* + Description: + Get edge from edge index or component index. + Parameters: + edge_index - [in] either an index into m_E[] or a component index + of type brep_edge. + Returns: + If the index is a valid edge index or a valid edge component + index, then a pointer to the ON_BrepEdge is returned. Otherwise + nullptr is returned. + See Also + ON_Brep::Component( const ON_BrepEdge& ) + */ + ON_BrepEdge* Edge( int edge_index ) const; + ON_BrepEdge* Edge( ON_COMPONENT_INDEX edge_index ) const; + + /* + Description: + Get trim from trim index or component index. + Parameters: + trim_index - [in] either an index into m_T[] or a component index + of type brep_trim. + Returns: + If the index is a valid trim index or a valid trim component + index, then a pointer to the ON_BrepTrim is returned. Otherwise + nullptr is returned. + See Also + ON_Brep::Component( const ON_BrepTrim& ) + */ + ON_BrepTrim* Trim( int trim_index ) const; + ON_BrepTrim* Trim( ON_COMPONENT_INDEX trim_index ) const; + + /* + Description: + Get loop from loop index or component index. + Parameters: + loop_index - [in] either an index into m_L[] or a component index + of type brep_loop. + Returns: + If the index is a valid loop index or a valid loop component + index, then a pointer to the ON_BrepLoop is returned. Otherwise + nullptr is returned. + See Also + ON_Brep::Component( const ON_BrepLoop& ) + */ + ON_BrepLoop* Loop( int loop_index ) const; + ON_BrepLoop* Loop( ON_COMPONENT_INDEX loop_index ) const; + + /* + Description: + Get face from face index or component index. + Parameters: + face_index - [in] either an index into m_F[] or a component index + of type brep_face. + Returns: + If the index is a valid face index or a valid face component + index, then a pointer to the ON_BrepFace is returned. Otherwise + nullptr is returned. + See Also + ON_Brep::Component( const ON_BrepFace& ) + */ + ON_BrepFace* Face( int face_index ) const; + ON_BrepFace* Face( ON_COMPONENT_INDEX face_index ) const; + + //Match endpoints of adjacent trims. If a trim needs to be adjusted, copy the 2d curve if necessary, + //convert to NURBS form, yank cvs. Compact() should be called afterwards. Returns false if error in + //computation, Trims must be from same face and meet at a common vertex. + //These are expert user functions. When in doubt use MatchTrimEnds() on the entire Brep. + + /* + Description: + Match the end of a trim to the start of the next trim. + Parameters: + T0 - [in] brep trim + T1 - [in] brep trim that comes immediately after T0 in the same loop + Returns: + true if either trim's 2d curve is changed + */ + bool MatchTrimEnds(ON_BrepTrim& T0, + ON_BrepTrim& T1 + ); + + /* + Description: + Match the endpoints of a trim to the next and previous trim + Parameters: + trim_index - [in] index into m_T + Returns: + true if any trim's 2d curve is changed + */ + bool MatchTrimEnds(int trim_index); + + /* + Description: + Match the endpoints of all trims in a loop + Parameters: + Loop - [in] brep loop + Returns: + true if any trim's 2d curve is changed + */ + bool MatchTrimEnds(ON_BrepLoop& Loop); + + /* + Description: + Match the endpoints of all trims in a brep + Parameters: + Returns: + true if any trim's 2d curve is changed + */ + bool MatchTrimEnds(); + + /* + Description: + Convert the 2d curve of a trim to an ON_NurbsCurve + Parameters: + T - [in] brep trim + Returns: + Pointer to m_C2[T.m_c2i] + NOTE: After calling this, m_C2[T.m_c2i] will be a NURBS curve only referenced by + T, with domain = T.m_t. Caller should not delete the returned curve since its memory is owned + by the brep (this). + */ + ON_NurbsCurve* MakeTrimCurveNurb(ON_BrepTrim& T); + + /* + Description: + Check for slit trims and slit boundaries in each face. + Returns: + true if any slits were found + */ + bool HasSlits() const; + + /* + Description: + Check for slit trims and slit boundaries in a face. + Returns: + true if any slits were found + */ + bool HasSlits(const ON_BrepFace& F) const; + + /* + Description: + Check for slit trims in a loop. + Returns: + true if any slits were found + */ + bool HasSlits(const ON_BrepLoop& L) const; + + /* + Description: + remove slit trims and slit boundaries from each face. + Returns: + true if any slits were removed + Remarks: + Caller should call Compact() afterwards. + */ + bool RemoveSlits(); + + /* + Description: + remove slit trims and slit boundaries from a face. + Parameters: + F - [in] brep face + Returns: + true if any slits were removed + Remarks: + Caller should call Compact() when done. + */ + bool RemoveSlits(ON_BrepFace& F); + + /* + Description: + remove slit trims from a loop. + Parameters: + L - [in] brep loop + Returns: + true if any slits were removed + Remarks: + Caller should call Compact() when done. + If all trims are removed, the loop will be marked as deleted. + */ + bool RemoveSlits(ON_BrepLoop& L); + + /* + Description: + If fid0 != fid1 and m_F[fid0] and m_F[fid1] have the same surface (m_si is identical), + and they are joined along a set of edges that do not have any other faces, then this will + combine the two faces into one. + Parameters: + fid0, fid1 - [in] indices into m_F of faces to be merged. + Returns: + id of merged face if faces were successfully merged. -1 if not merged. + Remarks: + Caller should call Compact() when done. + */ + int MergeFaces(int fid0, int fid1); + + /* + Description: + Merge all possible faces that have the same m_si + Returns: + true if any faces were successfully merged. + Remarks: + Caller should call Compact() when done. + */ + bool MergeFaces(); + + /* + Description: + Removes nested polycurves from the m_C2[] and m_C3[] arrays. + Parameters: + bExtractSingleSegments - [in] if true, polycurves with a + single segment are replaced with the segment curve. + bEdges - [in] if true, the m_C3[] array is processed + bTrimCurves - [in] if true, the m_C2[] array is processed. + Returns: + True if any nesting was removed and false if no nesting + was removed. + */ + bool RemoveNesting( + bool bExtractSingleSegments, + bool bEdges = true, + bool bTrimCurves = true + ); + + /* + Description: + Expert user tool to collapse a "short" edge to a vertex. + The edge is removed and the topology is repaired + so that everything that used to connect to the edge + connects the specified vertex. + Parameters: + edge_index - [in] index of edge to remove + bCloseTrimGap - [in] if true and the removal of the + edge creates a gap in the parameter space trimming + loop, then the 2d trim curves will be adjusted to + close the gap. + vertex_index - [in] if >= 0, this the edge is collapsed + to this vertex. Otherwise a vertex is automatically + selected or created. + Returns: + True if edge was successfully collapsed. + Remarks: + After you finish cleaning up the brep, you need + to call ON_Brep::Compact() to remove unused edge, + trim, and vertex information from the brep's m_E[], + m_V[], m_T[], m_C2[], and m_C3[] arrays. + */ + bool CollapseEdge( + int edge_index, + bool bCloseTrimGap = true, + int vertex_index = -1 + ); + + /* + Description: + Expert user tool to move trims and edges from + one vertex to another. + Parameters: + old_vi - [in] index of old vertex + new_vi - [in] index of new vertex + bClearTolerances - [in] if true, then tolerances of + edges and trims that are connected to the old + vertex are set to ON_UNSET_VALUE. + vertex_index - [in] if >= 0, this the edge is collapsed + to this vertex. Otherwise a vertex is automatically + selected or created. + Returns: + True if successful. + Remarks: + After you finish cleaning up the brep, you need + to call ON_Brep::Compact() to remove unused edge, + trim, and vertex information from the brep's m_E[], + m_V[], m_T[], m_C2[], and m_C3[] arrays. + */ + bool ChangeVertex( + int old_vi, + int new_vi, + bool bClearTolerances + ); + + /* + Description: + Expert user tool to remove any gap between adjacent trims. + Parameters: + trim0 - [in] + trim1 - [in] + Returns: + True if successful. + Remarks: + The trims must be in the same trimming loop. The vertex + at the end of trim0 must be the same as the vertex at + the start of trim1. The trim's m_iso and m_type flags + need to be correctly set. + */ + bool CloseTrimGap( + ON_BrepTrim& trim0, + ON_BrepTrim& trim1 + ); + + /* + Description: + Remove edges that are not connected to a face. + Parameters: + bDeleteVertices - [in] if true, then the vertices + at the ends of the wire edges are deleted if + they are not connected to face trimming edges. + Returns: + Number of edges that were removed. + Remarks: + After you finish cleaning up the brep, you need + to call ON_Brep::Compact() to remove unused edge, + trim, and vertex information from the brep's m_E[], + m_V[], m_T[], m_C2[], and m_C3[] arrays. + + After you finish cleaning up the brep, you need + to call ON_Brep::Compact() to remove deleted vertices + from the m_V[] array. + See Also: + ON_Brep::RemoveWireVertices + */ + int RemoveWireEdges( bool bDeleteVertices = true ); + + /* + Description: + Remove vertices that are not connected to an edge. + Returns: + Number of vertices that were deleted. + Remarks: + After you finish cleaning up the brep, you need + to call ON_Brep::Compact() to remove deleted + vertices from the m_V[] array. + See Also: + ON_Brep::RemoveWireEdges + */ + int RemoveWireVertices(); + + +public: + /* + Description: + Removes all per face material channel index overrides. + Returns: + Number of changed faces. + Remarks: + Per face material channel indices are a mutable property on ON_BrepFace and are set with ON_BrepFace.SetMaterialChannelIndex(). + */ + unsigned int ClearPerFaceMaterialChannelIndices(); + + /* + Returns: + True if one or more faces have per face material channel index overrides. + Remarks: + Per face material channel indices are a mutable property on ON_BrepFace and are set with ON_BrepFace.SetMaterialChannelIndex(). + */ + bool HasPerFaceMaterialChannelIndices() const; + + /* + Description: + Removes all per face color overrides. + Returns: + Number of changed faces. + Remarks: + Per face colors are a mutable property on ON_BrepFace and are set with ON_BrepFace.SetPerFaceColor(). + */ + unsigned int ClearPerFaceColors() const; + + /* + Returns: + True if one or more faces have per face color overrides. + Remarks: + Per face colors are a mutable property on ON_BrepFace and are set with ON_BrepFace.SetPerFaceColor(). + */ + bool HasPerFaceColors() const; + + ///////////////////////////////////////////////////////////////// + // "Expert" Interface + + void Set_user(ON_U u) const; // set every brep m_*_user value to u + void Clear_vertex_user_i() const; // zero all brep's m_vertex_user values + void Clear_edge_user_i(int) const; // zero all brep's m_edge_user values + void Clear_edge_user_i() const; // zero all brep's m_edge_user values + void Clear_trim_user_i() const; // zero all brep's m_trim_user values + void Clear_loop_user_i() const; // zero all brep's m_loop_user values + void Clear_face_user_i() const; // zero all brep's m_face_user values + void Clear_user_i() const; // zero all brep's m_*_user values + + // Union available for application use. + // The constructor zeros m_brep_user. + // The value is of m_brep_user is not saved in 3DM + // archives and may be changed by some computations. + mutable ON_U m_brep_user; + + // geometry + // (all geometry is deleted by ~ON_Brep(). Pointers can be nullptr + // or not referenced. Use Compact() to remove unreferenced geometry. + ON_CurveArray m_C2; // Pointers to parameter space trimming curves + // (used by trims). + ON_CurveArray m_C3; // Pointers to 3d curves (used by edges). + ON_SurfaceArray m_S; // Pointers to parametric surfaces (used by faces) + + // topology + // (all topology is deleted by ~ON_Brep(). Objects can be unreferenced. + // Use Compact() to to remove unreferenced geometry. + ON_BrepVertexArray m_V; // vertices + ON_BrepEdgeArray m_E; // edges + ON_BrepTrimArray m_T; // trims + ON_BrepLoopArray m_L; // loops + ON_BrepFaceArray m_F; // faces + +protected: + friend class ON_BrepFace; + friend class ON_BrepRegion; + friend class ON_BrepFaceSide; + friend class ON_V5_BrepRegionTopologyUserData; + ON_BoundingBox m_bbox; + mutable class ON_BrepRegionTopology* m_region_topology = nullptr; + static class ON_BrepRegionTopology* Internal_RegionTopologyPointer( + const ON_Brep* brep, + bool bValidateFaceCount + ); + void Internal_AttachV5RegionTopologyAsUserData( + ON_BinaryArchive& archive + ) const; + + + // m_aggregate_status "should" be an ON_AggregateComponentStatusEx, + // but that change requires breaking the C++ SDK. + mutable ON_AggregateComponentStatus m_aggregate_status; + + // Never directly set m_is_solid, use calls to IsSolid() and/or + // SolidOrientation() when you need to know the answer to this + // question. + // 0 = unset + // 1 = solid with normals pointing out + // 2 = solid with normals pointing in + // 3 = not solid + int m_is_solid = 0; + +public: + // Not ideal - used in debugging and testing + //bool GetLock(); + //bool GetLockOrReturnFalse(); + //bool ReturnLock(); + +private: + // In calculations where multiple threads are using a brep and calling functions + // that may modify content, the calling code can use use ON_SleepLockGuard guard(Mutex) + // or similar techniques to make the calculations thread safe. + // Because Mutex is a public resource, it must be used with great care to + // prevent lock contention. + friend class ON_SleepLockGuard; + mutable ON_SleepLock m_sleep_lock; + +protected: + // These are friends so legacy tol values stored in v1 3dm files + // can be used to set brep edge and trimming tolerances with a call + // to ON_Brep::SetTolsFromLegacyValues(). + friend bool ON_BinaryArchive::ReadV1_TCODE_LEGACY_FAC(ON_Object**,ON_3dmObjectAttributes*); + friend bool ON_BinaryArchive::ReadV1_TCODE_LEGACY_SHL(ON_Object**,ON_3dmObjectAttributes*); + void Initialize(); + + // helpers to set ON_BrepTrim::m_iso flag + void SetTrimIsoFlag(int,double[6]); + void SetTrimIsoFlag(int); + + // helpers to create and set vertices + bool SetEdgeVertex(const int, const int, const int ); + bool HopAcrossEdge( int&, int& ) const; + bool SetTrimStartVertex( const int, const int); + void SetLoopVertices(const int); + void ClearTrimVertices(); + void ClearEdgeVertices(); + + // helpers for SwapFaceParameters() + bool SwapLoopParameters( + int // index of loop + ); + bool SwapTrimParameters( + int // index of trim + ); + + // helpers for validation checking + bool IsValidTrim(int trim_index,ON_TextLog* text_log) const; + bool IsValidTrimTopology(int trim_index,ON_TextLog* text_log) const; + bool IsValidTrimGeometry(int trim_index,ON_TextLog* text_log) const; + bool IsValidTrimTolerancesAndFlags(int trim_index,ON_TextLog* text_log) const; + + bool IsValidLoop(int loop_index,ON_TextLog* text_log) const; + bool IsValidLoopTopology(int loop_index,ON_TextLog* text_log) const; + bool IsValidLoopGeometry(int loop_index,ON_TextLog* text_log) const; + bool IsValidLoopTolerancesAndFlags(int loop_index,ON_TextLog* text_log) const; + + bool IsValidFace(int face_index,ON_TextLog* text_log) const; + bool IsValidFaceTopology(int face_index,ON_TextLog* text_log) const; + bool IsValidFaceGeometry(int face_index,ON_TextLog* text_log) const; + bool IsValidFaceTolerancesAndFlags(int face_index,ON_TextLog* text_log) const; + + bool IsValidEdge(int edge_index,ON_TextLog* text_log) const; + bool IsValidEdgeTopology(int edge_index,ON_TextLog* text_log) const; + bool IsValidEdgeGeometry(int edge_index,ON_TextLog* text_log) const; + bool IsValidEdgeTolerancesAndFlags(int edge_index,ON_TextLog* text_log) const; + + bool IsValidVertex(int vertex_index,ON_TextLog* text_log) const; + bool IsValidVertexTopology(int vertex_index,ON_TextLog* text_log) const; + bool IsValidVertexGeometry(int vertex_index,ON_TextLog* text_log) const; + bool IsValidVertexTolerancesAndFlags(int vertex_index,ON_TextLog* text_log) const; + + void SetTolsFromLegacyValues(); + + // read helpers to support various versions + bool ReadOld100( ON_BinaryArchive& ); // reads legacy old RhinoIO toolkit b-rep + bool ReadOld101( ON_BinaryArchive& ); // reads legacy Rhino 1.1 b-rep + bool ReadOld200( ON_BinaryArchive&, int ); // reads legacy trimmed surface + ON_Curve* Read100_BrepCurve( ON_BinaryArchive& ) const; + ON_Surface* Read100_BrepSurface( ON_BinaryArchive& ) const; + + // helpers for reading legacy v1 trimmed surfaces and breps + bool ReadV1_LegacyTrimStuff( ON_BinaryArchive&, ON_BrepFace&, ON_BrepLoop& ); + bool ReadV1_LegacyTrim( ON_BinaryArchive&, ON_BrepFace&, ON_BrepLoop& ); + bool ReadV1_LegacyLoopStuff( ON_BinaryArchive&, ON_BrepFace& ); + bool ReadV1_LegacyLoop( ON_BinaryArchive&, ON_BrepFace& ); + bool ReadV1_LegacyFaceStuff( ON_BinaryArchive& ); + bool ReadV1_LegacyShellStuff( ON_BinaryArchive& ); + + + +public: + // The ON_Brep code increments ON_Brep::ErrorCount everytime something + // unexpected happens. This is useful for debugging. + static unsigned int ErrorCount; + +private: + /* + Parameters: + bLazy - [in] + If true and if ON_BrepFace.m_bbox is not empty, then ON_BrepFace.m_bbox is returned. + In all other cases the bbox is calculated from scratch. + bUpdateCachedBBox - [in] + If true and the bounding box is calculated, then the value is saved in ON_BrepFace.m_bbox + so future lazy evaluations can use the value. + */ + const ON_BoundingBox InternalBrepBoundingBox(bool bLazy, bool bUpdateCachedBBox) const; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// brep construction tools +// + +/* +Description: + Create a brep representation of a mesh. +Parameters: + mesh_topology - [in] + bTrimmedTriangles - [in] if true, triangles in the mesh + will be represented by trimmed planes in the brep. + If false, triangles in the mesh will be represented by + untrimmed singular bilinear NURBS surfaces in the brep. + pBrep - [in] If not nullptr, this the mesh representation will + be put into this brep. +Example: + + ON_Mesh mesh = ...; + ON_Brep* pBrep = ON_BrepFromMesh( mesh.Topology() ); + ... + delete pBrep; + +See Also + ON_BrepFromMesh( const ON_Mesh& mesh, ... ); +*/ +ON_DECL +ON_Brep* ON_BrepFromMesh( + const ON_MeshTopology& mesh_topology, + bool bTrimmedTriangles = true, + ON_Brep* pBrep = nullptr + ); + +/* +Description: + Get an ON_Brep definition of a box. +Parameters: + box_corners - [in] 8 points defining the box corners + arranged as the vN labels indicate. + + v7_______e6_____v6 + |\ |\ + | e7 | e5 + | \ ______e4_____\ + e11 v4 | v5 + | | e10 | + | | | | + v3---|---e2----v2 e9 + \ e8 \ | + e3 | e1 | + \ | \ | + \v0_____e0_____\v1 + + pBrep - [in] if not nullptr, this brep will be used and + returned. +Returns: + An ON_Brep representation of the box with topology + + edge vertices + m_E[ 0] m_V[0], m_V[1] + m_E[ 1] m_V[1], m_V[2] + m_E[ 2] m_V[2], m_V[3] + m_E[ 3] m_V[3], m_V[0] + m_E[ 4] m_V[4], m_V[5] + m_E[ 5] m_V[5], m_V[6] + m_E[ 6] m_V[6], m_V[7] + m_E[ 7] m_V[7], m_V[4] + m_E[ 8] m_V[0], m_V[4] + m_E[ 9] m_V[1], m_V[5] + m_E[10] m_V[2], m_V[6] + m_E[11] m_V[3], m_V[7] + + face boundary edges + m_F[0] +m_E[0] +m_E[9] -m_E[4] -m_E[8] + m_F[1] +m_E[1] +m_E[10] -m_E[5] -m_E[9] + m_F[2] +m_E[2] +m_E[11] -m_E[6] -m_E[10] + m_F[3] +m_E[3] +m_E[8] -m_E[7] -m_E[11] + m_F[4] -m_E[3] -m_E[2] -m_E[1] -m_E[0] +// m_F[5] +m_E[4] +m_E[5] +m_E[6] +m_E[7] +*/ +ON_DECL +ON_Brep* ON_BrepBox( const ON_3dPoint* box_corners, ON_Brep* pBrep = nullptr ); + +/* +Description: + Get an ON_Brep definition of a wedge. +Parameters: + corners - [in] 6 points defining the box corners + arranged as the vN labels indicate. + + /v5 + /|\ + / | \ + e5 | e4 + / e8 \ + /__e3_____\ + v3| | |v4 + | | | + | /v2 | + e6 / \ e7 + | / \ | + | e2 e1| + |/ \| + /____e0___\ + v0 v1 + + pBrep - [in] if not nullptr, this brep will be used and + returned. +Returns: + An ON_Brep representation of the wedge with topology + + edge vertices + m_E[ 0] m_V[0], m_V[1] + m_E[ 1] m_V[1], m_V[2] + m_E[ 2] m_V[2], m_V[0] + m_E[ 3] m_V[3], m_V[4] + m_E[ 4] m_V[4], m_V[5] + m_E[ 5] m_V[5], m_V[0] + m_E[ 6] m_V[0], m_V[3] + m_E[ 7] m_V[1], m_V[4] + m_E[ 8] m_V[2], m_V[5] + + face boundary edges + m_F[0] +m_E[0] +m_E[7] -m_E[3] -m_E[6] + m_F[1] +m_E[1] +m_E[8] -m_E[4] -m_E[7] + m_F[2] +m_E[2] +m_E[6] -m_E[5] -m_E[8] + m_F[3] +m_E[3] +m_E[8] -m_E[7] -m_E[11] + m_F[4] -m_E[2] -m_E[1] -m_E[0] + m_F[5] +m_E[3] +m_E[4] +m_E[5] +*/ +ON_DECL +ON_Brep* ON_BrepWedge( const ON_3dPoint* corners, ON_Brep* pBrep = nullptr ); + +/* +Description: + Get an ON_Brep definition of a sphere. +Parameters: + sphere - [in] + pBrep - [in] if not nullptr, this brep will be used and + returned. +Returns: + An ON_Brep representation of the sphere with a single face, + a single edge along the seam, and vertices at the north + and south poles. +*/ +ON_DECL +ON_Brep* ON_BrepSphere( const ON_Sphere& sphere, ON_Brep* pBrep = nullptr ); + +/* +Description: + Get an ON_Brep definition of a sphere. +Parameters: + Center - [in] Center of sphere + radius - [int] Radius of sphere + pBrep - [in] if not nullptr, this brep will be used and + returned. +Returns: + An ON_Brep representation of the sphere with six similar faces, + each an untrimmed rational quadratic surface +*/ +ON_DECL +ON_Brep* ON_BrepQuadSphere( const ON_3dPoint& Center, double radius, ON_Brep* pBrep = nullptr ); + +/* +Description: + Get an ON_Brep definition of a torus. +Parameters: + torus - [in] + pBrep - [in] if not nullptr, this brep will be used and + returned. +Returns: + An ON_Brep representation of the torus with a single face + a two edges along the seams. +*/ +ON_DECL +ON_Brep* ON_BrepTorus( const ON_Torus& torus, ON_Brep* pBrep = nullptr ); + +/* +Description: + Get an ON_Brep definition of a cylinder. +Parameters: + cylinder - [in] cylinder.IsFinite() must be true + bCapBottom - [in] if true end at cylinder.m_height[0] should be capped + bCapTop - [in] if true end at cylinder.m_height[1] should be capped + pBrep - [in] if not nullptr, this brep will be used and + returned. +Returns: + An ON_Brep representation of the cylinder with a single + face for the cylinder, an edge along the cylinder seam, + and vertices at the bottom and top ends of this seam edge. + The optional bottom/top caps are single faces with one + circular edge starting and ending at the bottom/top vertex. +*/ +ON_DECL +ON_Brep* ON_BrepCylinder( const ON_Cylinder& cylinder, + bool bCapBottom, + bool bCapTop, + ON_Brep* pBrep = nullptr ); + +/* +Description: + Get an ON_Brep definition of a cone. +Parameters: + cylinder - [in] cylinder.IsFinite() must be true + bCapBase - [in] if true the base of the cone should be capped. + pBrep - [in] if not nullptr, this brep will be used and + returned. +Returns: + An ON_Brep representation of the cone with a single + face for the cone, an edge along the cone seam, + and vertices at the base and apex ends of this seam edge. + The optional cap is a single face with one circular edge + starting and ending at the base vertex. +*/ +ON_DECL +ON_Brep* ON_BrepCone( + const ON_Cone& cone, + bool bCapBottom, + ON_Brep* pBrep = nullptr + ); + +/* +Description: + Get an ON_Brep form of a surface of revolution. +Parameters: + pRevSurface - [in] pointer to a surface of revolution. + The brep will manage this pointer and delete it in ~ON_Brep. + bCapStart - [in] if true, the start of the revolute is + not on the axis of revolution, and the surface of revolution + is closed, then a circular cap will be added to close + of the hole at the start of the revolute. + bCapEnd - [in] if true, the end of the revolute is + not on the axis of revolution, and the surface of revolution + is closed, then a circular cap will be added to close + of the hole at the end of the revolute. + pBrep - [in] if not nullptr, this brep will be used and + returned. +Returns: + @untitled table + true successful + false brep cannot be created from this surface. +Remarks: + The surface class must be created with new because + it will be destroyed with the delete operator + in ~ON_Brep. +*/ +ON_DECL +ON_Brep* ON_BrepRevSurface( + ON_RevSurface*& pRevSurface, + bool bCapStart, + bool bCapEnd, + ON_Brep* pBrep = nullptr + ); + + + +/* +Description: + Create an ON_Brep trimmed plane. +Parameters: + plane - [in] plane that will be trimmed. + boundary - [in] a simple (no self intersections) closed + curve that defines the outer boundary of the trimmed + plane. This curve is copied for use in the brep. + pBrep - [in] if not nullptr, this brep will be used and returned. +Returns: + An ON_Brep representation of the trimmed plane with a single face. +See Also: + ON_Brep::NewPlanarFaceLoop() +*/ +ON_DECL +ON_Brep* ON_BrepTrimmedPlane( + const ON_Plane& plane, + const ON_Curve& boundary, + ON_Brep* pBrep = nullptr ); + +/* +Description: + Get an ON_Brep definition of a trimmed plane. +Parameters: + plane - [in] plane that will be trimmed. + boundary - [in] a list of 3d curves that form a simple + (no self intersections) closed curve that defines the + outer boundary of the trimmed plane. + bDuplicateCurves - [in] if true, duplicates of the + curves in the boundary array are used in the brep. If false + the curves in the boundary array are used in the brep + and the brep's destructor will delete the curves. + pBrep - [in] if not nullptr, this brep will be used and + returned. +Returns: + An ON_Brep representation of the trimmed plane with a singe face. +See Also: + ON_Brep::NewPlanarFaceLoop() +*/ +ON_DECL +ON_Brep* ON_BrepTrimmedPlane( + const ON_Plane& plane, + ON_SimpleArray& boundary, + bool bDuplicateCurves = true, + ON_Brep* pBrep = nullptr ); + + +/* +Description: + Extrude a brep +Parameters: + brep - [in/out] + path_curve - [in] path to extrude along. + bCap - [in] if true, the extrusion is capped with a translation + of the input brep. +Returns: + True if successful. +See Also: + ON_BrepExtrudeFace + ON_BrepExtrudeLoop + ON_BrepExtrudeEdge + ON_BrepExtrudeVertex + ON_BrepConeFace + ON_BrepConeLoop + ON_BrepConeEdge +Remarks: + The new faces are appended to brep.m_F[]. It is the caller's + responsibility to insure the result does not self intersect. +*/ +ON_DECL +bool ON_BrepExtrude( + ON_Brep& brep, + const ON_Curve& path_curve, + bool bCap = true + ); + +/* +Description: + Extrude a face in a brep. +Parameters: + brep - [in/out] + face_index - [in] index of face to extrude. + path_curve - [in] path to extrude along. + bCap - [in] if true, the extrusion is capped with a translation + of the face being extruded. +Example: + Extrude a face along a vector. + + ON_Brep brep = ...; + int face_index = ...; + ON_3dVector v = ...; + ON_LineCurve line_curve( ON_Line( ON_3dPoint::Origin, vector ) ); + ON_BrepExtrudeFace( brep, face_index, line_curve, true ); + +Returns: + @untitled table + 0 failure + 1 successful - no cap added + 2 successful - cap added as last face +See Also: + ON_BrepExtrude + ON_BrepExtrudeLoop + ON_BrepExtrudeEdge + ON_BrepExtrudeVertex + ON_BrepConeFace + ON_BrepConeLoop + ON_BrepConeEdge +Remarks: + The new faces are appended to brep.m_F[]. If a cap is requested + it is the last face in the returned brep.m_F[] +*/ +ON_DECL +int ON_BrepExtrudeFace( + ON_Brep& brep, + int face_index, + const ON_Curve& path_curve, + bool bCap = true + ); + +/* +Description: + Extrude a loop in a brep. +Parameters: + brep - [in/out] + loop_index - [in] index of face to extrude. + path_curve - [in] path to extrude along. + bCap - [in] if true and the loop is closed, the extrusion + is capped. +Returns: + @untitled table + 0 failure + 1 successful - no cap added + 2 successful - cap added as last face +See Also: + ON_BrepExtrude + ON_BrepExtrudeFace + ON_BrepExtrudeEdge + ON_BrepExtrudeVertex + ON_BrepConeFace + ON_BrepConeLoop + ON_BrepConeEdge +Remarks: + The new faces are appended to brep.m_F[]. If a cap is requested + it is the last face in the returned brep.m_F[] +*/ +ON_DECL +int ON_BrepExtrudeLoop( + ON_Brep& brep, + int loop_index, + const ON_Curve& path_curve, + bool bCap = true + ); + +/* +Description: + Extrude an edge in a brep. +Parameters: + brep - [in/out] + edge_index - [in] index of face to extrude. + path_curve - [in] path to extrude along. +Returns: + @untitled table + 0 failure + 1 successful +See Also: + ON_BrepExtrude + ON_BrepExtrudeFace + ON_BrepExtrudeLoop + ON_BrepExtrudeVertex + ON_BrepConeFace + ON_BrepConeLoop + ON_BrepConeEdge +Remarks: + The new face is appended to brep.m_F[]. +*/ +ON_DECL +int ON_BrepExtrudeEdge( + ON_Brep& brep, + int edge_index, + const ON_Curve& path_curve + ); + + +/* +Description: + Extrude a vertex in a brep. +Parameters: + brep - [in/out] + vertex_index - [in] index of vertex to extrude. + path_curve - [in] path to extrude along. +Returns: + @untitled table + 0 failure + 1 successful +See Also: + ON_BrepExtrude + ON_BrepExtrudeFace + ON_BrepExtrudeLoop + ON_BrepExtrudeEdge + ON_BrepConeFace + ON_BrepConeLoop + ON_BrepConeEdge +Remarks: + The new vertex is appended to brep.m_V[] and + the new edge is appended to brep.m_E[]. +*/ +ON_DECL +int ON_BrepExtrudeVertex( + ON_Brep& brep, + int vertex_index, + const ON_Curve& path_curve + ); + + +/* +Description: + Cone a face in a brep. +Parameters: + brep - [in/out] + face_index - [in] index of face to extrude. + apex_point - [in] apex of cone. +Returns: + @untitled table + 0 failure + 1 successful +See Also: + ON_BrepExtrudeFace + ON_BrepExtrudeLoop + ON_BrepExtrudeEdge + ON_BrepExtrudeVertex + ON_BrepConeFace + ON_BrepConeLoop + ON_BrepConeEdge +Remarks: + The new faces are appended to brep.m_F[]. +*/ +ON_DECL +int ON_BrepConeFace( + ON_Brep& brep, + int face_index, + ON_3dPoint apex_point + ); + +/* +Description: + Cone a loop in a brep. +Parameters: + brep - [in/out] + loop_index - [in] index of face to extrude. + apex_point - [in] apex of cone. +Returns: + @untitled table + 0 failure + 1 successful +See Also: + ON_BrepExtrudeFace + ON_BrepExtrudeLoop + ON_BrepExtrudeEdge + ON_BrepExtrudeVertex + ON_BrepConeFace + ON_BrepConeLoop + ON_BrepConeEdge +Remarks: + The new faces are appended to brep.m_F[]. +*/ +ON_DECL +bool ON_BrepConeLoop( + ON_Brep& brep, + int loop_index, + ON_3dPoint apex_point + ); + +/* +Description: + Cone an edge in a brep. +Parameters: + brep - [in/out] + edge_index - [in] index of face to extrude. + apex_point - [in] apex of cone. +Returns: + @untitled table + 0 failure + 1 successful +See Also: + ON_BrepExtrudeFace + ON_BrepExtrudeLoop + ON_BrepExtrudeEdge + ON_BrepExtrudeVertex + ON_BrepConeFace + ON_BrepConeLoop + ON_BrepConeEdge +Remarks: + The new face is appended to brep.m_F[]. +*/ +ON_DECL +int ON_BrepConeEdge( + ON_Brep& brep, + int edge_index, + ON_3dPoint apex_point + ); + +//These merge adjacent faces that have the same underlying surface. +ON_DECL +int ON_BrepMergeFaces(ON_Brep& B, int fid0, int fid1); + +ON_DECL +bool ON_BrepMergeFaces(ON_Brep& B); + +//This removes all slit trims from F that are not joined to another face. +//Unlike ON_Brep::RemoveSlits(), this will remove slit pairs from a loop in cases +//that will result in the creation of more loops. Caller is responsible for calling +//ON_Brep::Compact() to get rid of deleted trims and loops. + +ON_DECL +bool ON_BrepRemoveSlits(ON_BrepFace& F); + +//Merges all possible edges +ON_DECL +void ON_BrepMergeAllEdges(ON_Brep& B); + +/* +Description: + Merges two breps into a single brep. The + result may be non-manifold or have multiple + connected components. +Parameters: + brep0 - [in] + brep1 - [in] + tolerance - [in] +Returns: + Merged brep or nullptr if calculation failed. +*/ +ON_DECL +ON_Brep* ON_MergeBreps( + const ON_Brep& brep0, + const ON_Brep& brep1, + double tolerance + ); + +/* +Description: + Very low level utility. Order edges around a vertex. +Parameters: + B - [in] + vid - [in] + trim_ends - [out] trim_ends[a].i is a trim index, trim_ends[a].j is 0 for start or 1 for end. + The nth is B.m_T[trim_ends[n].i].Edge(). If bClosed is false, then the first and last edges will be naked. + bClosed - [out] If true, then all edges at the vertex have exactly two trims +Returns: + True if the order can be found. If any edge at the vertex is non-manifold, or if more than two are naked, then false. +*/ +ON_DECL +bool ON_OrderEdgesAroundVertex(const ON_Brep& B, int vid, + ON_SimpleArray& trim_ends, + bool& bClosed); + + +/* +Description: +Very low level utility. Order edges around a vertex. +Parameters: +B - [in] +vid - [in] +trim_ends - [out] trim_ends[a].i is a trim index, trim_ends[a].j is 0 for start or 1 for end. +The nth is B.m_T[trim_ends[n].i].Edge(). If bClosed is false, then the first and last edges will be naked. +Must have at least as many ON2dex as the vertex has edges. +bClosed - [out] If true, then all edges at the vertex have exactly two trims +Returns: +True if the order can be found. If any edge at the vertex is non-manifold, or if more than two are naked, then false. +NOTE: If you don't know how many edges are at the vertex, call the version that takes an ON_SimpleArray. +*/ +ON_DECL +bool ON_OrderEdgesAroundVertex(const ON_Brep& B, int vid, + ON_2dex* trim_ends,//Must be at as big as the edge count at the vertex + bool& bClosed); + + + + + + +#if defined(ON_COMPILING_OPENNURBS) +////////////////////////////////////////////////////////////////////////// +// +// ON_BrepIncrementErrorCount() +// +// Appears in places where the code traps error conditions. +// Putting a breakpoint on the line indicated below is an easy way +// to have the debugger break on all error conditions and inspect +// the first place something goes wrong in a complex calculation. +// +void ON_BrepIncrementErrorCount(); // defined in opennurbs_error.cpp +#define ON_BREP_ERROR(msg) (ON_BrepIncrementErrorCount(), ON_ERROR(msg)) +#define ON_BREP_RETURN_ERROR(rc) (ON_BrepIncrementErrorCount(), rc) +#define ON_BREP_RETURN_ERROR_MSG(msg, rc) \ + (ON_BrepIncrementErrorCount(), ON_ERROR(msg), rc) +#endif + +#endif diff --git a/opennurbs/Include/opennurbs_circle.h b/opennurbs/Include/opennurbs_circle.h new file mode 100644 index 0000000..81396f9 --- /dev/null +++ b/opennurbs/Include/opennurbs_circle.h @@ -0,0 +1,325 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_CIRCLE_INC_) +#define ON_CIRCLE_INC_ + +class ON_NurbsCurve; + +/* +Description: + ON_Circle is a circle in 3d. The cirle is represented by a radius and an + orthonormal frame of the plane containing the circle, with origin at the center. + + An Is_Valid() circle has positive radius and an Is_ Valid() plane defining the frame. + + The circle is parameterized by radians from 0 to 2 Pi given by + t -> center + cos(t)*radius*xaxis + sin(t)*radius*yaxis + where center, xaxis and yaxis define the orthonormal frame of the circle's plane. +*/ +class ON_CLASS ON_Circle +{ +public: + + ON_Plane plane = ON_Plane::World_xy; + double radius = 1.0; + + ON_Circle() = default; + ~ON_Circle() = default; + ON_Circle(const ON_Circle&) = default; + ON_Circle& operator=(const ON_Circle&) = default; + + static const ON_Circle UnitCircle; // unit circle in the xy plane + + // Creates a circle in the plane with center at + // plane.origin. + ON_Circle( + const ON_Plane& plane, + double radius + ); + + // Creates a circle parallel to the world XY plane + // with given center and radius + ON_Circle( + const ON_3dPoint& center, + double radius + ); + + // Creates a circle parallel to the plane + // with given center and radius. + ON_Circle( + const ON_Plane& plane, + const ON_3dPoint& center, + double radius + ); + + // Create a circle through three 2d points. + // The start/end of the circle is at point P. + ON_Circle( // circle through 3 2d points + const ON_2dPoint& P, + const ON_2dPoint& Q, + const ON_2dPoint& R + ); + + // Create a circle through three 3d points. + // The start/end of the circle is at point P. + ON_Circle( + const ON_3dPoint& P, + const ON_3dPoint& Q, + const ON_3dPoint& R + ); + + // Creates a circle in the plane with center at + // plane.origin. + bool Create( + const ON_Plane& plane, + double radius + ); + + // Creates a circle parallel to the world XY plane + // with given center and radius + bool Create( + const ON_3dPoint& center, + double radius + ); + + // Creates a circle parallel to the plane + // with given centr and radius. + bool Create( + const ON_Plane& plane, + const ON_3dPoint& center, + double radius + ); + + // Create a circle through three 2d points. + // The start/end of the circle is at point P. + bool Create( // circle through 3 2d points + const ON_2dPoint& P, + const ON_2dPoint& Q, + const ON_2dPoint& R + ); + + // Create a circle through three 3d points. + // The start/end of the circle is at point P. + bool Create( + const ON_3dPoint& P, + const ON_3dPoint& Q, + const ON_3dPoint& R + ); + + // Create a circle from two 2d points and a + // tangent at the first point. + // The start/end of the circle is at point P. + bool Create( + const ON_2dPoint& P, + const ON_2dVector& tangent_at_P, + const ON_2dPoint& Q + ); + + // Create a circle from two 3d points and a + // tangent at the first point. + // The start/end of the circle is at point P. + bool Create( + const ON_3dPoint& P, + const ON_3dVector& tangent_at_P, + const ON_3dPoint& Q + ); + + // A Valid circle has m_radius>0 and m_plane.IsValid(). + bool IsValid() const; + + //bool UpdatePoints(); // sets m_point[] to have valid points + + bool IsInPlane( const ON_Plane&, double = ON_ZERO_TOLERANCE ) const; + + double Radius() const; + double Diameter() const; + double Circumference() const; + const ON_3dPoint& Center() const; + const ON_3dVector& Normal() const; + const ON_Plane& Plane() const; // plane containing circle + + ON_BoundingBox BoundingBox() const; + + /* + Description: + Get tight bounding box. + Parameters: + tight_bbox - [in/out] tight bounding box + bGrowBox -[in] (default=false) + If true and the input tight_bbox is valid, then returned + tight_bbox is the union of the input tight_bbox and the + arc's tight bounding box. + xform -[in] (default=nullptr) + If not nullptr, the tight bounding box of the transformed + arc is calculated. The arc is not modified. + Returns: + True if a valid tight_bbox is returned. + */ + bool GetTightBoundingBox( + ON_BoundingBox& tight_bbox, + bool bGrowBox = false, + const ON_Xform* xform = nullptr + ) const; + + bool Transform( const ON_Xform& ); + + // Circles use trigonometric parameterization + // t -> center + cos(t)*radius*xaxis + sin(t)*radius*yaxis + ON_3dPoint PointAt( + double // evaluation parameter + ) const; + ON_3dVector DerivativeAt( + int, // derivative (>=0) + double // evaluation parameter + ) const; + + ON_3dVector TangentAt(double) const; + + // returns parameters of point on circle that is closest to given point + bool ClosestPointTo( + const ON_3dPoint& point, + double* t + ) const; + + // returns point on circle that is closest to given point + ON_3dPoint ClosestPointTo( + const ON_3dPoint& point + ) const; + + // evaluate circle's implicit equation in plane + double EquationAt( const ON_2dPoint& plane_point ) const; + + ON_2dVector GradientAt( const ON_2dPoint& plane_point ) const; + + // rotate circle about its center + bool Rotate( + double sin_angle, + double cos_angle, + const ON_3dVector& axis_of_rotation + ); + + bool Rotate( + double angle_in_radians, + const ON_3dVector& axis_of_rotation + ); + + // rotate circle about a point and axis + bool Rotate( + double sin_angle, + double cos_angle, + const ON_3dVector& axis_of_rotation, + const ON_3dPoint& center_of_rotation + ); + + bool Rotate( + double angle_in_radians, + const ON_3dVector& axis_of_rotation, + const ON_3dPoint& center_of_rotation + ); + + bool Translate( + const ON_3dVector& delta + ); + + bool Reverse(); + + // Description: + // Get a four span rational degree 2 NURBS circle representation + // of the circle. + // Returns: + // 2 for success, 0 for failure + // Remarks: + // Note that the parameterization of NURBS curve + // does not match circle's transcendental paramaterization. + // Use ON_Circle::GetRadianFromNurbFormParameter() and + // ON_Circle::GetParameterFromRadian() to convert between + // the NURBS curve parameter and the transcendental parameter. + int GetNurbForm( + ON_NurbsCurve& nurbs_curve + ) const; + + /* + Description: + Convert a NURBS curve circle parameter to a circle radians parameter. + Parameters: + nurbs_parameter - [in] + circle_radians_parameter - [out] + Example: + + ON_Circle circle = ...; + double nurbs_t = 1.2345; // some number in interval (0,2.0*ON_PI). + double circle_t; + circle.GetRadianFromNurbFormParameter( nurbs_t, &circle_t ); + + ON_NurbsCurve nurbs_curve; + circle.GetNurbsForm( nurbs_curve ); + circle_pt = circle.PointAt(circle_t); + nurbs_pt = nurbs_curve.PointAt(nurbs_t); + // circle_pt and nurbs_pt will be the same + + Remarks: + The NURBS curve parameter is with respect to the NURBS curve + created by ON_Circle::GetNurbForm. At nurbs parameter values of + 0.0, 0.5*ON_PI, ON_PI, 1.5*ON_PI, and 2.0*ON_PI, the nurbs + parameter and radian parameter are the same. At all other + values the nurbs and radian parameter values are different. + See Also: + ON_Circle::GetNurbFormParameterFromRadian + */ + bool GetRadianFromNurbFormParameter( + double nurbs_parameter, + double* circle_radians_parameter + ) const; + + /* + Description: + Convert a circle radians parameter to a NURBS curve circle parameter. + Parameters: + circle_radians_parameter - [in] 0.0 to 2.0*ON_PI + nurbs_parameter - [out] + Example: + + ON_Circle circle = ...; + double circle_t = 1.2345; // some number in interval (0,2.0*ON_PI). + double nurbs_t; + circle.GetNurbFormParameterFromRadian( circle_t, &nurbs_t ); + + ON_NurbsCurve nurbs_curve; + circle.GetNurbsForm( nurbs_curve ); + circle_pt = circle.PointAt(circle_t); + nurbs_pt = nurbs_curve.PointAt(nurbs_t); + // circle_pt and nurbs_pt will be the same + + Remarks: + The NURBS curve parameter is with respect to the NURBS curve + created by ON_Circle::GetNurbForm. At radian values of + 0.0, 0.5*ON_PI, ON_PI, 1.5*ON_PI, and 2.0*ON_PI, the nurbs + parameter and radian parameter are the same. At all other + values the nurbs and radian parameter values are different. + See Also: + ON_Circle::GetNurbFormParameterFromRadian + */ + bool GetNurbFormParameterFromRadian( + double circle_radians_parameter, + double* nurbs_parameter + ) const; + +}; + + +#endif + diff --git a/opennurbs/Include/opennurbs_color.h b/opennurbs/Include/opennurbs_color.h new file mode 100644 index 0000000..8f5af21 --- /dev/null +++ b/opennurbs/Include/opennurbs_color.h @@ -0,0 +1,448 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_COLOR_INC_) +#define OPENNURBS_COLOR_INC_ + +/////////////////////////////////////////////////////////////////////////////// +// +// Class ON_Color +// +class ON_CLASS ON_Color +{ +public: + ON_Color() = default; + ~ON_Color() = default; + ON_Color(const ON_Color&) = default; + ON_Color& operator=(const ON_Color&) = default; + + static const ON_Color UnsetColor; // 0xFFFFFFFFu + static const ON_Color Black; // 0x00000000u + static const ON_Color White; // 0x00FFFFFFu on little endan, 0xFFFFFF00u on big endian + static const ON_Color SaturatedRed; // 0x000000FFu on little endan, 0xFF000000u on big endian + static const ON_Color SaturatedGreen; // 0x0000FF00u on little endan, 0x00FF0000u on big endian + static const ON_Color SaturatedBlue; // 0x00FF0000u on little endan, 0x0000FF00u on big endian + static const ON_Color SaturatedYellow; // 0x0000FFFFu on little endan, 0xFFFF0000u on big endian + static const ON_Color SaturatedCyan; // 0x00FFFF00u on little endan, 0x00FFFF00u on big endian + static const ON_Color SaturatedMagenta; // 0x00FF00FFu on little endan, 0xFF00FF00u on big endian + static const ON_Color SaturatedGold; // 0x0000BFFFu on little endan, 0xFFBF0000u on big endian + static const ON_Color Gray105; // R = G = B = 105 (medium dark) + static const ON_Color Gray126; // R = G = B = 128 (medium) + static const ON_Color Gray160; // R = G = B = 160 (medium light) + static const ON_Color Gray230; // R = G = B = 230 (light) + static const ON_Color Gray250; // R = G = B = 250 (lightest) + + // If you need to use byte indexing to convert RGBA components to and from + // an unsigned int ON_Color value and want your code to work on both little + // and big endian computers, then use the RGBA_byte_index enum. + // + // unsigned int u; + // unsigned char* rgba = &y; + // rbga[ON_Color::kRedByteIndex] = red value 0 to 255. + // rbga[ON_Color::kGreenByteIndex] = green value 0 to 255. + // rbga[ON_Color::kBlueByteIndex] = blue value 0 to 255. + // rbga[ON_Color::kAlphaByteIndex] = alpha value 0 to 255. + // ON_Color color = u; + enum RGBA_byte_index : unsigned int + { + // same for both little and big endian computers. + kRedByteIndex = 0, + kGreenByteIndex = 1, + kBlueByteIndex = 2, + kAlphaByteIndex = 3 + }; + + /* + Returns: + A random color. + */ + static const ON_Color RandomColor(); + + /* + Parameters: + seed - [in] + hue_range - [in] + range of hues. Use ON_Interval::ZeroToTwoPi for all hues. + saturation_range - [in] + range of saturations. Use ON_Interval::ZeroToOne for all saturations. + value_range - [in] + range of values. Use ON_Interval::ZeroToOne for all values. + Returns: + A color generated from seed. The color for a given seed will always be the same. + */ + static const ON_Color RandomColor( + ON_Interval hue_range, + ON_Interval saturation_range, + ON_Interval value_range + ); + + /* + Returns: + A color generated from seed. The color for a given seed will always be the same. + */ + static const ON_Color RandomColor( + ON__UINT32 seed + ); + + /* + Parameters: + seed - [in] + hue_range - [in] + range of hues. Use ON_Interval::ZeroToTwoPi for all hues. + saturation_range - [in] + range of saturations. Use ON_Interval::ZeroToOne for all saturations. + value_range - [in] + range of values. Use ON_Interval::ZeroToOne for all values. + Returns: + A color generated from seed. The color for a given seed will always be the same. + */ + static const ON_Color RandomColor( + ON__UINT32 seed, + ON_Interval hue_range, + ON_Interval saturation_range, + ON_Interval value_range + ); + + // If you need to use shifting to convert RGBA components to and from + // an unsigned int ON_COlor value and you want your code to work + // on both little and big endian computers, use the RGBA_shift enum. + // + // unsigned int u = 0; + // u |= ((((unsigned int)red) & 0xFFU) << ON_Color::RGBA_shift::kRedShift); + // u |= ((((unsigned int)green) & 0xFFU) << ON_Color::RGBA_shift::kGreenShift); + // u |= ((((unsigned int)blue) & 0xFFU) << ON_Color::RGBA_shift::kBlueShift); + // u |= ((((unsigned int)alpha) & 0xFFU) << ON_Color::RGBA_shift::kAlphaShift); + // ON_Color color = u; + enum RGBA_shift : unsigned int + { +#if defined(ON_LITTLE_ENDIAN) + kRedShift = 0, + kGreenShift = 8, + kBlueShift = 16, + kAlphaShift = 24 +#elif defined(ON_BIG_ENDIAN) + kRedShift = 24, + kGreenShift = 16, + kBlueShift = 8, + kAlphaShift = 0 +#else +#error unknown endian +#endif + }; + + // Sets A = 0 + ON_Color( + int red, // ( 0 to 255 ) + int green, // ( 0 to 255 ) + int blue // ( 0 to 255 ) + ); + + ON_Color( + int red, // ( 0 to 255 ) + int green, // ( 0 to 255 ) + int blue, // ( 0 to 255 ) + int alpha // ( 0 to 255 ) (0 = opaque, 255 = transparent) + ); + + /* + Parameters: + colorref - [in] + Windows COLORREF in little endian RGBA order. + */ + ON_Color( + unsigned int colorref + ); + + // Conversion to Windows COLORREF in little endian RGBA order. + operator unsigned int() const; + + /* + Description: + Call this function when the color is needed in a + Windows COLORREF format with alpha = 0; + Returns + A Windows COLOREF with alpha = 0. + */ + unsigned int WindowsRGB() const; + + // < 0 if this < arg, 0 ir this==arg, > 0 if this > arg + int Compare( const ON_Color& ) const; + + int Red() const; // ( 0 to 255 ) + int Green() const; // ( 0 to 255 ) + int Blue() const; // ( 0 to 255 ) + int Alpha() const; // ( 0 to 255 ) (0 = opaque, 255 = transparent) + + double FractionRed() const; // ( 0.0 to 1.0 ) + double FractionGreen() const; // ( 0.0 to 1.0 ) + double FractionBlue() const; // ( 0.0 to 1.0 ) + double FractionAlpha() const; // ( 0.0 to 1.0 ) (0.0 = opaque, 1.0 = transparent) + + void SetRGB( + int red, // red in range 0 to 255 + int green, // green in range 0 to 255 + int blue // blue in range 0 to 255 + ); + + void SetFractionalRGB( + double red, // red in range 0.0 to 1.0 + double green, // green in range 0.0 to 1.0 + double blue // blue in range 0.0 to 1.0 + ); + + void SetAlpha( + int alpha // alpha in range 0 to 255 (0 = opaque, 255 = transparent) + ); + + void SetFractionalAlpha( + double alpha // alpha in range 0.0 to 1.0 (0.0 = opaque, 1.0 = transparent) + ); + + void SetRGBA( + int red, // red in range 0 to 255 + int green, // green in range 0 to 255 + int blue, // blue in range 0 to 255 + int alpha // alpha in range 0 to 255 (0 = opaque, 255 = transparent) + ); + + // input args + void SetFractionalRGBA( + double red, // red in range 0.0 to 1.0 + double green, // green in range 0.0 to 1.0 + double blue, // blue in range 0.0 to 1.0 + double alpha // alpha in range 0.0 to 1.0 (0.0 = opaque, 1.0 = transparent) + ); + + // Hue() returns an angle in the range 0 to 2*pi + // + // 0 = red, pi/3 = yellow, 2*pi/3 = green, + // pi = cyan, 4*pi/3 = blue,5*pi/3 = magenta, + // 2*pi = red + double Hue() const; + + // Returns 0.0 (gray) to 1.0 (saturated) + double Saturation() const; + + // Returns 0.0 (black) to 1.0 (white) + double Value() const; + + void SetHSV( + double h, // hue in radians 0 to 2*pi + double s, // satuation 0.0 = gray, 1.0 = saturated + double v // value + ); + + /// + /// Formats used by ON_Color::ToText() and ON_Color::ToString(). + /// + enum class TextFormat: unsigned char + { + /// + /// Indicates no format has been selected. Empty text is created. + /// + Unset = 0, + + /// + /// red,green,blue as floating point values from 0.0 to 1.0. + /// + FractionalRGB = 1, + + /// + /// red,green,blue as floating point values from 0.0 to 1.0. alpha is appended if it is not zero. + /// + FractionalRGBa = 2, + + /// + /// red,green,blue,alpha as floating point values from 0.0 to 1.0. + /// + FractionalRGBA = 3, + + /// + /// red,green,blue as decimal integers from 0 to 255. + /// + DecimalRGB = 4, + + /// + /// red,green,blue as decimal integers from 0 to 255. alpha is appended if it is not zero. + /// + DecimalRGBa = 5, + + /// + /// red,green,blue,alpha as decimal integers from 0 to 255. + /// + DecimalRGBA = 6, + + /// + /// red,green,blue as hexadecimal integers from 0 to 255. + /// + HexadecimalRGB = 7, + + /// + /// red,green,blue as hexadecimal integers from 0 to 255. alpha is appended if it is not zero. + /// + HexadecimalRGBa = 8, + + /// + /// red,green,blue,alpha as hexadecimal integers from 0 to 255. + /// + HexadecimalRGBA = 9, + + /// + /// hue (0 to 2pi), saturation (0 to 1), value (0 to 1) as floating point values. + /// + HSV = 10, + + /// + /// hue (0 to 2pi), saturation (0 to 1), value (0 to 1) as floating point values. alpha (0 to 1) is appended if it is not zero. + /// + HSVa = 11, + + /// + /// hue (0 to 2pi), saturation (0 to 1), value (0 to 1), alpha (0 to 1) as floating point values. + /// + HSVA = 12, + }; + + /* + Parameters: + format - [in] + separator - [in] + character to sepearate numbers (unicode code point - UTF-16 surrogate pairs not supported) + pass 0 for default. + bFormatUnsetColor - [in] + If true, ON_Color::UnsetColor will return "UnsetColor". Otherwise ON_Color::UnsetColor will return the empty string. + text_log - [in] + destination of the text. + */ + const ON_wString ToString( + ON_Color::TextFormat format, + wchar_t separator, + bool bFormatUnsetColor, + class ON_TextLog& text_log + ) const; + + /* + Parameters: + format - [in] + If format is ON_Color::TextFormat::Unset, then text_log.ColorFormat is used. + separator - [in] + character to sepearate numbers (unicode code point - UTF-16 surrogate pairs not supported) + pass 0 for default. + bFormatUnsetColor - [in] + If true, ON_Color::UnsetColor will return "UnsetColor". Otherwise ON_Color::UnsetColor will return the empty string. + text_log - [in] + destination of the text. + */ + void ToText( + ON_Color::TextFormat format, + wchar_t separator, + bool bFormatUnsetColor, + class ON_TextLog& text_log + ) const; + + +private: + union { + // On little endian (Intel) computers, m_color has the same byte order + // as Windows COLORREF values. + // On little endian computers, m_color = 0xaabbggrr as an unsigned int value. + // On big endian computers, m_color = 0xrrggbbaa as an unsigned int value + // rr = red component 0-255 + // gg = grean component 0-255 + // bb = blue component 0-255 + // aa = alpha 0-255. 0 means opaque, 255 means transparent. + unsigned int m_color = 0; + + // m_colorComponent is a 4 unsigned byte array in RGBA order + // red component = m_RGBA[ON_Color::RGBA_byte::kRed] + // grean component = m_RGBA[ON_Color::RGBA_byte::kGreen] + // blue component = m_RGBA[ON_Color::RGBA_byte::kBlue] + // alpha component = m_RGBA[ON_Color::RGBA_byte::kAlpha] + unsigned char m_RGBA[4]; + }; +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Class ON_ColorStop +// +// Combination of a color and a single value. Typically used for defining +// gradient fills over a series of colors. +class ON_CLASS ON_ColorStop +{ +public: + ON_ColorStop() = default; + ON_ColorStop(const ON_Color& color, double position); + + bool Write(class ON_BinaryArchive& archive) const; + bool Read(class ON_BinaryArchive& archive); + + ON_Color m_color = ON_Color::UnsetColor; + double m_position = 0; +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +#endif + + +class ON_CLASS ON_4fColor +{ +public: + ON_4fColor(); + ~ON_4fColor() = default; + ON_4fColor(const ON_4fColor&) = default; + ON_4fColor& operator=(const ON_4fColor&) = default; + + static const ON_4fColor Unset; + + //Note that these function will set the alpha correctly from ON_Colors "inverted" alpha. + ON_4fColor(const ON_Color&); + ON_4fColor& operator=(const ON_Color&); + + //Will invert the opacity alpha to transparency. + operator ON_Color(void) const; + + float Red(void) const; + void SetRed(float); + + float Green(void) const; + void SetGreen(float); + + float Blue(void) const; + void SetBlue(float); + + //Alpha in ON_4fColor is OPACITY - not transparency as in ON_Color. + float Alpha(void) const; + void SetAlpha(float); + + void SetRGBA(float r, float g, float b, float a); + + bool IsValid(class ON_TextLog* text_log = nullptr) const; + + // < 0 if this < arg, 0 ir this==arg, > 0 if this > arg + int Compare(const ON_4fColor&) const; + +private: + float m_color[4]; +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +#endif + + +#endif diff --git a/opennurbs/Include/opennurbs_compress.h b/opennurbs/Include/opennurbs_compress.h new file mode 100644 index 0000000..7d3d4f2 --- /dev/null +++ b/opennurbs/Include/opennurbs_compress.h @@ -0,0 +1,493 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_COMPRESS_INC_) +#define OPENNURBS_COMPRESS_INC_ + +typedef bool (*ON_StreamCallbackFunction)( void* context, ON__UINT32 size, const void* buffer ); + +class ON_CLASS ON_CompressStream +{ +public: + ON_CompressStream(); + virtual ~ON_CompressStream(); + + /* + Description: + ON_CompressStream delivers the compressed stream by calling + a compressed stream output handler function. There are two + options for specifying the compressed stream output handler + function. + 1. Overriding the virtual Out() function. + 2. Providing a callback function. + SetCallback() is used to specify a callback function to handle + the compressed stream and to specify a context pointer to be + passed to either option of the handler. + Parameters: + callback_function - [in] + Function to call with sections of the compressed stream. + If callback_function is null, then the virtual Out() + function will be called. When callback_function + is specified, it must return true if the compression + calculation should continue and false to cancel the + compression calculation. + callback_context - [in] + This value is passed as the first argument when calling + callback_function or the virutal Out() function. + Returns: + True if successful. + Remarks: + Once compression has started, it would be unusual to + intentionally change the compressed stream output handler, + but you can do this if you need to. + */ + bool SetCallback( + ON_StreamCallbackFunction callback_function, + void* callback_context + ); + + /* + Returns: + Current value of the callback function for handling + the compressed stream. If the callback function is + null, the the virtual Out() function is used to + handle + */ + ON_StreamCallbackFunction CallbackFunction() const; + + /* + Returns: + Current value of the context pointer passed as the first + argument to the compressed stream output handler function. + */ + void* CallbackContext() const; + + /* + Description: + Call Begin() one time to initialize the compression + calculation. Then call In() one or more times + to submit the uncompressed stream to the compression calculation. + When you reach the end of the uncompressed stream, call + End(). + Returns: + true if successful, false if an error occured. + */ + bool Begin(); + + /* + Description: + Call In() one or more times to compress a stream of uncompressed + bytes. After the last call to In(), call End(). Calling In() + may generate zero or more calls to the output stream handler. + Parameters: + in_buffer_size - [in] + number of bytes in in_buffer + in_buffer - [in] + Returns: + true if successful, false if an error occured. + */ + bool In( + ON__UINT64 in_buffer_size, + const void* in_buffer + ); + + /* + Description: + If an explicit compressed stream output handler is not specified + ( CallbackFunction() returns null ), then the virtual Out() + function is called to handle the compressed output stream. + As the input stream is compressed, one or more calls to Out() + will occur. + Returns: + True to continue compressing and false to cancel the compression + calculation. + Remarks: + In general, it is probably going to be easier to test and debug + your code if you ignore the callback_context parameter and add + a member variable to your derived class to make additional + information accessable to your Out function. + */ + virtual bool Out( + void* callback_context, + ON__UINT32 out_buffer_size, + const void* out_buffer + ); + + /* + Description: + After the last call to In(), call End(). + Calling End() may generate zero or more + calls to the output stream handler. + Returns: + true if successful, false if an error occured. + */ + bool End(); + + /* + Returns: + Then the returned value is the total number bytes in the input + stream. The size is updated every time In() is called before + any calls are made to the output stream handler. If the + calculation is finished ( End() has been called ), then the + returned value is the total number of bytes in the entire + input stream. + */ + ON__UINT64 InSize() const; + + /* + Returns: + Then the returned value is the total number bytes in the output + stream. The size is incremented immediately after each call to + the output stream handler. If the compression calculation is + finished ( End() has been called ), then the returned value is + the total number of bytes in the entire output stream. + */ + ON__UINT64 OutSize() const; + + /* + Returns: + Then the returned value is the 32-bit crc of the input stream. + The crc is updated every time In() is called before any calls + are made to the output stream handler. If the compression + calculation is finished ( End() has been called ), then the + returned value is the 32-bit crc of the entire input stream. + */ + ON__UINT32 InCRC() const; + + /* + Returns: + Then the returned value is the 32bit crc of the output stream. + The crc is updated immediately after each call to the output + stream handler. If the calculation is finished ( End() has + been called ), then the returned value is the 32-bit crc of + the entire output stream. + */ + ON__UINT32 OutCRC() const; + +private: + ON_StreamCallbackFunction m_out_callback_function; + void* m_out_callback_context; + ON__UINT64 m_in_size; + ON__UINT64 m_out_size; + ON__UINT32 m_in_crc; + ON__UINT32 m_out_crc; + void* m_implementation; + void* m_reserved; + + void ErrorHandler(); + +private: + // prohibit use - no implementation + ON_CompressStream(const ON_CompressStream&); + ON_CompressStream& operator=(const ON_CompressStream&); +}; + + +class ON_CLASS ON_UncompressStream +{ +public: + ON_UncompressStream(); + virtual ~ON_UncompressStream(); + + /* + Description: + ON_UncompressStream delivers the uncompressed stream by calling + an uncompressed stream output handler function. There are two + options for specifying the uncompressed stream output handler + function. + 1. Overriding the virtual Out() function. + 2. Providing a callback function. + SetCallback() is used to specify a callback function to handle + the uncompressed stream and to specify a context pointer to be + passed to either option of the handler. + Parameters: + callback_function - [in] + Function to call with sections of the uncompressed stream. + If callback_function is null, then the virtual Out() + function will be called. When callback_function + is specified, it must return true if the uncompression + calculation should continue and false to cancel the + uncompression calculation. + callback_context - [in] + This value is passed as the first argument when calling + callback_function or the virutal Out() function. + Returns: + True if successful. + Remarks: + Once uncompression has started, it would be unusual to + intentionally change the uncompressed stream output handler, + but you can do this if you need to. + */ + bool SetCallback( + ON_StreamCallbackFunction callback_function, + void* callback_context + ); + + /* + Returns: + Current value of the callback function for handling + the uncompressed stream. If the callback function is + null, the the virtual UncompressedStreamOut() function + is used. + */ + ON_StreamCallbackFunction CallbackFunction() const; + + /* + Returns: + Current value of the context pointer passed as the first + argument to the uncompressed stream output handler function. + */ + void* CallbackContext() const; + + /* + Description: + Call BeginUnompressStream() one time to initialize the compression + calculation. Then call In() one or more times + to submit the compressed stream to the uncompression calculation. + When you reach the end of the compressed stream, call + End(). + Returns: + true if successful, false if an error occured. + */ + bool Begin(); + + /* + Description: + Call In() one or more times to uncompress a stream of compressed + bytes. After the last call to In(), call End(). Calling End() + may generate zero or more calls to the output stream handler. + Parameters: + in_buffer_size - [in] + number of bytes in in_buffer + in_buffer - [in] + Returns: + true if successful, false if an error occured. + */ + bool In( + ON__UINT64 in_buffer_size, + const void* in_buffer + ); + + /* + Description: + If an explicit uncompressed stream handler is not specified + ( CallbackFunction() returns null ), then the virtual Out() + function is called to handle the uncompressed output stream. + As the input stream is uncompressed, one or more calls to Out() + will occur. + Returns: + True to continue uncompressing and false to cancel the + uncompression calculation. + Remarks: + In general, it is probably going to be easier to test and debug + your code if you ignore the callback_context parameter and add + a member variable to your derived class to make additional + information accessable to your Out function. + */ + virtual bool Out( + void* callback_context, + ON__UINT32 out_buffer_size, + const void* out_buffer + ); + + /* + Description: + After the last call to In(), call End(). + Calling End() may generate zero or more + calls to the output stream handler. + Returns: + true if successful, false if an error occured. + */ + bool End(); + + /* + Returns: + Then the returned value is the total number bytes in the input + stream. The size is updated every time In() is called before + any calls are made to the output stream handler. If the + calculation is finished ( End() has been called ), then the + returned value is the total number of bytes in the entire + input stream. + */ + ON__UINT64 InSize() const; + + /* + Returns: + Then the returned value is the total number bytes in the output + stream. The size is incremented immediately after each call to + the output stream handler. If the compression calculation is + finished ( End() has been called ), then the returned value is + the total number of bytes in the entire output stream. + */ + ON__UINT64 OutSize() const; + + /* + Returns: + Then the returned value is the 32-bit crc of the input stream. + The crc is updated every time In() is called before any calls + are made to the output stream handler. If the compression + calculation is finished ( End() has been called ), then the + returned value is the 32-bit crc of the entire input stream. + */ + ON__UINT32 InCRC() const; + + /* + Returns: + Then the returned value is the 32bit crc of the output stream. + The crc is updated immediately after each call to the output + stream handler. If the calculation is finished ( End() has + been called ), then the returned value is the 32-bit crc of + the entire output stream. + */ + ON__UINT32 OutCRC() const; + +private: + ON_StreamCallbackFunction m_out_callback_function; + void* m_out_callback_context; + ON__UINT64 m_in_size; + ON__UINT64 m_out_size; + ON__UINT32 m_in_crc; + ON__UINT32 m_out_crc; + void* m_implementation; + void* m_reserved; + + void ErrorHandler(); + +private: + // prohibit use - no implementation + ON_UncompressStream(const ON_UncompressStream&); + ON_UncompressStream& operator=(const ON_UncompressStream&); +}; + +/* +Description: + Simple tool for uncompressing a buffer when the output + buffer size is known. +Parameters: + sizeof_compressed_buffer - [in] + byte count + compressed_buffer - [in] + sizeof_uncompressed_buffer + byte count + uncompressed_buffer - [out] +Returns: + Number of bytes written to uncompressed_buffer. +*/ +ON_DECL +size_t ON_UncompressBuffer( + size_t sizeof_compressed_buffer, + const void* compressed_buffer, + size_t sizeof_uncompressed_buffer, + void* uncompressed_buffer + ); + +class ON_CLASS ON_CompressedBuffer +{ +public: + ON_CompressedBuffer(); + ~ON_CompressedBuffer(); + ON_CompressedBuffer(const ON_CompressedBuffer& src); + ON_CompressedBuffer& operator=(const ON_CompressedBuffer& src); + + /* + Description: + Compress inbuffer. + Parameters: + sizeof__inbuffer - [in] + Number of bytes in inbuffer. + inbuffer - [in] + Uncompressed information. + sizeof_element - [out] + This parameter only matters if the buffer will be compressed, + and decompressed on CPUs with different endianness. If this + is the case, then the types in the buffer need to have the + same size (2,4, or 8). + Returns: + True if inbuffer is successfully compressed. + */ + bool Compress( + size_t sizeof__inbuffer, // sizeof uncompressed input data + const void* inbuffer, // uncompressed input data + int sizeof_element + ); + + /* + Returns: + Number of bytes in the uncompressed information. + */ + size_t SizeOfUncompressedBuffer() const; + + /* + Description: + Uncompress the contents of this ON_CompressedBuffer. + Parameters: + outbuffer - [in/out] + This buffer must have at least SizeOfUncompressedBuffer() bytes. + If the function returns true, then the uncopressed information + is stored in this buffer. + bFailedCRC - [out] + If not null, then this boolean is set to true if the CRC + of the uncompressed information has changed. + Returns: + True if uncompressed information is returned in outbuffer. + */ + bool Uncompress( // read and uncompress + void* outbuffer, // uncompressed output data returned here + int* bFailedCRC + ) const; + + /* + Description: + Destroy the current informtion in the ON_CompressedBuffer + so the class can be reused. + */ + void Destroy(); + + bool Write(ON_BinaryArchive& binary_archive) const; + bool Read(ON_BinaryArchive& binary_archive); + + ///////////////////////////////////////////////// + // + // Implementation + // + bool CompressionInit(struct ON_CompressedBufferHelper*) const; + bool CompressionEnd(struct ON_CompressedBufferHelper*) const; + size_t DeflateHelper( // returns number of bytes written + struct ON_CompressedBufferHelper*, + size_t sizeof___inbuffer, // sizeof uncompressed input data ( > 0 ) + const void* in___buffer // uncompressed input data ( != nullptr ) + ); + bool InflateHelper( + struct ON_CompressedBufferHelper*, + size_t sizeof___outbuffer, // sizeof uncompressed data + void* out___buffer // buffer for uncompressed data + ) const; + bool WriteChar( + size_t count, + const void* buffer + ); + + size_t m_sizeof_uncompressed; + size_t m_sizeof_compressed; + ON__UINT32 m_crc_uncompressed; + ON__UINT32 m_crc_compressed; + int m_method; // 0 = copied, 1 = compressed + int m_sizeof_element; + size_t m_buffer_compressed_capacity; + void* m_buffer_compressed; +}; + +#endif diff --git a/opennurbs/Include/opennurbs_compstat.h b/opennurbs/Include/opennurbs_compstat.h new file mode 100644 index 0000000..af71405 --- /dev/null +++ b/opennurbs/Include/opennurbs_compstat.h @@ -0,0 +1,884 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2014 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_COMPSTAT_INC_) +#define OPENNURBS_COMPSTAT_INC_ + +////////////////////////////////////////////////////////////////////////// +// +// ON_ComponentState and ON_ComponentStatus +// + +#pragma region RH_C_SHARED_ENUM [ON_ComponentState] [Rhino.Geometry.ComponentState] [internal:byte] + +///Provides a set of values describing component state. +///This is not a bit field. +///Some of these values are mutually exclusive and should not be combined. +enum class ON_ComponentState : unsigned char +{ + ///Not a valid status. + Unset = 0, + + ///This is a default component state. + Clear = 1, + + ///This is a default component state, but not selected. + NotSelected = 2, + + ///This component is selected. + Selected = 3, + + ///This component is selected persistently. + SelectedPersistent = 4, + + ///This is a default component state, but not highlighted. + NotHighlighted = 5, + + ///This component is highlighted. + Highlighted = 6, + + ///This is a default component state, but not hidden. + NotHidden = 7, + + ///This component is hidden. + Hidden = 8, + + ///This is a default component state, but not locked. + NotLocked = 9, + + ///This component is locked. + Locked = 10, + + ///This is a default component state, but not damaged. + NotDamaged = 11, + + ///This component is damaged. + Damaged = 12, + + ///This component is not deleted. + NotDeleted = 13, + + ///This component is deleted. + Deleted = 14, + + ///This runtime mark is clear. + RuntimeMarkClear = 15, + + ///This runtime mark is set. + RuntimeMarkSet = 16 +}; +#pragma endregion + +ON_DECL +ON_ComponentState ON_ComponentStateFromUnsigned( + unsigned int state_as_unsigned + ); + +class ON_CLASS ON_ComponentStatus +{ +public: + + static const ON_ComponentStatus NoneSet; + static const ON_ComponentStatus Selected; + static const ON_ComponentStatus SelectedPersistent; + static const ON_ComponentStatus Highlighted; + static const ON_ComponentStatus Hidden; + static const ON_ComponentStatus Locked; + static const ON_ComponentStatus Deleted; + static const ON_ComponentStatus Damaged; + static const ON_ComponentStatus Marked; + + /* + The six bits for SelectedPersistent, Highlighted, Hidden, Locked, and Damaged are set. + The two bits for Deleted and RuntimeMark are clear. + */ + static const ON_ComponentStatus AllSet; + + /* + Returns: + A logical and of the status bit in lhs and rhs. + */ + static const ON_ComponentStatus LogicalAnd(ON_ComponentStatus lhs, ON_ComponentStatus rhs); + + /* + Returns: + A logical and of the status bit in lhs and rhs. + */ + static const ON_ComponentStatus LogicalOr(ON_ComponentStatus lhs, ON_ComponentStatus rhs); + + /* + Description: + A tool for adding a status check filter. This tool pays attention to RuntimeMark(). + + Paramters: + candidate - [in] + pass_bits - [in] + fail_bits - [in] + + Returns: + Checking is perfomed in the folloing order and every bit, include the RuntimeMark() bit, are tested. + + First: + If ON_ComponentStatus::LogicalAnd(candidate,status_pass) has any set bits, + then true is returned. + + Second: + If ON_ComponentStatus::LogicalAnd(candidate,status_fail) has any set bits, + then false is returned. + + Third: + If status_fail has no set bits the true is returned. + + Forth: + If status_pass has any set bits then false is returned. + + Fifth: + True is returned. + + Examples: + StatusCheck(candidate,ON_ComponentStatus::Selected,ON_ComponentStatus::NoneSet) = candidate.>IsSelected(). + + StatusCheck(candidate,ON_ComponentStatus::NoneSet,ON_ComponentStatus::Selected) = !candidate.>IsSelected(). + + StatusCheck(candidate,ON_ComponentStatus::NoneSet,ON_ComponentStatus::NoneSet) = true; + + StatusCheck(candidate,ON_ComponentStatus::AllSet,ON_ComponentStatus::NoneSet) = true; + + StatusCheck(candidate,ON_ComponentStatus::NoneSet,ON_ComponentStatus::AllSet) = candidate.IsClear() && false==candidate.RuntimeMark(); + */ + static bool StatusCheck( + ON_ComponentStatus candidate, + ON_ComponentStatus status_pass, + ON_ComponentStatus status_fail + ); + + ON_ComponentStatus() = default; + ~ON_ComponentStatus() = default; + ON_ComponentStatus(const ON_ComponentStatus&) = default; + ON_ComponentStatus& operator=(const ON_ComponentStatus&) = default; + + /* + Description: + Constructs a status with the specified state set. + */ + ON_ComponentStatus( + ON_ComponentState state + ); + + bool operator==(ON_ComponentStatus); + bool operator!=(ON_ComponentStatus); + + /* + Returns: + True if every setting besides runtime mark is 0 or false. + Ignores the runtime mark state. + Remarks: + The runtime mark setting is ignored by IsClear(). + */ + bool IsClear() const; + + /* + Returns: + True if some setting besides runtime mark is 1 or true. + Ignores the runtime mark state. + Remarks: + The runtime mark setting is ignored by IsNotClear(). + */ + bool IsNotClear() const; + + /* + Description: + Sets *this = status_to_copy and returns 1 if a state setting changed. + Returns: + 1 if status changed. + 0 if status did not change. + Remarks: + The runtime mark setting cannot be changed using SetStatus(). + */ + unsigned int SetStatus( + ON_ComponentStatus status_to_copy + ); + + /* + Description: + If a state is set in states_to_set, the same state is set in "this". + Parameters: + states_to_set - [in] + Returns: + 1 if status changed. + 0 if status did not change. + Remarks: + The runtime mark setting cannot be changed using SetStates(). + */ + unsigned int SetStates( + ON_ComponentStatus states_to_set + ); + + /* + Description: + If a state is set in states_to_clear, the same state is cleared in "this". + Parameters: + states_to_clear - [in] + Returns: + 1 if status changed. + 0 if status did not change. + Remarks: + The runtime mark setting cannot be changed using ClearStates(). + */ + unsigned int ClearStates( + ON_ComponentStatus states_to_clear + ); + + ////////////////////////////////////////////////////////////////////////// + // + // RuntimeMark + // + bool RuntimeMark() const; + + /* + Returns: + Input value of RuntimeMark(); + */ + bool SetRuntimeMark( + bool bRuntimeMark + ); + + /* + Returns: + Input value of RuntimeMark(); + */ + bool SetRuntimeMark(); + + /* + Returns: + Input value of RuntimeMark(); + */ + bool ClearRuntimeMark(); + + ON__UINT8 MarkBits() const; + + ON__UINT8 SetMarkBits(ON__UINT8 bits); + + /* + Returns: + (0==mark_bits) ? RuntimeMark() : (mark_bits == MarkBits() + */ + bool IsMarked( + ON__UINT8 mark_bits + ) const; + + + ////////////////////////////////////////////////////////////////////////// + // + // Selection + // + + /* + Returns: + ON_ComponentState::not_selected, + ON_ComponentState::Selected or + ON_ComponentState::Selected_pesistent. + */ + ON_ComponentState SelectedState() const; + + /* + Returns: + 1 if status changed. + 0 if status did not change. + */ + unsigned int SetSelectedState( + bool bSelectedState, + bool bPersistent, + bool bSynchronizeHighlight + ); + + unsigned int SetSelectedState( + ON_ComponentState selected_state, + bool bSynchronizeHighlight + ); + + /* + Returns: + false + The selection state is ON_ComponentState::not_selected. + true + The selection state is ON_ComponentState::Selected + or ON_ComponentState::Selected_pesistent. + */ + bool IsSelected() const; + + /* + Returns: + false + The selection state is ON_ComponentState::not_selected. + true + The selection state is ON_ComponentState::Selected_pesistent. + */ + bool IsSelectedPersistent() const; + + ////////////////////////////////////////////////////////////////////////// + // + // Highlighted + // + /* + Returns: + 1 if status changed. + 0 if status did not change. + */ + unsigned int SetHighlightedState( + bool bIsHighlighed + ); + + /* + Returns: + false if not highlighted. + true otherwise. + */ + bool IsHighlighted() const; + + + ////////////////////////////////////////////////////////////////////////// + // + // Hidden + // + + /* + Returns: + 1 if status changed. + 0 if status did not change. + */ + unsigned int SetHiddenState( + bool bIsHidden + ); + + /* + Returns: + false if not hidden. + true otherwise. + (ON_ComponentStatus::HIDDEN_STATE::not_hidden != HiddenState()) + */ + bool IsHidden() const; + + ////////////////////////////////////////////////////////////////////////// + // + // Locked + // + /* + Returns: + 1 if status changed. + 0 if status did not change. + */ + unsigned int SetLockedState( + bool bIsLocked + ); + + /* + Returns: + false if not locked. + true otherwise. + (ON_ComponentStatus::LOCKED_STATE::not_locked != LockedState()) + */ + bool IsLocked() const; + + ////////////////////////////////////////////////////////////////////////// + // + // Deleted + // + + /* + Returns: + 1 if status changed. + 0 if status did not change. + */ + unsigned int SetDeletedState( + bool bIsDeleted + ); + + /* + Returns: + false if not hidden. + true otherwise. + (ON_ComponentStatus::DELETED_STATE::not_deleted != DeletedState()) + */ + bool IsDeleted() const; + + + ////////////////////////////////////////////////////////////////////////// + // + // Damaged + // + + /* + Returns: + 1 if status changed. + 0 if status did not change. + */ + unsigned int SetDamagedState( + bool bIsDamaged + ); + + /* + Returns: + false if not damaged. + true otherwise. + (ON_ComponentStatus::DAMAGED_STATE::not_damaged != DamagedState()) + */ + bool IsDamaged() const; + + + ////////////////////////////////////////////////////////////////////////// + // + // Checking multiple state values efficently + // + + bool operator==(const ON_ComponentStatus&) const; + bool operator!=(const ON_ComponentStatus&) const; + + /* + Parameters: + states_filter - [in] + If no states are specified, then false is returned. + comparand - [in] + If a state is set in states_filter, the corresponding state + in "this" and comparand will be tested. + Returns: + True if every tested state in "this" and comparand are identical. + Remarks: + For the purposes of this test, ON_ComponentState::Selected + and ON_ComponentState::SelectedPersistent are considered equal. + */ + bool AllEqualStates( + ON_ComponentStatus states_filter, + ON_ComponentStatus comparand + ) const; + + /* + Parameters: + states_filter - [in] + If no states are specified, then false is returned. + comparand - [in] + If a state is set in states_filter, the corresponding state + in "this" and comparand will be tested. + Returns: + True if at least one tested state in "this" and comparand are identical. + Remarks: + For the purposes of this test, ON_ComponentState::Selected + and ON_ComponentState::SelectedPersistent are considered equal. + */ + bool SomeEqualStates( + ON_ComponentStatus states_filter, + ON_ComponentStatus comparand + ) const; + + /* + Parameters: + states_filter - [in] + If no states are specified, then false is returned. + comparand - [in] + If a state is set in states_filter, the corresponding state + in "this" and comparand will be tested. + Returns: + True if every tested state in "this" and comparand are different. + Remarks: + For the purposes of this test, ON_ComponentState::Selected + and ON_ComponentState::SelectedPersistent are considered equal. + */ + bool NoEqualStates( + ON_ComponentStatus states_filter, + ON_ComponentStatus comparand + ) const; + +private: + friend class ON_AggregateComponentStatus; + + // NOTE: + // Hidden, Selected, ..., Mark() bool values are saved + // as single bits on m_status_flags. + unsigned char m_status_flags = 0U; + + // extra bits for advanced marking + // no rules for use and runtime only - never saved in 3dm archives + // NOTE: Mark() and MarkBits() are independent. + // bool Mark() is a bit on m_status_flags. + // ON__UINT8 MarkBits() returns m_mark_bits. + ON__UINT8 m_mark_bits = 0U; +}; + + + +////////////////////////////////////////////////////////////////////////// +// +// ON_AggregateComponentStatus +// +// + + +/* +ON_AggregateComponentStatus is obsolte. +It exists because the virtual interface on ON_Object and the member on ON_Brep +cannot be changed without breakky the pubic C++ SDK. +Whenever possible, use ON_AggregateComponentStatusEx. +*/ +class ON_CLASS ON_AggregateComponentStatus +{ +public: + static const ON_AggregateComponentStatus Empty; + static const ON_AggregateComponentStatus NotCurrent; + + ON_AggregateComponentStatus() = default; + ~ON_AggregateComponentStatus() = default; + ON_AggregateComponentStatus(const ON_AggregateComponentStatus&) = default; + ON_AggregateComponentStatus& operator=(const ON_AggregateComponentStatus&) = default; + + ON_AggregateComponentStatus(const class ON_AggregateComponentStatusEx&); + ON_AggregateComponentStatus& operator=(const class ON_AggregateComponentStatusEx&); + + /* + Description: + Sets all states to clear. + Marks status as current. + Does not change compoent count + Returns + true if successful. + false if information is not current and ClearAllStates() failed. + */ + bool ClearAllStates(); + + /* + Description: + Sets all states specified by states_to_clear to clear. + Does not change current mark. + Does not change compoent count. + Returns + true if successful. + false if information is not current and ClearAggregateStatus() failed. + */ + bool ClearAggregateStatus( + ON_ComponentStatus states_to_clear + ); + + /* + Description: + Add the status information in component_status to this aggregate status. + Parameters: + component_status - [in] + Returns: + true if successful. + false if information is not current and Add failed. + */ + bool Add( + ON_ComponentStatus component_status + ); + + /* + Description: + Add the status information in aggregate_status to this aggregate status. + Parameters: + aggregate_status - [in] + Returns: + true if successful. + false if information is not current and Add failed. + */ + bool Add( + const ON_AggregateComponentStatus& aggregate_status + ); + + /* + Returns: + true if this is empty + false if not empty. + */ + bool IsEmpty() const; + + /* + Returns: + true if the information is current (valid, up to date, ...). + false if the information is not current. + Remarks: + If the information is not current, all counts are zero and states are clear. + */ + bool IsCurrent() const; + + /* + Description: + Mark the information as not current. + Erases all information. + */ + void MarkAsNotCurrent(); + + ON_ComponentStatus AggregateStatus() const; + + unsigned int ComponentCount() const; + + /* + Returns: + Number of compoents that are selected or persistently selected. + */ + unsigned int SelectedCount() const; + + /* + Returns: + Number of compoents that are persistently selected. + */ + unsigned int SelectedPersistentCount() const; + + unsigned int HighlightedCount() const; + + unsigned int HiddenCount() const; + + unsigned int LockedCount() const; + + unsigned int DamagedCount() const; + +private: + // a bitwise or of all component status settings + ON_ComponentStatus m_aggregate_status = ON_ComponentStatus::NoneSet; + +private: + unsigned char m_current = 0; // 0 = empty, 1 = current, 2 = dirty + +private: + unsigned char m_reserved1 = 0; + +private: + // number of components + unsigned int m_component_count = 0; + + // number of selected components (includes persistent and non persistent) + unsigned int m_selected_count = 0; + + // number of selected components + unsigned int m_selected_persistent_count = 0; + + // number of highlighted components + unsigned int m_highlighted_count = 0; + + // number of hidden components + unsigned int m_hidden_count = 0; + + // number of locked components + unsigned int m_locked_count = 0; + + // number of damaged components + unsigned int m_damaged_count = 0; +}; + +class ON_CLASS ON_AggregateComponentStatusEx : private ON_AggregateComponentStatus +{ +public: + static const ON_AggregateComponentStatusEx Empty; + static const ON_AggregateComponentStatusEx NotCurrent; + + ON_AggregateComponentStatusEx() = default; + ~ON_AggregateComponentStatusEx() = default; + ON_AggregateComponentStatusEx(const ON_AggregateComponentStatusEx&) = default; + ON_AggregateComponentStatusEx& operator=(const ON_AggregateComponentStatusEx&) = default; + + ON_AggregateComponentStatusEx(const ON_AggregateComponentStatus&); + ON_AggregateComponentStatusEx& operator=(const ON_AggregateComponentStatus&); + + /* + Returns: + A runtime serial number that is incremented every time a component status setting + changes, even when the actual counts may be unknown. + If the returned value is 0, status information is unknown. + */ + ON__UINT64 ComponentStatusSerialNumber() const; + + /* + Description: + Sets all states to clear. + Marks status as current. + Does not change compoent count + Returns + true if successful. + false if information is not current and ClearAllStates() failed. + */ + bool ClearAllStates(); + + /* + Description: + Sets all states specified by states_to_clear to clear. + Does not change current mark. + Does not change compoent count. + Returns + true if successful. + false if information is not current and ClearAggregateStatus() failed. + */ + bool ClearAggregateStatus( + ON_ComponentStatus states_to_clear + ); + + /* + Description: + Add the status information in component_status to this aggregate status. + Parameters: + component_status - [in] + Returns: + true if successful. + false if information is not current and Add failed. + */ + bool Add( + ON_ComponentStatus component_status + ); + + /* + Description: + Add the status information in aggregate_status to this aggregate status. + Parameters: + aggregate_status - [in] + Returns: + true if successful. + false if information is not current and Add failed. + */ + bool Add( + const ON_AggregateComponentStatus& aggregate_status + ); + + /* + Returns: + true if this is empty + false if not empty. + */ + bool IsEmpty() const; + + /* + Returns: + true if the information is current (valid, up to date, ...). + false if the information is not current. + Remarks: + If the information is not current, all counts are zero and states are clear. + */ + bool IsCurrent() const; + + /* + Description: + Mark the information as not current. + Erases all information. + */ + void MarkAsNotCurrent(); + + ON_ComponentStatus AggregateStatus() const; + + unsigned int ComponentCount() const; + + /* + Returns: + Number of compoents that are selected or persistently selected. + */ + unsigned int SelectedCount() const; + + /* + Returns: + Number of compoents that are persistently selected. + */ + unsigned int SelectedPersistentCount() const; + + unsigned int HighlightedCount() const; + + unsigned int HiddenCount() const; + + unsigned int LockedCount() const; + + unsigned int DamagedCount() const; + +private: + // Whenever component status changes, m_runtime_serial_number is changed by calling Internal_ChangeStatusSerialNumber(). + void Internal_ChangeStatusSerialNumber(); + ON__UINT64 m_component_status_serial_number = 0; +}; + +////////////////////////////////////////////////////////////////////////// +// +// ON_UniqueTester +// + +class ON_CLASS ON_UniqueTester +{ +public: + ON_UniqueTester() = default; + ~ON_UniqueTester(); + ON_UniqueTester(const ON_UniqueTester&); + ON_UniqueTester& operator=(const ON_UniqueTester&); + +public: + + /* + Description: + If p is not in the list, it is added. + Returns: + True if p is in the list. + */ + bool InList(ON__UINT_PTR x) const; + + /* + Description: + If p is not in the list, it is added. + Returns: + True if p is not in the list and was added. False if p was already in the list. + */ + bool AddToList(ON__UINT_PTR x); + + void ClearList(); + + unsigned int Count() const; + +public: + /* + Description: + Add x to the list. The expert caller is certain that x is not already in the list. + For large lists, using this function when appropriate, can result in substantial + speed improvments. + Parameters: + x - [in] + A value that is known to not be in the list. + */ + void ExpertAddNewToList(ON__UINT_PTR x); + +private: + class Block + { + public: + static Block* NewBlock(); + static void DeleteBlock(Block*); + + public: + enum : size_t {BlockCapacity=1000}; + size_t m_count = 0; + ON__UINT_PTR* m_a = nullptr; + class Block* m_next = nullptr; + bool InBlock(size_t sorted_count,ON__UINT_PTR p) const; + + void SortBlock(); + + private: + static int Compare(ON__UINT_PTR* lhs, ON__UINT_PTR* rhs); + Block() = default; + ~Block() = delete; + Block(const Block&) = delete; + Block& operator=(const Block&) = delete; + }; + + size_t m_sorted_count = 0; + Block* m_block_list = nullptr; + +private: + void Internal_CopyFrom(const ON_UniqueTester& src); + void Internal_Destroy(); + void Internal_AddValue(ON__UINT_PTR x); +}; + +#endif diff --git a/opennurbs/Include/opennurbs_cone.h b/opennurbs/Include/opennurbs_cone.h new file mode 100644 index 0000000..4eac53b --- /dev/null +++ b/opennurbs/Include/opennurbs_cone.h @@ -0,0 +1,190 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_CONE_INC_) +#define ON_CONE_INC_ + +class ON_NurbsSurface; +class ON_Brep; + +// Description: +// Lightweight right circular cone. Use ON_ConeSurface if +// you need ON_Cone geometry as a virtual ON_Surface. +class ON_CLASS ON_Cone +{ +public: + + // Creates a cone with world XY plane as the base plane, + // center = (0,0,0), radius = 0.0, height = 0.0. + ON_Cone(); + + // See ON_Cone::Create. + ON_Cone( + const ON_Plane& plane, + double height, + double radius + ); + + ~ON_Cone(); + + // Description: + // Creates a right circular cone from a plane, height, + // and radius. + // plane - [in] The apex of cone is at plane.origin and + // the axis of the cone is plane.zaxis. + // height - [in] The center of the base is height*plane.zaxis. + // radius - [in] tan(cone angle) = radius/height + bool Create( + const ON_Plane& plane, + double height, + double radius + ); + + // Returns true if plane is valid, height is not zero, and + // radius is not zero. + bool IsValid() const; + + // Returns: + // Center of base circle. + // Remarks: + // The base point is plane.origin + height*plane.zaxis. + ON_3dPoint BasePoint() const; + + // Returns: + // Point at the tip of the cone. + // Remarks: + // The apex point is plane.origin. + const ON_3dPoint& ApexPoint() const; + + // Returns: + // Unit vector axis of cone. + const ON_3dVector& Axis() const; + + // Returns: + // The angle (in radians) between the axis and the + // side of the cone. + // The angle and the height have the same sign. + double AngleInRadians() const; + + // Returns: + // The angle Iin degrees) between the axis and the side. + // The angle and the height have the same sign. + double AngleInDegrees() const; + + // evaluate parameters and return point + // Parameters: + // radial_parameter - [in] 0.0 to 2.0*ON_PI + // height_parameter - [in] 0 = apex, height = base + ON_3dPoint PointAt( + double radial_parameter, + double height_parameter + ) const; + + // Parameters: + // radial_parameter - [in] (in radians) 0.0 to 2.0*ON_PI + // height_parameter - [in] 0 = apex, height = base + // Remarks: + // If radius>0 and height>0, then the normal points "out" + // when height_parameter >= 0. + ON_3dVector NormalAt( + double radial_parameter, + double height_parameter + ) const; + + // Description: + // Get iso curve circle at a specified height. + // Parameters: + // height_parameter - [in] 0 = apex, height = base + ON_Circle CircleAt( + double height_parameter + ) const; + + // Description: + // Get iso curve line segment at a specified angle. + // Parameters: + // radial_parameter - [in] (in radians) 0.0 to 2.0*ON_PI + ON_Line LineAt( + double radial_parameter + ) const; + + // returns parameters of point on cone that is closest to given point + bool ClosestPointTo( + ON_3dPoint point, + double* radial_parameter, + double* height_parameter + ) const; + + // returns point on cone that is closest to given point + ON_3dPoint ClosestPointTo( + ON_3dPoint + ) const; + + bool Transform( const ON_Xform& ); + + // rotate cone about its origin + bool Rotate( + double sin_angle, + double cos_angle, + const ON_3dVector& axis_of_rotation + ); + + bool Rotate( + double angle_in_radians, + const ON_3dVector& axis_of_rotation + ); + + // rotate cone about a point and axis + bool Rotate( + double sin_angle, + double cos_angle, + const ON_3dVector& axis_of_rotation, + const ON_3dPoint& center_of_rotation + ); + bool Rotate( + double angle_in_radians, + const ON_3dVector& axis_of_rotation, + const ON_3dPoint& center_of_rotation + ); + + bool Translate( + const ON_3dVector& delta + ); + + /* + returns: + 0 = failure + 2 = success + */ + int GetNurbForm( ON_NurbsSurface& ) const; + + /* + Description: + Creates a surface of revolution definition of the cylinder. + Parameters: + srf - [in] if not nullptr, then this srf is used. + Result: + A surface of revolution or nullptr if the cylinder is not + valid or is infinite. + */ + ON_RevSurface* RevSurfaceForm( ON_RevSurface* srf = nullptr ) const; + +public: + ON_Plane plane; // apex = plane.origin, axis = plane.zaxis + double height; // not zero + double radius; // not zero +}; + +#endif diff --git a/opennurbs/Include/opennurbs_convex_poly.h b/opennurbs/Include/opennurbs_convex_poly.h new file mode 100644 index 0000000..296b40b --- /dev/null +++ b/opennurbs/Include/opennurbs_convex_poly.h @@ -0,0 +1,427 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_CONVEX_POLY_INC_) +#define ON_CONVEX_POLY_INC_ + + +// A Simplex in 3d +class ON_CLASS ON_3dSimplex +{ +public: + ON_3dSimplex(); // An empty simplex + explicit ON_3dSimplex(const ON_3dPoint& a); // 0-simplex in 3d + ON_3dSimplex(const ON_3dPoint& a, const ON_3dPoint& b); // 1-simplex + ON_3dSimplex(const ON_3dPoint& a, const ON_3dPoint& b, const ON_3dPoint& c); // 2-simplex + ON_3dSimplex(const ON_3dPoint& a, const ON_3dPoint& b, const ON_3dPoint& c, const ON_3dPoint& d); // 3-simplex + + ON_3dSimplex(const ON_3dSimplex& rhs) = default; + ON_3dSimplex& operator=(const ON_3dSimplex& rhs) = default; + ~ON_3dSimplex() = default; + + int Count() const; // Number of Verticies <=4 + bool IsValid(double eps) const; // true if the Verticies are affinely independent + + /* + Description: + Evaluate a point in a Simplex from a barycentric coordinate b. + Returns: + The point + b[0] * Vertex[0] + ... + b[Count()-1] * Vertex[Count()-1] + Notes: + If b[0] + ... + b[Count()-1] = 1 and b[i]>=0 for i=0 to Count()-1 then the + returned point is on the simplex + */ + ON_3dPoint Evaluate(const double* b) const; + ON_3dPoint Evaluate(const ON_4dPoint& b) const; + + /* + Description: + Find Closest Point to this simplex from a base point P0 or the Origin. + If true is retuned then Evaluate(Bary) is the closest point on the Simplex. + maximum_distance - optional upperbound on closest point. If maximum_distance>=0 is specified and + Dist(P0, Simplex)>maximum_distance then false is returned. + */ + bool GetClosestPoint(const ON_3dPoint& P0, ON_4dPoint& Bary, double maximum_distance = ON_DBL_MAX) const; + bool GetClosestPointToOrigin(ON_4dPoint& Bary) const; + + /* + Count() Volume() returns + 0 0.0 + 1 0.0 + 2 length >=0 + 3 area >=0 + 4 volume >=0 + */ + double Volume() const; + double SignedVolume() const; // returns ON_UNSET_VALUE if Count()<4 else the signed volume + + /* + FaceNormal(noti) is the oriented face normal obtained by omitting vertex noti. + FaceNormal returns ON_UNSET_VALUE if Count()<3 or Count()==4 noti not 0,1,2 or 3. + FaceUnitNormal returns ON_UNSET_VALUE if Count()<3 or Count()==4 noti not 0,1,2 or 3 or if FaceNormal(noti)=Zero_Vector + */ + ON_3dVector FaceNormal(int noti = 0) const; + ON_3dVector FaceUnitNormal(int noti = 0) const; + + /* + Edge vector from Vertex(e0) to Vertex(e1) + */ + ON_3dVector Edge(int e0, int e1)const; + + /* If 0<=i=0 + */ + virtual int Count() const = 0; + /* + Returns: Vertex[i] for i=0,...,Count()-1 + */ + virtual ON_3dVector Vertex(int i) const = 0; + + /* + Description: + Let K be this ON_ConvexPoly then for a non-zero vector W the support Support(W) are point in K defined by + arg max x * W + x \in K + This method returns one of these points in Support(W). + i0 is an optional initial index seed value. It may provide a performance enhancement toward finding + a minimizer. + */ + ON_3dPoint Support(ON_3dVector W, int i0 =0) const + { + return Vertex(SupportIndex(W, i0)); + } + + /* + Description: + For any vector W there is a vetex that is Support(W) + SupportIndex( W, i0) returns a vertex index for a vertex that is the support. + Veretx( K.SupportIndex( W )) = K.Support(W ); + */ + virtual int SupportIndex(ON_3dVector W, int i0=0) const = 0; + + /* + Description: + Points in a Convex Polytope are parameterized , not necessaily uniquely, + by an ON_4dex of vertex indicies and a 4d barycentric point B + Evaluate(Ind, B ) = Sum_{i=0,..,3} Vertex(Ind[i])*B[i], where the sum is taken over i such that Ind[i]>=0 + If B is a barycentric coordinte + B[i]>=0 and B[0] + B[1] + B[2] + B[3] = 1.0 + then Evaluate( Ind, B) is a point in the convex polytope + */ + ON_3dPoint Evaluate(ON_4dex dex, ON_4dPoint B)const + { + ON_3dVector v(0, 0, 0); + if (dex.i >= 0) + v = B[0] * Vertex(dex.i); + if (dex.j >= 0) + v += B[1] * Vertex(dex.j); + if (dex.k >= 0) + v += B[2] * Vertex(dex.k); + if (dex.l >= 0) + v += B[3] * Vertex(dex.l); + return v; + }; + + /* +Description: + Computes the closest point on this convex polytope from a point P0. +Parameters: + P0 - [in] Base Point for closest point + dex -[out] + bary - [out] Evaluate(dex,bary) is the closest point on this polyhedran + maximum_distance - [in ] optional upper bound on distance + +Returns: + Returns true if a closest point is found and it is within optional maximum_distance bound; + +Details: + Setting maximum_distance can speedup the calculation in cases where dist(P0, *this)>maximum_distance. +*/ + bool GetClosestPoint( ON_3dPoint P0, + ON_4dex& dex, ON_4dPoint& bary, + double maximum_distance = ON_DBL_MAX) const; + + // Expert version of GetClosestPoint. + // dex is used at input to seed search algorithm. + // the points of *this singled out by dex must define a nondegenerate simplex + bool GetClosestPointSeeded(ON_3dPoint P0, + ON_4dex& dex, ON_4dPoint& Bary, + double maximum_distance = ON_DBL_MAX) const; + + /* + Description: + Computes a pair of points on *this and BHull that achieve the minimum distance between + the two convex polytopes. + Parameters: + BHull - [in] the other convex polytope + adex, bdex -[out] Evaluate(adex,bary) is the closest point on this polyhedron + bary - [out] BHull.Evaluate(bdex,bary) is the closest point on BHull. + maximum_distance - [in ] optional upper bound on distance + +Returns: + Returns true if a closest points are found and they are within optional maximum_distance bound; + +Details: + Setting maximum_distance can speedup the calculation in cases where dist(*this, BHull)>maximum_distance. + */ + bool GetClosestPoint(const ON_ConvexPoly& BHull, + ON_4dex& Adex, ON_4dex& Bdex, ON_4dPoint& bary, + double maximum_distance = ON_DBL_MAX) const; + + // Expert version of GetClosestPoint. +// Adex and Bdex are used at input to seed search algorithm. +// the points of this-Bhull singled out by Adex and Bdex must define a nondegenerate simplex + bool GetClosestPointSeeded(const ON_ConvexPoly& BHull, + ON_4dex& Adex, ON_4dex& Bdex, ON_4dPoint& bary, + double maximum_distance = ON_DBL_MAX) const; + + /* + Description: + This is a bound on the collection of verticies. + Vertex(i).MaximumCoordinate()<= MaximumCoordinate() for all i + */ + virtual double MaximumCoordinate() const = 0; + + /* + Description: + A point represented by a ON_4dex D and a barycentric coordinate B + can be put in a standard form so that non-negative elements of D are unique and + corresponding coordinates are positive. Furthemore, the non-negative + indicies are all listed before the unset ( neagative ) values + */ + static bool Standardize(ON_4dex& D, ON_4dPoint& B); + + /* + Returns: + true if d[i] n) return false; + } + return true; + } + bool IsValid4Dex(const ON_4dex& D) const { return IsValid4DexN(D, Count()); }; + + virtual ~ON_ConvexPoly() {}; +}; + +// 3d convex hull defined by an explicit collection of points called verticies. +// Note: verticies need not be extreme points + +// WARNING: Points are referenced not stored for optimal performance in' +// some applications. +// The list of points must remain alive and in there initial location +// For the duration of this object. +class ON_CLASS ON_ConvexHullRef : public ON_ConvexPoly +{ +public: + ON_ConvexHullRef() { m_n = 0; m_is_rat = false; m_stride = 3; }; + ON_ConvexHullRef(const ON_3dVector* V0, int count); // a 3d point array + ON_ConvexHullRef(const ON_3dPoint* V0, int count); // a 3d point array + ON_ConvexHullRef(const ON_4dPoint* V0, int count); // a array of homogeneous points + ON_ConvexHullRef(const double* v0, bool is_rat, int n); // v0 is an array of 3dpoints or homo 4d points + ON_ConvexHullRef(const double* v0, bool is_rat, int n, int stride); // v0 is an array of 3dpoints or homo 4d points + + void Initialize(const ON_3dVector* V0, int count); + void Initialize(const ON_4dPoint* V0, int count); + void Initialize(const double* V0, ON::point_style style, int count); // style must be either not_rational or homogeneous_rational = 2, + + int Count() const override { return m_n; } + ON_3dVector Vertex(int j) const override; + + // Support map + virtual int SupportIndex(ON_3dVector W, int i0) const override; + virtual double MaximumCoordinate() const override; + + virtual ~ON_ConvexHullRef() override {}; +private: + + int m_n = 0; + bool m_is_rat= false; + const double* m_v = nullptr; + int m_stride=3; +}; + +// 3d convex hull defined by an explicit collection of points called verticies. +// Note: verticies need not be extreme points +class ON_CLASS ON_ConvexHullPoint2 : public ON_ConvexPoly +{ +public: + ON_ConvexHullPoint2() = default; + ON_ConvexHullPoint2(int init_capacity) : m_Vert(init_capacity) {}; + + virtual int Count() const override { return m_Vert.Count(); } + virtual ON_3dVector Vertex(int j) const override { return m_Vert[j]; } + + // Support map + virtual int SupportIndex(ON_3dVector W, int i0) const override { + return Ref.SupportIndex(W, i0); + }; + + virtual double MaximumCoordinate() const override; + + virtual ~ON_ConvexHullPoint2() override {}; + + int AppendVertex(const ON_3dPoint& P); // return index of new vertex. must set Adjacent Indicies. + void Empty(); + + bool SetCapacity(int vcnt) { + m_Vert.SetCapacity(vcnt); + return true; + }; + +private: + ON_ConvexHullRef Ref; + ON_SimpleArray m_Vert; +}; + + + +/* + Compute Convex hull of 2d points + Parameters: + Pnt - array of points, this is array of working data. The points are sorted in place as part of the algorithm + HUll - the sequence Hull[0], HUll[1]... ,*Hull.Last() == Hull[0] defines the convex hull with a positive orientation retuns 2. + PntInd - otional array to be filled in so that Hull[i] = Pnt[ PntInd[i]] where Pnt is the original input point + Returns + dimension of the convex hull + 2 - Hull is 2 dimensional + 1 - Hull is a line segments + 0 - hull is a point + <0 error +*/ +ON_DECL +int ON_ConvexHull2d(const ON_SimpleArray& Pnt, ON_SimpleArray& Hull, ON_SimpleArray< int>* PntInd = nullptr); + +#endif + + diff --git a/opennurbs/Include/opennurbs_cpp_base.h b/opennurbs/Include/opennurbs_cpp_base.h new file mode 100644 index 0000000..e0e81cf --- /dev/null +++ b/opennurbs/Include/opennurbs_cpp_base.h @@ -0,0 +1,108 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2015 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_CPP_BASE_INC_) +#define OPENNURBS_CPP_BASE_INC_ + +// basic C++ declarations + + +#if !defined(UUID_DEFINED) && !defined(GUID_DEFINED) +// basic C++ declarations +bool operator==(const struct ON_UUID_struct& a, const struct ON_UUID_struct& b); +bool operator!=(const struct ON_UUID_struct& a, const struct ON_UUID_struct& b); +#endif + +class ON_CLASS ON_StopWatch +{ +public: + ON_StopWatch() = default; + ~ON_StopWatch() = default; + ON_StopWatch(const ON_StopWatch&) = default; + ON_StopWatch& operator=(const ON_StopWatch&) = default; + +public: + enum class State : unsigned char + { + /// + /// The stopwatch is off. + /// + Off = 0, + + /// + /// The stopwatch is started and running. + /// + Running = 1, + + /// + /// The stopwatch has been started and stopped. + /// + Stopped = 2 + }; + + /* + Description: + If the stopwatch is off or stopped, it is started. Otherwise nothing happens. + */ + void Start(); + + /* + Description: + If the stopwatch is running, then it is stopped. Otherwise nothing happens. + Returns: + If the stopwatch was running, the elapsed time from the most recent Start(). + Otherwise, 0.0 is returned. + */ + double Stop(); + + /* + Description: + The stopwatch is reset and turned off. Any previously set times are lost. + */ + void Reset(); + + /* + Returns: + Current state of the stopwatch. + */ + ON_StopWatch::State CurrentState() const; + + + /* + Returns: + The elapsed time in seconds. + Remarks: + If the stopwatch is running, the elapsed time is the duration from the most recent Start() to now. + If the stopwatch is stopped, the elapsed time is the duration between the most recent Start() and Stop(). + If the stopwatch is off, the elapsed time is zero. + */ + double ElapsedTime() const; + +private: + // current state + ON_StopWatch::State m_state = ON_StopWatch::State::Off; +#pragma ON_PRAGMA_WARNING_PUSH +#pragma ON_PRAGMA_WARNING_DISABLE_MSC( 4251 ) + // C4251: ... : class 'std::...' + // needs to have dll-interface to be used by clients ... + // m_start and m_stop are private and all code that manages them is explicitly implemented in the DLL. + std::chrono::high_resolution_clock::time_point m_start; // most recent Start() time. + std::chrono::high_resolution_clock::time_point m_stop; // most recent Stop() time. +#pragma ON_PRAGMA_WARNING_POP +}; + + +#endif diff --git a/opennurbs/Include/opennurbs_crc.h b/opennurbs/Include/opennurbs_crc.h new file mode 100644 index 0000000..99dd7e5 --- /dev/null +++ b/opennurbs/Include/opennurbs_crc.h @@ -0,0 +1,152 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_CRC_INC_) +#define OPENNURBS_CRC_INC_ + +ON_BEGIN_EXTERNC + +/* +Description: + Continues 16 bit CRC calulation to include the buffer. + +Parameters: + current_remainder - [in] + sizeof_buffer - [in] number of bytes in buffer + buffer - [in] + +Example: + 16 bit CRC calculations are typically done something like this: + + const ON__UINT16 crc_seed = 0; // or 1, or your favorite starting value + + // Compute CRC on "good" data + unsigned ON__UINT16 first_crc = crc_seed; + first_crc = ON_CRC16( first_crc, size1, buffer1 ); + ... + first_crc = ON_CRC16( first_crc, sizeN, bufferN ); + unsigned char two_zero_bytes[2] = (0,0); + first_crc = ON_CRC16( first_crc, 2, two_zero_bytes ); + + // make sure 16 bit CRC calculation is valid + ON__UINT16 check_crc_calculation = ON_CRC16( first_crc, 2, &first_crc ); + if ( check_crc_calculation != 0 ) + { + printf("ON_CRC16() calculated a bogus 16 bit CRC\n"); + } + + // Do something that may potentially change the values in + // the buffers (like storing them on a faulty disk). + + // Compute CRC on "suspect" data + ON__UINT16 second_crc = crc_seed; + second_crc = ON_CRC16( second_crc, size1, buffer1 ); + ... + second_crc = ON_CRC16( second_crc, sizeN, bufferN ); + if ( 0 != ON_CRC16( second_crc, 2, &first_crc ) ) + { + printf( "The value of at least one byte has changed.\n" ); + } +*/ +ON_DECL +ON__UINT16 ON_CRC16( + ON__UINT16 current_remainder, + size_t sizeof_buffer, + const void* buffer + ); + +/* +Description: + Continues 32 bit CRC calulation to include the buffer + + ON_CRC32() is a slightly altered version of zlib 1.3.3's crc32() + and the zlib "legal stuff" is reproduced below. + + ON_CRC32() and zlib's crc32() compute the same values. ON_CRC32() + was renamed so it wouldn't clash with the other crc32()'s that are + out there and the argument order was switched to match that used by + the legacy ON_CRC16(). + +Parameters: + current_remainder - [in] + sizeof_buffer - [in] number of bytes in buffer + buffer - [in] + +Example: + 32 bit CRC calculations are typically done something like this: + + const ON__UINT32 crc_seed = 0; // or 1, or your favorite starting value + + //Compute CRC on "good" data + ON__UINT32 first_crc = crc_seed; + first_crc = ON_CRC32( first_crc, size1, buffer1 ); + ... + first_crc = ON_CRC32( first_crc, sizeN, bufferN ); + + // Do something that may potentially change the values in + // the buffers (like storing them on a faulty disk). + + // Compute CRC on "suspect" data + ON__UINT32 second_crc = crc_seed; + second_crc = ON_CRC32( second_crc, size1, buffer1 ); + ... + second_crc = ON_CRC32( second_crc, sizeN, bufferN ); + if ( second_crc != first_crc ) + { + printf( "The value of at least one byte has changed.\n" ); + } +*/ +ON_DECL +ON__UINT32 ON_CRC32( + ON__UINT32 current_remainder, + size_t sizeof_buffer, + const void* buffer + ); + +/* +zlib.h -- interface of the 'zlib' general purpose compression library +version 1.1.3, July 9th, 1998 + +Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +Jean-loup Gailly Mark Adler +jloup@gzip.org madler@alumni.caltech.edu + +The data format used by the zlib library is described by RFCs (Request for +Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt +(zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). + +*/ + +ON_END_EXTERNC + +#endif diff --git a/opennurbs/Include/opennurbs_curve.h b/opennurbs/Include/opennurbs_curve.h new file mode 100644 index 0000000..2e8cc2d --- /dev/null +++ b/opennurbs/Include/opennurbs_curve.h @@ -0,0 +1,1474 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +//////////////////////////////////////////////////////////////// +// +// Definition of virtual parametric curve +// +//////////////////////////////////////////////////////////////// + +#if !defined(OPENNURBS_CURVE_INC_) +#define OPENNURBS_CURVE_INC_ + +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// + +class ON_CLASS ON_MeshCurveParameters +{ +public: + ON_MeshCurveParameters(); + + // If main_seg_count <= 0, then both these parameters are ignored. + // If main_seg_count > 0, then sub_seg_count must be >= 1. In this + // case the curve will be broken into main_seg_count equally spaced + // chords. If needed, each of these chords can be split into as many + // sub_seg_count sub-parts if the subdivision is necessary for the + // mesh to meet the other meshing constraints. In particular, if + // sub_seg_count = 0, then the curve is broken into main_seg_count + // pieces and no further testing is performed. + int m_main_seg_count; + int m_sub_seg_count; + + int m_reserved1; + int m_reserved2; + + // Maximum angle (in radians) between unit tangents at adjacent + // vertices. + double m_max_ang_radians; + + // Maximum permitted value of + // distance chord midpoint to curve) / (length of chord) + double m_max_chr; + + // If max_aspect < 1.0, the parameter is ignored. + // If 1 <= max_aspect < sqrt(2), it is treated as if + // max_aspect = sqrt(2). + // This parameter controls the maximum permitted value of + // (length of longest chord) / (length of shortest chord) + double m_max_aspect; + + // If tolerance = 0, the parameter is ignored. + // This parameter controls the maximum permitted value of the + // distance from the curve to the mesh. + double m_tolerance; + + // If m_min_edge_length = 0, the parameter is ignored. + // This parameter controls the minimum permitted edge length. + double m_min_edge_length; + + // If max_edge_length = 0, the parameter is ignored. + // This parameter controls the maximum permitted edge length. + double m_max_edge_length; + + double m_reserved3; + double m_reserved4; +}; + +/* +Description: + ON_Curve is a pure virtual class for curve objects + - Any class derived from ON_Curve should have a + ON_OBJECT_DECLARE(ON_...); + at the beginning of its class definition and a + ON_OBJECT_IMPLEMENT( ON_..., ON_Curve ); + in a .cpp file. +Example: + - See the definition of ON_NurbsCurve for an example. +*/ +class ON_CLASS ON_Curve : public ON_Geometry +{ + ON_OBJECT_DECLARE(ON_Curve); + +public: + ON_Curve() ON_NOEXCEPT; + virtual ~ON_Curve(); + ON_Curve(const ON_Curve&); + ON_Curve& operator=(const ON_Curve&); + +#if defined(ON_HAS_RVALUEREF) + // rvalue copy constructor + ON_Curve( ON_Curve&& ) ON_NOEXCEPT; + + // The rvalue assignment operator calls ON_Object::operator=(ON_Object&&) + // which could throw exceptions. See the implementation of + // ON_Object::operator=(ON_Object&&) for details. + ON_Curve& operator=( ON_Curve&& ); +#endif + +public: + // virtual ON_Object::DestroyRuntimeCache override + void DestroyRuntimeCache( bool bDelete = true ) override; + + // virtual ON_Object::SizeOf override + unsigned int SizeOf() const override; + + // virtual ON_Geometry override + bool EvaluatePoint( const class ON_ObjRef& objref, ON_3dPoint& P ) const override; + + /* + Description: + Get a duplicate of the curve. + Returns: + A duplicate of the curve. + Remarks: + The caller must delete the returned curve. + For non-ON_CurveProxy objects, this simply duplicates the curve using + ON_Object::Duplicate. + For ON_CurveProxy objects, this duplicates the actual proxy curve + geometry and, if necessary, trims and reverse the result to that + the returned curve's parameterization and locus match the proxy curve's. + */ + virtual + ON_Curve* DuplicateCurve() const; + + // Description: + // overrides virtual ON_Object::ObjectType. + // Returns: + // ON::curve_object + ON::object_type ObjectType() const override; + + ON::eCurveType ON_CurveType() const ; + + // virtual ON_Geometry GetTightBoundingBox override + bool GetTightBoundingBox( class ON_BoundingBox& tight_bbox, bool bGrowBox = false, const class ON_Xform* xform = nullptr ) const override; + + /* + Description: + overrides virtual ON_Geometry::Transform(). + ON_Curve::Transform() calls ON_Geometry::Transform(xform), + which calls ON_Object::TransformUserData(xform), and then + calls this->DestroyCurveTree(). + Parameters: + xform - [in] transformation to apply to object. + Remarks: + Classes derived from ON_Curve should call + ON_Curve::Transform() to handle user data + transformations and curve tree destruction + and then transform their definition. + */ + bool Transform( + const ON_Xform& xform + ) override; + + + //////////////////////////////////////////////////////////////////// + // curve interface + + // Description: + // Gets domain of the curve + // Parameters: + // t0 - [out] + // t1 - [out] domain is [*t0, *t1] + // Returns: + // true if successful. + bool GetDomain( double* t0, double* t1 ) const; + + // Returns: + // domain of the curve. + virtual + ON_Interval Domain() const = 0; + + /* + Description: + Set the domain of the curve. + Parameters: + domain - [in] increasing interval + Returns: + true if successful. + */ + bool SetDomain( ON_Interval domain ); + + // Description: + // Set the domain of the curve + // Parameters: + // t0 - [in] + // t1 - [in] new domain will be [t0,t1] + // Returns: + // true if successful. + virtual + bool SetDomain( + double t0, + double t1 + ); + + + /* + Description: + If this curve is closed, then modify it so that + the start/end point is at curve parameter t. + Parameters: + t - [in] curve parameter of new start/end point. The + returned curves domain will start at t. + min_dist - [in] Do not change if Crv(t) is within min_dist of the original seam + Returns: + true if successful, and seam was moved. + */ + + bool ChangeClosedCurveSeam( + double t, + double min_dist + ); + + /* + Description: + If this curve is closed, then modify it so that + the start/end point is at curve parameter t. + Parameters: + t - [in] curve parameter of new start/end point. The + returned curves domain will start at t. + Returns: + true if successful. + */ + virtual + bool ChangeClosedCurveSeam( + double t + ); + + /* + Description: + Change the dimension of a curve. + Parameters: + desired_dimension - [in] + Returns: + true if the curve's dimension was already desired_dimension + or if the curve's dimension was successfully changed to + desired_dimension. + */ + virtual + bool ChangeDimension( + int desired_dimension + ); + + + // Description: + // Get number of nonempty smooth (c-infinity) spans in curve + // Returns: + // Number of nonempty smooth (c-infinity) spans. + virtual + int SpanCount() const = 0; + + // Description: + // Get number of parameters of "knots". + // Parameters: + // span_parameters - [out] an array of length SpanCount()+1 is filled in + // with the parameters where the curve is not smooth (C-infinity). + // Returns: + // true if successful + virtual + bool GetSpanVector( + double* span_parameters + ) const = 0; // + + ////////// + // If t is in the domain of the curve, GetSpanVectorIndex() returns the + // span vector index "i" such that span_vector[i] <= t <= span_vector[i+1]. + // The "side" parameter determines which span is selected when t is at the + // end of a span. + virtual + bool GetSpanVectorIndex( + double t , // [IN] t = evaluation parameter + int side, // [IN] side 0 = default, -1 = from below, +1 = from above + int* span_vector_index, // [OUT] span vector index + ON_Interval* span_domain // [OUT] domain of the span containing "t" + ) const; + + // Description: + // Returns maximum algebraic degree of any span + // or a good estimate if curve spans are not algebraic. + // Returns: + // degree + virtual + int Degree() const = 0; + + // Description: + // Returns maximum algebraic degree of any span + // or a good estimate if curve spans are not algebraic. + // Returns: + // degree + virtual + bool GetParameterTolerance( // returns tminus < tplus: parameters tminus <= s <= tplus + double t, // [IN] t = parameter in domain + double* tminus, // [OUT] tminus + double* tplus // [OUT] tplus + ) const; + + // Description: + // Test a curve to see if the locus if its points is a line segment. + // Parameters: + // tolerance - [in] // tolerance to use when checking linearity + // Returns: + // true if the ends of the curve are farther than tolerance apart + // and the maximum distance from any point on the curve to + // the line segment connecting the curve's ends is <= tolerance. + virtual + bool IsLinear( + double tolerance = ON_ZERO_TOLERANCE + ) const; + + /* + Description: + Several types of ON_Curve can have the form of a polyline including + a degree 1 ON_NurbsCurve, an ON_PolylineCurve, and an ON_PolyCurve + all of whose segments are some form of polyline. IsPolyline tests + a curve to see if it can be represented as a polyline. + Parameters: + pline_points - [out] if not nullptr and true is returned, then the + points of the polyline form are returned here. + t - [out] if not nullptr and true is returned, then the parameters of + the polyline points are returned here. + Returns: + @untitled table + 0 curve is not some form of a polyline + >=2 number of points in polyline form + */ + virtual + int IsPolyline( + ON_SimpleArray* pline_points = nullptr, + ON_SimpleArray* pline_t = nullptr + ) const; + + // Description: + // Test a curve to see if the locus if its points is an arc or circle. + // Parameters: + // plane - [in] if not nullptr, test is performed in this plane + // arc - [out] if not nullptr and true is returned, then arc parameters + // are filled in + // tolerance - [in] tolerance to use when checking + // Returns: + // ON_Arc.m_angle > 0 if curve locus is an arc between + // specified points. If ON_Arc.m_angle is 2.0*ON_PI, then the curve + // is a circle. + virtual + bool IsArc( + const ON_Plane* plane = nullptr, + ON_Arc* arc = nullptr, + double tolerance = ON_ZERO_TOLERANCE + ) const; + + /* + Description: + Parameters: + t - [in] curve parameter + plane - [in] + if not nullptr, test is performed in this plane + arc - [out] + if not nullptr and true is returned, then arc parameters + are filled in + tolerance - [in] + tolerance to use when checking + t0 - [out] + if not nullptr, and then *t0 is set to the parameter + at the start of the G2 curve segment that was + tested. + t1 - [out] + if not nullptr, and then *t0 is set to the parameter + at the start of the G2 curve segment that was + tested. + Returns: + True if the paramter t is on a arc segment of the curve. + */ + bool IsArcAt( + double t, + const ON_Plane* plane = 0, + ON_Arc* arc = 0, + double tolerance = ON_ZERO_TOLERANCE, + double* t0 = 0, + double* t1 = 0 + ) const; + + virtual + bool IsEllipse( + const ON_Plane* plane = nullptr, + ON_Ellipse* ellipse = nullptr, + double tolerance = ON_ZERO_TOLERANCE + ) const; + + // Description: + // Test a curve to see if it is planar. + // Parameters: + // plane - [out] if not nullptr and true is returned, + // the plane parameters are filled in. + // tolerance - [in] tolerance to use when checking + // Returns: + // true if there is a plane such that the maximum distance from + // the curve to the plane is <= tolerance. + virtual + bool IsPlanar( + ON_Plane* plane = nullptr, + double tolerance = ON_ZERO_TOLERANCE + ) const; + + // Description: + // Test a curve to see if it lies in a specific plane. + // Parameters: + // test_plane - [in] + // tolerance - [in] tolerance to use when checking + // Returns: + // true if the maximum distance from the curve to the + // test_plane is <= tolerance. + virtual + bool IsInPlane( + const ON_Plane& test_plane, + double tolerance = ON_ZERO_TOLERANCE + ) const = 0; + + /* + Description: + Decide if it makes sense to close off this curve by moving + the endpoint to the start based on start-end gap size and length + of curve as approximated by chord defined by 6 points. + Parameters: + tolerance - [in] maximum allowable distance between start and end. + if start - end gap is greater than tolerance, returns false + min_abs_size - [in] if greater than 0.0 and none of the interior sampled + points are at least min_abs_size from start, returns false. + min_rel_size - [in] if greater than 1.0 and chord length is less than + min_rel_size*gap, returns false. + Returns: + true if start and end points are close enough based on above conditions. + */ + + bool IsClosable( + double tolerance, + double min_abs_size = 0.0, + double min_rel_size = 10.0 + ) const; + + // Description: + // Test a curve to see if it is closed. + // Returns: + // true if the curve is closed. + virtual + bool IsClosed() const; + + // Description: + // Test a curve to see if it is periodic. + // Returns: + // true if the curve is closed and at least C2 at the start/end. + virtual + bool IsPeriodic() const; + + /* + Description: + Search for a derivatitive, tangent, or curvature + discontinuity. + Parameters: + c - [in] type of continity to test for. + t0 - [in] Search begins at t0. If there is a discontinuity + at t0, it will be ignored. This makes it + possible to repeatedly call GetNextDiscontinuity + and step through the discontinuities. + t1 - [in] (t0 != t1) If there is a discontinuity at t1 is + will be ingored unless c is a locus discontinuity + type and t1 is at the start or end of the curve. + t - [out] if a discontinuity is found, then *t reports the + parameter at the discontinuity. + hint - [in/out] if GetNextDiscontinuity will be called + repeatedly, passing a "hint" with initial value *hint=0 + will increase the speed of the search. + dtype - [out] if not nullptr, *dtype reports the kind of + discontinuity found at *t. A value of 1 means the first + derivative or unit tangent was discontinuous. A value + of 2 means the second derivative or curvature was + discontinuous. A value of 0 means teh curve is not + closed, a locus discontinuity test was applied, and + t1 is at the start of end of the curve. + If 'c', the type of continuity to test for + is ON::continuity::Gsmooth_continuous and the curvature changes + from curved to 0 or 0 to curved and there is no + tangency kink dtype is returns 3 + cos_angle_tolerance - [in] default = cos(1 degree) Used only + when c is ON::continuity::G1_continuous or ON::continuity::G2_continuous. If the + cosine of the angle between two tangent vectors is + <= cos_angle_tolerance, then a G1 discontinuity is reported. + curvature_tolerance - [in] (default = ON_SQRT_EPSILON) Used + only when c is ON::continuity::G2_continuous. If K0 and K1 are + curvatures evaluated from above and below and + |K0 - K1| > curvature_tolerance, then a curvature + discontinuity is reported. + Returns: + Parametric continuity tests c = (C0_continuous, ..., G2_continuous): + + true if a parametric discontinuity was found strictly + between t0 and t1. Note well that all curves are + parametrically continuous at the ends of their domains. + + Locus continuity tests c = (C0_locus_continuous, ...,G2_locus_continuous): + + true if a locus discontinuity was found strictly between + t0 and t1 or at t1 is the at the end of a curve. + Note well that all open curves (IsClosed()=false) are locus + discontinuous at the ends of their domains. All closed + curves (IsClosed()=true) are at least C0_locus_continuous at + the ends of their domains. + */ + virtual + bool GetNextDiscontinuity( + ON::continuity c, + double t0, + double t1, + double* t, + int* hint=nullptr, + int* dtype=nullptr, + double cos_angle_tolerance=ON_DEFAULT_ANGLE_TOLERANCE_COSINE, + double curvature_tolerance=ON_SQRT_EPSILON + ) const; + + /* + Description: + Test continuity at a curve parameter value. + Parameters: + c - [in] type of continuity to test for. Read ON::continuity + comments for details. + t - [in] parameter to test + hint - [in] evaluation hint + point_tolerance - [in] if the distance between two points is + greater than point_tolerance, then the curve is not C0. + d1_tolerance - [in] if the difference between two first derivatives is + greater than d1_tolerance, then the curve is not C1. + d2_tolerance - [in] if the difference between two second derivatives is + greater than d2_tolerance, then the curve is not C2. + cos_angle_tolerance - [in] default = cos(1 degree) Used only when + c is ON::continuity::G1_continuous or ON::continuity::G2_continuous. If the cosine + of the angle between two tangent vectors + is <= cos_angle_tolerance, then a G1 discontinuity is reported. + curvature_tolerance - [in] (default = ON_SQRT_EPSILON) Used only when + c is ON::continuity::G2_continuous or ON::continuity::Gsmooth_continuous. + ON::continuity::G2_continuous: + If K0 and K1 are curvatures evaluated + from above and below and |K0 - K1| > curvature_tolerance, + then a curvature discontinuity is reported. + ON::continuity::Gsmooth_continuous: + If K0 and K1 are curvatures evaluated from above and below + and the angle between K0 and K1 is at least twice angle tolerance + or ||K0| - |K1|| > (max(|K0|,|K1|) > curvature_tolerance, + then a curvature discontinuity is reported. + Returns: + true if the curve has at least the c type continuity at + the parameter t. + */ + virtual + bool IsContinuous( + ON::continuity c, + double t, + int* hint = nullptr, + double point_tolerance=ON_ZERO_TOLERANCE, + double d1_tolerance=ON_ZERO_TOLERANCE, + double d2_tolerance=ON_ZERO_TOLERANCE, + double cos_angle_tolerance=ON_DEFAULT_ANGLE_TOLERANCE_COSINE, + double curvature_tolerance=ON_SQRT_EPSILON + ) const; + + + // Description: + // Reverse the direction of the curve. + // Returns: + // true if curve was reversed. + // Remarks: + // If reveresed, the domain changes from [a,b] to [-b,-a] + virtual + bool Reverse()=0; + + + /* + Description: + Force the curve to start at a specified point. + Parameters: + start_point - [in] + Returns: + true if successful. + Remarks: + Some end points cannot be moved. Be sure to check return + code. + ON_Curve::SetStartPoint() returns true if start_point is the same as the start of the curve, + false otherwise. + See Also: + ON_Curve::SetEndPoint + ON_Curve::PointAtStart + ON_Curve::PointAtEnd + */ + virtual + bool SetStartPoint( + ON_3dPoint start_point + ); + + /* + Description: + Force the curve to end at a specified point. + Parameters: + end_point - [in] + Returns: + true if successful. + Remarks: + Some end points cannot be moved. Be sure to check return + code. + ON_Curve::SetEndPoint() returns true if end_point is the same as the end of the curve, + false otherwise. + See Also: + ON_Curve::SetStartPoint + ON_Curve::PointAtStart + ON_Curve::PointAtEnd + */ + virtual + bool SetEndPoint( + ON_3dPoint end_point + ); + + // Description: + // Evaluate point at a parameter. + // Parameters: + // t - [in] evaluation parameter + // Returns: + // Point (location of curve at the parameter t). + // Remarks: + // No error handling. + // See Also: + // ON_Curve::EvPoint + // ON_Curve::PointAtStart + // ON_Curve::PointAtEnd + ON_3dPoint PointAt( + double t + ) const; + + // Description: + // Evaluate point at the start of the curve. + // Parameters: + // t - [in] evaluation parameter + // Returns: + // Point (location of the start of the curve.) + // Remarks: + // No error handling. + // See Also: + // ON_Curve::PointAt + ON_3dPoint PointAtStart() const; + + // Description: + // Evaluate point at the end of the curve. + // Parameters: + // t - [in] evaluation parameter + // Returns: + // Point (location of the end of the curve.) + // Remarks: + // No error handling. + // See Also: + // ON_Curve::PointAt + ON_3dPoint PointAtEnd() const; + + // Description: + // Evaluate first derivative at a parameter. + // Parameters: + // t - [in] evaluation parameter + // Returns: + // First derivative of the curve at the parameter t. + // Remarks: + // No error handling. + // See Also: + // ON_Curve::Ev1Der + ON_3dVector DerivativeAt( + double t + ) const; + + // Description: + // Evaluate unit tangent vector at a parameter. + // Parameters: + // t - [in] evaluation parameter + // Returns: + // Unit tangent vector of the curve at the parameter t. + // Remarks: + // No error handling. + // See Also: + // ON_Curve::EvTangent + ON_3dVector TangentAt( + double t + ) const; + + // Description: + // Evaluate the curvature vector at a parameter. + // Parameters: + // t - [in] evaluation parameter + // Returns: + // curvature vector of the curve at the parameter t. + // Remarks: + // No error handling. + // See Also: + // ON_Curve::EvCurvature + ON_3dVector CurvatureAt( + double t + ) const; + + // Description: + // Return a 3d frame at a parameter. + // Parameters: + // t - [in] evaluation parameter + // plane - [out] the frame is returned here + // Returns: + // true if successful + // See Also: + // ON_Curve::PointAt, ON_Curve::TangentAt, + // ON_Curve::Ev1Der, Ev2Der + bool FrameAt( double t, ON_Plane& plane) const; + + // Description: + // Evaluate point at a parameter with error checking. + // Parameters: + // t - [in] evaluation parameter + // point - [out] value of curve at t + // side - [in] optional - determines which side to evaluate from + // =0 default + // <0 to evaluate from below, + // >0 to evaluate from above + // hint - [in/out] optional evaluation hint used to speed repeated evaluations + // Returns: + // false if unable to evaluate. + // See Also: + // ON_Curve::PointAt + // ON_Curve::EvTangent + // ON_Curve::Evaluate + bool EvPoint( + double t, + ON_3dPoint& point, + int side = 0, + int* hint = 0 + ) const; + + // Description: + // Evaluate first derivative at a parameter with error checking. + // Parameters: + // t - [in] evaluation parameter + // point - [out] value of curve at t + // first_derivative - [out] value of first derivative at t + // side - [in] optional - determines which side to evaluate from + // =0 default + // <0 to evaluate from below, + // >0 to evaluate from above + // hint - [in/out] optional evaluation hint used to speed repeated evaluations + // Returns: + // false if unable to evaluate. + // See Also: + // ON_Curve::EvPoint + // ON_Curve::Ev2Der + // ON_Curve::EvTangent + // ON_Curve::Evaluate + bool Ev1Der( + double t, + ON_3dPoint& point, + ON_3dVector& first_derivative, + int side = 0, + int* hint = 0 + ) const; + + // Description: + // Evaluate second derivative at a parameter with error checking. + // Parameters: + // t - [in] evaluation parameter + // point - [out] value of curve at t + // first_derivative - [out] value of first derivative at t + // second_derivative - [out] value of second derivative at t + // side - [in] optional - determines which side to evaluate from + // =0 default + // <0 to evaluate from below, + // >0 to evaluate from above + // hint - [in/out] optional evaluation hint used to speed repeated evaluations + // Returns: + // false if unable to evaluate. + // See Also: + // ON_Curve::Ev1Der + // ON_Curve::EvCurvature + // ON_Curve::Evaluate + bool Ev2Der( + double t, + ON_3dPoint& point, + ON_3dVector& first_derivative, + ON_3dVector& second_derivative, + int side = 0, + int* hint = 0 + ) const; + + /* + Description: + Evaluate unit tangent at a parameter with error checking. + Parameters: + t - [in] evaluation parameter + point - [out] value of curve at t + tangent - [out] value of unit tangent + side - [in] optional - determines which side to evaluate from + =0 default + <0 to evaluate from below, + >0 to evaluate from above + hint - [in/out] optional evaluation hint used to speed repeated evaluations + Returns: + false if unable to evaluate. + See Also: + ON_Curve::TangentAt + ON_Curve::Ev1Der + */ + bool EvTangent( + double t, + ON_3dPoint& point, + ON_3dVector& tangent, + int side = 0, + int* hint = 0 + ) const; + + /* + Description: + Evaluate unit tangent and curvature at a parameter with error checking. + Parameters: + t - [in] evaluation parameter + point - [out] value of curve at t + tangent - [out] value of unit tangent + kappa - [out] value of curvature vector + side - [in] optional - determines which side to evaluate from + =0 default + <0 to evaluate from below, + >0 to evaluate from above + hint - [in/out] optional evaluation hint used to speed repeated evaluations + Returns: + false if unable to evaluate. + See Also: + ON_Curve::CurvatureAt + ON_Curve::Ev2Der + ON_EvCurvature + */ + bool EvCurvature( + double t, + ON_3dPoint& point, + ON_3dVector& tangent, + ON_3dVector& kappa, + int side = 0, + int* hint = 0 + ) const; + + /* + Description: + This evaluator actually does all the work. The other ON_Curve + evaluation tools call this virtual function. + Parameters: + t - [in] evaluation parameter ( usually in Domain() ). + der_count - [in] (>=0) number of derivatives to evaluate + v_stride - [in] (>=Dimension()) stride to use for the v[] array + v - [out] array of length (der_count+1)*v_stride + curve(t) is returned in (v[0],...,v[m_dim-1]), + curve'(t) is retuned in (v[v_stride],...,v[v_stride+m_dim-1]), + curve"(t) is retuned in (v[2*v_stride],...,v[2*v_stride+m_dim-1]), + etc. + side - [in] optional - determines which side to evaluate from + =0 default + <0 to evaluate from below, + >0 to evaluate from above + hint - [in/out] optional evaluation hint used to speed repeated evaluations + Returns: + false if unable to evaluate. + See Also: + ON_Curve::EvPoint + ON_Curve::Ev1Der + ON_Curve::Ev2Der + */ + virtual + bool Evaluate( + double t, + int der_count, + int v_stride, + double* v, + int side = 0, + int* hint = 0 + ) const = 0; + + + + /* + Parameters: + min_length -[in] + minimum length of a linear span + tolerance -[in] + distance tolerance to use when checking linearity. + Returns + true if the span is a non-degenrate line. This means: + - dimension = 2 or 3 + - The length of the the line segment from the span's initial + point to the span's control point is >= min_length. + - The maximum distance from the line segment to the span + is <= tolerance and the span increases monotonically + in the direction of the line segment. + */ + bool FirstSpanIsLinear( + double min_length, + double tolerance + ) const; + + bool LastSpanIsLinear( + double min_length, + double tolerance + ) const; + + bool FirstSpanIsLinear( + double min_length, + double tolerance, + ON_Line* span_line + ) const; + + bool LastSpanIsLinear( + double min_length, + double tolerance, + ON_Line* span_line + ) const; + + + // Description: + // Removes portions of the curve outside the specified interval. + // Parameters: + // domain - [in] interval of the curve to keep. Portions of the + // curve before curve(domain[0]) and after curve(domain[1]) are + // removed. + // Returns: + // true if successful. + virtual + bool Trim( + const ON_Interval& domain + ); + + // Description: + // Pure virtual function. Default returns false. + // Where possible, analytically extends curve to include domain. + // Parameters: + // domain - [in] if domain is not included in curve domain, + // curve will be extended so that its domain includes domain. + // Will not work if curve is closed. Original curve is identical + // to the restriction of the resulting curve to the original curve domain, + // Returns: + // true if successful. + virtual + bool Extend( + const ON_Interval& domain + ); + + /* + Description: + Splits (divides) the curve at the specified parameter. + The parameter must be in the interior of the curve's domain. + The pointers passed to Split must either be nullptr or point to + an ON_Curve object of the same type. If the pointer is nullptr, + then a curve will be created in Split(). You may pass "this" + as left_side or right_side. + Parameters: + t - [in] parameter to split the curve at in the + interval returned by Domain(). + left_side - [out] left portion of curve returned here + right_side - [out] right portion of curve returned here + Returns: + true - The curve was split into two pieces. + false - The curve could not be split. For example if the parameter is + too close to an endpoint. + + Example: + For example, if crv were an ON_NurbsCurve, then + + ON_NurbsCurve right_side; + crv.Split( crv.Domain().Mid() &crv, &right_side ); + + would split crv at the parametric midpoint, put the left side + in crv, and return the right side in right_side. + */ + virtual + bool Split( + double t, + ON_Curve*& left_side, + ON_Curve*& right_side + ) const; + + /* + Description: + Get a NURBS curve representation of this curve. + Parameters: + nurbs_curve - [out] NURBS representation returned here + tolerance - [in] tolerance to use when creating NURBS + representation. + subdomain - [in] if not nullptr, then the NURBS representation + for this portion of the curve is returned. + Returns: + 0 unable to create NURBS representation + with desired accuracy. + 1 success - returned NURBS parameterization + matches the curve's to wthe desired accuracy + 2 success - returned NURBS point locus matches + the curve's to the desired accuracy and the + domain of the NURBS curve is correct. On + However, This curve's parameterization and + the NURBS curve parameterization may not + match to the desired accuracy. This situation + happens when getting NURBS representations of + curves that have a transendental parameterization + like circles + Remarks: + This is a low-level virtual function. If you do not need + the parameterization information provided by the return code, + then ON_Curve::NurbsCurve may be easier to use. + See Also: + ON_Curve::NurbsCurve + */ + virtual + int GetNurbForm( + ON_NurbsCurve& nurbs_curve, + double tolerance = 0.0, + const ON_Interval* subdomain = nullptr + ) const; + /* + Description: + Does a NURBS curve representation of this curve. + Parameters: + Returns: + 0 unable to create NURBS representation + with desired accuracy. + 1 success - NURBS parameterization + matches the curve's to wthe desired accuracy + 2 success - NURBS point locus matches + the curve's and the + domain of the NURBS curve is correct. + However, This curve's parameterization and + the NURBS curve parameterization may not + match. This situation + happens when getting NURBS representations of + curves that have a transendental parameterization + like circles + Remarks: + This is a low-level virtual function. + See Also: + ON_Curve::GetNurbForm + ON_Curve::NurbsCurve + */ + virtual + int HasNurbForm() const; + + /* + Description: + Get a NURBS curve representation of this curve. + Parameters: + pNurbsCurve - [in/out] if not nullptr, this ON_NurbsCurve + will be used to store the NURBS representation + of the curve will be returned. + tolerance - [in] tolerance to use when creating NURBS + representation. + subdomain - [in] if not nullptr, then the NURBS representation + for this portion of the curve is returned. + Returns: + nullptr or a NURBS representation of the curve. + Remarks: + See ON_Surface::GetNurbForm for important details about + the NURBS surface parameterization. + See Also: + ON_Curve::GetNurbForm + */ + ON_NurbsCurve* NurbsCurve( + ON_NurbsCurve* pNurbsCurve = nullptr, + double tolerance = 0.0, + const ON_Interval* subdomain = nullptr + ) const; + + // Description: + // Convert a NURBS curve parameter to a curve parameter + // + // Parameters: + // nurbs_t - [in] nurbs form parameter + // curve_t - [out] curve parameter + // + // Remarks: + // If GetNurbForm returns 2, this function converts the curve + // parameter to the NURBS curve parameter. + // + // See Also: + // ON_Curve::GetNurbForm, ON_Curve::GetNurbFormParameterFromCurveParameter + virtual + bool GetCurveParameterFromNurbFormParameter( + double nurbs_t, + double* curve_t + ) const; + + // Description: + // Convert a curve parameter to a NURBS curve parameter. + // + // Parameters: + // curve_t - [in] curve parameter + // nurbs_t - [out] nurbs form parameter + // + // Remarks: + // If GetNurbForm returns 2, this function converts the curve + // parameter to the NURBS curve parameter. + // + // See Also: + // ON_Curve::GetNurbForm, ON_Curve::GetCurveParameterFromNurbFormParameter + virtual + bool GetNurbFormParameterFromCurveParameter( + double curve_t, + double* nurbs_t + ) const; + + + // Description: + // Destroys the runtime curve tree used to speed closest + // point and intersection calcuations. + // Remarks: + // If the geometry of the curve is modified in any way, + // then call DestroyCurveTree(); The curve tree is + // created as needed. + void DestroyCurveTree(); + + + /* + Description: + Lookup a parameter in the m_t array, optionally using a built in snap tolerance to + snap a parameter value to an element of m_t. + This function is used by some types derived from ON_Curve to snap parameter values + Parameters: + t - [in] parameter + index -[out] index into m_t such that + if function returns false then + + @table + value condition + -1 tm_t[ m_t.Count()-1] + + if the function returns true then t is equal to, or is closest to and + within tolerance of m_t[index]. + + bEnableSnap-[in] enable snapping + m_t -[in] Array of parameter values to snap to + RelTol -[in] tolerance used in snapping + + Returns: + true if the t is exactly equal to (bEnableSnap==false), or within tolerance of + (bEnableSnap==true) m_t[index]. + */ +protected: + bool ParameterSearch( double t, int& index, bool bEnableSnap, const ON_SimpleArray& m_t, + double RelTol=ON_SQRT_EPSILON) const; + +private: +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +#endif + +class ON_CLASS ON_CurveArray : public ON_SimpleArray +{ +public: + ON_CurveArray( int = 0 ); + ~ON_CurveArray(); // deletes any non-nullptr curves + + bool Write( ON_BinaryArchive& ) const; + bool Read( ON_BinaryArchive& ); + + void Destroy(); // deletes curves, sets pointers to nullptr, sets count to zero + + bool Duplicate( ON_CurveArray& ) const; // operator= copies the pointer values + // duplicate copies the curves themselves + + /* + Description: + Get tight bounding box of the bezier. + Parameters: + tight_bbox - [in/out] tight bounding box + bGrowBox -[in] (default=false) + If true and the input tight_bbox is valid, then returned + tight_bbox is the union of the input tight_bbox and the + tight bounding box of the bezier curve. + xform -[in] (default=nullptr) + If not nullptr, the tight bounding box of the transformed + bezier is calculated. The bezier curve is not modified. + Returns: + True if the returned tight_bbox is set to a valid + bounding box. + */ + bool GetTightBoundingBox( + ON_BoundingBox& tight_bbox, + bool bGrowBox = false, + const ON_Xform* xform = nullptr + ) const; +}; + +/* +Description: + Trim a curve. +Parameters: + curve - [in] curve to trim (not modified) + trim_parameters - [in] trimming parameters + If curve is open, then trim_parameters must be an increasing + interval.If curve is closed, and trim_parameters ins a + decreasing interval, then the portion of the curve across the + start/end is returned. +Returns: + trimmed curve or nullptr if input is invalid. +*/ +ON_DECL +ON_Curve* ON_TrimCurve( + const ON_Curve& curve, + ON_Interval trim_parameters + ); + +/* +Description: + Move ends of curves to a common point. Neither curve can be closed or an ON_CurveProxy. + If one is an arc or polycurve with arc at end to change, and the other is not, + then the arc is left unchanged and the other curve is moved to the arc endpoint. + Otherwise, both are moved to the midpoint of the segment between the ends. +Parameters: + Crv0 - [in] first curve to modify. + [out] with one endpoint possibly changed. + end0 - [in] if 0, change start of Crv0. Otherwise change end. + Crv1 - [in] second curve to modify. + [out] with one endpoint possibly changed. + end1 - [in] if 0, change start of Crv1. Otherwise change end. +Returns: + true if the endpoints match. Falsse otherwise, +*/ +ON_DECL +bool ON_ForceMatchCurveEnds( + ON_Curve& Crv0, + int end0, + ON_Curve& Crv1, + int end1 + ); + +/* +OBSOLETE. Use int ON_JoinCurves(const ON_SimpleArray& InCurves, + ON_SimpleArray& OutCurves, + double join_tol, + double kink_tol, + bool bPreserveDirection = false, + ON_SimpleArray* key = 0 + ); + +Description: + Join all contiguous curves of an array of ON_Curves. +Parameters: + InCurves - [in] Array of curves to be joined (not modified) + OutCurves - [out] Resulting joined curves and copies of curves that were not joined to anything + are appended. + join_tol - [in] Distance tolerance used to decide if endpoints are close enough + bPreserveDirection - [in] If true, curve endpoints will be compared to curve startpoints. + If false, all start and endpoints will be compared, and copies of input + curves may be reversed in output. + key - [out] if key is not null, InCurves[i] was joined into OutCurves[key[i]]. +Returns: + Number of curves added to Outcurves +Remarks: + Closed curves are copied to OutCurves. + Curves that cannot be joined to others are copied to OutCurves. When curves are joined, the results + are ON_PolyCurves. All members of InCurves must have same dimension, at most 3. + */ +ON_DECL +int ON_JoinCurves(const ON_SimpleArray& InCurves, + ON_SimpleArray& OutCurves, + double join_tol, + bool bPreserveDirection = false, + ON_SimpleArray* key = 0 + ); + +/* +Description: + Join all contiguous curves of an array of ON_Curves. +Parameters: + InCurves - [in] Array of curves to be joined (not modified) + OutCurves - [out] Resulting joined curves and copies of curves that were not joined to anything + are appended. + join_tol - [in] Distance tolerance used to decide if endpoints are close enough + kink_tol - [in] Angle in radians. If > 0.0, then curves within join_tol will only be joined if the angle between them + is less than kink_tol. If <= 0, then the angle will be ignored and only join_tol will be used. + bUseTanAngle - [in] If true, choose the best match using angle between tangents. + If false, best match is the closest. This is used whether or not kink_tol is positive. + bPreserveDirection - [in] If true, curve endpoints will be compared to curve startpoints. + If false, all start and endpoints will be compared, and copies of input + curves may be reversed in output. + key - [out] if key is not null, InCurves[i] was joined into OutCurves[key[i]]. +Returns: + Number of curves added to Outcurves +Remarks: + Closed curves are copied to OutCurves. + Curves that cannot be joined to others are copied to OutCurves. When curves are joined, the results + are ON_PolyCurves. All members of InCurves must have same dimension, at most 3. + */ +ON_DECL +int ON_JoinCurves(const ON_SimpleArray& InCurves, + ON_SimpleArray& OutCurves, + double join_tol, + double kink_tol, + bool bUseTanAngle, + bool bPreserveDirection = false, + ON_SimpleArray* key = 0 + ); + + +/* +Description: + Sort a list of lines so they are geometrically continuous. +Parameters: + line_count - [in] number of lines + line_list - [in] array of lines + index - [out] The input index[] is an array of line_count unused integers. + The returned index[] is a permutation of {0,1,...,line_count-1} + so that the list of lines is in end-to-end order. + bReverse - [out] The input bReverse[] is an array of line_count unused bools. + If the returned value of bReverse[j] is true, then + line_list[index[j]] needs to be reversed. +Returns: + True if successful, false if not. +*/ +ON_DECL +bool ON_SortLines( + int line_count, + const ON_Line* line_list, + int* index, + bool* bReverse + ); + +/* +Description: + Sort a list of lines so they are geometrically continuous. +Parameters: + line_list - [in] array of lines + index - [out] The input index[] is an array of line_count unused integers. + The returned index[] is a permutation of {0,1,...,line_count-1} + so that the list of lines is in end-to-end order. + bReverse - [out] The input bReverse[] is an array of line_count unused bools. + If the returned value of bReverse[j] is true, then + line_list[index[j]] needs to be reversed. +Returns: + True if successful, false if not. +*/ +ON_DECL +bool ON_SortLines( + const ON_SimpleArray& line_list, + int* index, + bool* bReverse + ); + +/* +Description: + Sort a list of open curves so end of a curve matches the start of the next curve. +Parameters: + curve_count - [in] number of curves + curve_list - [in] array of curve pointers + index - [out] The input index[] is an array of curve_count unused integers. + The returned index[] is a permutation of {0,1,...,curve_count-1} + so that the list of curves is in end-to-end order. + bReverse - [out] The input bReverse[] is an array of curve_count unused bools. + If the returned value of bReverse[j] is true, then + curve_list[index[j]] needs to be reversed. +Returns: + True if successful, false if not. +*/ +ON_DECL +bool ON_SortCurves( + int curve_count, + const ON_Curve* const* curve_list, + int* index, + bool* bReverse + ); + +/* +Description: + Sort a list of curves so end of a curve matches the start of the next curve. +Parameters: + curve - [in] array of curves to sort. The curves themselves are not modified. + index - [out] The input index[] is an array of curve_count unused integers. + The returned index[] is a permutation of {0,1,...,curve_count-1} + so that the list of curves is in end-to-end order. + bReverse - [out] The input bReverse[] is an array of curve_count unused bools. + If the returned value of bReverse[j] is true, then + curve[index[j]] needs to be reversed. +Returns: + True if successful, false if not. +*/ +ON_DECL +bool ON_SortCurves( + const ON_SimpleArray& curves, + ON_SimpleArray& index, + ON_SimpleArray& bReverse + ); + +/* +Description: + Sort a list of curves so end of a curve matches the start of the next curve. +Parameters: + curve_count - [in] number of curves + curve - [in] array of curve pointers + index - [out] The input index[] is an array of curve_count unused integers. + The returned index[] is a permutation of {0,1,...,curve_count-1} + so that the list of curves is in end-to-end order. + bReverse - [out] The input bReverse[] is an array of curve_count unused bools. + If the returned value of bReverse[j] is true, then + curve[index[j]] needs to be reversed. +Returns: + True if successful, false if not. +*/ +ON_DECL +bool ON_SortCurves( + const ON_SimpleArray& curves, + ON_SimpleArray& index, + ON_SimpleArray& bReverse + ); + +/* +Description: + Determine the orientaion (counterclockwise or clockwise) of a closed + planar curve. +Paramters: + curve - [in] simple (no self intersections) closed planar curve + xform - [in] Transformation to map the curve to the xy plane. If the + curve is parallel to the xy plane, you may pass nullptr. + plane - [in] If curve is on plane then determine the orientation in relation to + plane's orientation. +Returns: + +1: The curve's orientation is counter clockwise in the xy plane. + -1: The curve's orientation is clockwise in the xy plane. + 0: Unable to compute the curve's orientation. +*/ +ON_DECL +int ON_ClosedCurveOrientation(const ON_Curve& curve, const ON_Xform* xform); +ON_DECL +int ON_ClosedCurveOrientation(const ON_Curve& curve, const ON_Plane& plane); + + +/* +Description: + Get a crude aproximation of the signed area of the region in the + x-y plane traced out by the curve. This is useful for calculating + the orientation of projections of loops to planes when you have + more than one curve. +Paramters: + curve - [in] + domain - [in] + optional sub-domain. (null if entire curve should be used). + xform - [in] Transformation to map the curve to the xy plane. If the + curve is parallel to the xy plane, you may pass nullptr. + bReverseCurve - [in] +Returns: + 1/2 the sum of (p[i].x-p[i+1].x)*(p[i].y+p[i+1].y), where p[i] + is a series of sampled points on the curve. +*/ +ON_DECL +double ON_CurveOrientationArea( + const ON_Curve* curve, + const ON_Interval* domain, + const ON_Xform* xform, + bool bReverseCurve + ); + + +#endif diff --git a/opennurbs/Include/opennurbs_curveonsurface.h b/opennurbs/Include/opennurbs_curveonsurface.h new file mode 100644 index 0000000..71f4fd3 --- /dev/null +++ b/opennurbs/Include/opennurbs_curveonsurface.h @@ -0,0 +1,201 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_CURVE_ON_SURFACE_INC_) +#define OPENNURBS_CURVE_ON_SURFACE_INC_ + +class ON_CLASS ON_CurveOnSurface : public ON_Curve +{ + ON_OBJECT_DECLARE(ON_CurveOnSurface); + +public: + ON_CurveOnSurface() ON_NOEXCEPT; + + /* + Remarks: + Deletes m_c2, m_c3, and m_s. Use ON_CurveProxy or ON_SurfaceProxy + if you need to use curves or a surface that you do not want deleted. + */ + virtual ~ON_CurveOnSurface(); + +private: + ON_CurveOnSurface(const ON_CurveOnSurface&); // no implementation + +private: + ON_CurveOnSurface& operator=(const ON_CurveOnSurface&); // no implementation + +#if defined(ON_HAS_RVALUEREF) +public: + // rvalue copy constructor + ON_CurveOnSurface( ON_CurveOnSurface&& ) ON_NOEXCEPT; + + // The rvalue assignment operator calls ON_Object::operator=(ON_Object&&) + // which could throw exceptions. See the implementation of + // ON_Object::operator=(ON_Object&&) for details. + ON_CurveOnSurface& operator=( ON_CurveOnSurface&& ); +#endif + +public: + /* + Parameters: + p2dCurve - [in] ~ON_CurveOnSurface() will delete this curve. + Use an ON_CurveProxy if you don't want the original deleted. + p3dCurve - [in] ~ON_CurveOnSurface() will delete this curve. + Use an ON_CurveProxy if you don't want the original deleted. + pSurface - [in] ~ON_CurveOnSurface() will delete this surface. + Use an ON_SurfaceProxy if you don't want the original deleted. + */ + ON_CurveOnSurface( ON_Curve* p2dCurve, // required 2d curve + ON_Curve* p3dCurve, // optional 3d curve + ON_Surface* pSurface // required surface + ); + + // virtual ON_Object::SizeOf override + unsigned int SizeOf() const override; + + + ///////////////////////////////////////////////////////////////// + // ON_Object overrides + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + void Dump( ON_TextLog& ) const override; // for debugging + + bool Write( + ON_BinaryArchive& // open binary file + ) const override; + + bool Read( + ON_BinaryArchive& // open binary file + ) override; + + ///////////////////////////////////////////////////////////////// + // ON_Geometry overrides + + int Dimension() const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + bool Transform( + const ON_Xform& + ) override; + + // (optional - default uses Transform for 2d and 3d objects) + bool SwapCoordinates( + int, int // indices of coords to swap + ) override; + + ///////////////////////////////////////////////////////////////// + // ON_Curve overrides + + ON_Interval Domain() const override; + + int SpanCount() const override; // number of smooth spans in curve + + bool GetSpanVector( // span "knots" + double* // array of length SpanCount() + 1 + ) const override; // + + int Degree( // returns maximum algebraic degree of any span + // ( or a good estimate if curve spans are not algebraic ) + ) const override; + + + // (optional - override if curve is piecewise smooth) + bool GetParameterTolerance( // returns tminus < tplus: parameters tminus <= s <= tplus + double, // t = parameter in domain + double*, // tminus + double* // tplus + ) const override; + + bool IsLinear( // true if curve locus is a line segment between + // between specified points + double = ON_ZERO_TOLERANCE // tolerance to use when checking linearity + ) const override; + + bool IsArc( // ON_Arc.m_angle > 0 if curve locus is an arc between + // specified points + const ON_Plane* = nullptr, // if not nullptr, test is performed in this plane + ON_Arc* = nullptr, // if not nullptr and true is returned, then arc parameters + // are filled in + double = ON_ZERO_TOLERANCE // tolerance to use when checking + ) const override; + + bool IsPlanar( + ON_Plane* = nullptr, // if not nullptr and true is returned, then plane parameters + // are filled in + double = ON_ZERO_TOLERANCE // tolerance to use when checking + ) const override; + + bool IsInPlane( + const ON_Plane&, // plane to test + double = ON_ZERO_TOLERANCE // tolerance to use when checking + ) const override; + + bool IsClosed( // true if curve is closed (either curve has + void // clamped end knots and euclidean location of start + ) const override; // CV = euclidean location of end CV, or curve is + // periodic.) + + bool IsPeriodic( // true if curve is a single periodic segment + void + ) const override; + + bool Reverse() override; // reverse parameterizatrion + // Domain changes from [a,b] to [-b,-a] + + bool Evaluate( // returns false if unable to evaluate + double, // evaluation parameter + int, // number of derivatives (>=0) + int, // array stride (>=Dimension()) + double*, // array of length stride*(ndir+1) + int = 0, // optional - determines which side to evaluate from + // 0 = default + // < 0 to evaluate from below, + // > 0 to evaluate from above + int* = 0 // optional - evaluation hint (int) used to speed + // repeated evaluations + ) const override; + + int GetNurbForm( // returns 0: unable to create NURBS representation + // with desired accuracy. + // 1: success - returned NURBS parameterization + // matches the curve's to wthe desired accuracy + // 2: success - returned NURBS point locus matches + // the curve's to the desired accuracy but, on + // the interior of the curve's domain, the + // curve's parameterization and the NURBS + // parameterization may not match to the + // desired accuracy. + ON_NurbsCurve&, + double = 0.0, + const ON_Interval* = nullptr // OPTIONAL subdomain of 2d curve + ) const override; + + ///////////////////////////////////////////////////////////////// + // Interface + + // ~ON_CurveOnSurface() deletes these classes. Use a + // ON_CurveProxy and/or ON_SurfaceProxy wrapper if you don't want + // the destructor to destroy the curves + ON_Curve* m_c2; // REQUIRED parameter space (2d) curve + ON_Curve* m_c3; // OPTIONAL 3d curve (approximation) to srf(crv2(t)) + ON_Surface* m_s; +}; + + +#endif diff --git a/opennurbs/Include/opennurbs_curveproxy.h b/opennurbs/Include/opennurbs_curveproxy.h new file mode 100644 index 0000000..5d8d819 --- /dev/null +++ b/opennurbs/Include/opennurbs_curveproxy.h @@ -0,0 +1,467 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +//////////////////////////////////////////////////////////////// +// +// Definition of curve proxy object +// +//////////////////////////////////////////////////////////////// + +#if !defined(OPENNURBS_CURVEPROXY_INC_) +#define OPENNURBS_CURVEPROXY_INC_ + +/* +Description: + An ON_CurveProxy is a reference to an ON_Curve. + One may specify a subdomain of the referenced curve + and apply a affine reparameterization, possibly reversing + the orientation. The underlying curve cannot be modified through + the curve proxy. +Details: + The reference to the "real_curve" is const, so most functions + which modify an ON_Curve will fail when passed an ON_CurveProxy. +*/ +class ON_CurveProxy; +class ON_CLASS ON_CurveProxy : public ON_Curve +{ + ON_OBJECT_DECLARE(ON_CurveProxy); + +public: + ON_CurveProxy() ON_NOEXCEPT; + virtual ~ON_CurveProxy(); + ON_CurveProxy( const ON_CurveProxy& ); + ON_CurveProxy& operator=(const ON_CurveProxy&); + +#if defined(ON_HAS_RVALUEREF) + // rvalue copy constructor + ON_CurveProxy( ON_CurveProxy&& ) ON_NOEXCEPT; + + // The rvalue assignment operator calls ON_Object::operator=(ON_Object&&) + // which could throw exceptions. See the implementation of + // ON_Object::operator=(ON_Object&&) for details. + ON_CurveProxy& operator=( ON_CurveProxy&& ); +#endif + +public: + // virtual ON_Object::DestroyRuntimeCache override + void DestroyRuntimeCache( bool bDelete = true ) override; + + + + ON_CurveProxy( const ON_Curve* ); + ON_CurveProxy( const ON_Curve*, ON_Interval ); + + // virtual ON_Object::SizeOf override + unsigned int SizeOf() const override; + + // virtual ON_Object::DataCRC override + ON__UINT32 DataCRC(ON__UINT32 current_remainder) const override; + + /* + Description: + Sets the curve geometry that "this" is a proxy for. + Sets proxy domain to proxy_curve->Domain(). + Parameters: + real_curve - [in] + */ + void SetProxyCurve( const ON_Curve* real_curve ); + + /* + Description: + Sets the curve geometry that "this" is a proxy for. + Sets proxy domain to proxy_curve->Domain(). + Parameters: + real_curve - [in] + real_curve_subdomain - [in] increasing sub interval of + real_curve->Domain(). This interval defines the + portion the "real" curve geometry that "this" proxy + uses. + bReversed - [in] true if the parameterization of "this" proxy + as a curve is reversed from the underlying "real" curve + geometry. + */ + void SetProxyCurve( const ON_Curve* real_curve, + ON_Interval real_curve_subdomain + ); + + /* + Returns: + "Real" curve geometry that "this" is a proxy for. + */ + const ON_Curve* ProxyCurve() const; + + /* + Description: + Sets portion of the "real" curve that this proxy represents. + Does NOT change the domain of "this" curve. + Parameters: + proxy_curve_subdomain - [in] increasing sub interval of + ProxyCurve()->Domain(). This interval defines the + portion the curve geometry that "this" proxy uses. + Remarks: + This function is poorly named. It does NOT set the proxy + curve's domain. It does set the interval of the "real" + curve for which "this" is a proxy. + */ + bool SetProxyCurveDomain( ON_Interval proxy_curve_subdomain ); + + + /* + Returns: + Sub interval of the "real" curve's domain that "this" uses. + This interval is not necessarily the same as "this" curve's + domain. + Remarks: + This function is poorly named. It does NOT get the proxy + curve's domain. It does get the evaluation interval + of the "real" curve for which "this" is a proxy. + */ + ON_Interval ProxyCurveDomain() const; + + /* + Returns: + True if "this" as a curve is reversed from the "real" curve + geometry. + */ + bool ProxyCurveIsReversed() const; + +protected: + // Used by CRhinoPolyEdgeSegment::Create() to restore the + // value of ON_CurveProxy::m_bReversed. + void SetProxyCurveIsReversed(bool bReversed); + +public: + /* + Parameters: + t - [in] parameter for "this" curve + Returns: + Corresponding parameter in m_real_curve's domain. + */ + double RealCurveParameter( double t ) const; + + /* + Parameters: + real_curve_parameter - [in] m_real_curve parameter + Returns: + Corresponding parameter for "this" curve + */ + double ThisCurveParameter( double real_curve_parameter ) const; + +private: + // "real" curve geometry that "this" is a proxy for. + const ON_Curve* m_real_curve; + // If true, the parameterization of "this" proxy is + // the reverse of the m_curve parameterization. + bool m_bReversed; + + // The m_domain interval is always increasing and included in + // m_curve->Domain(). The m_domain interval defines the portion + // of m_curve that "this" proxy uses and it can be a proper + // sub-interval of m_curve->Domain(). + ON_Interval m_real_curve_domain; + + // The evaluation domain of this curve. If "t" is a parameter for + // "this" and "r" is a parameter for m_curve, then when m_bReversed==false + // we have + // t = m_this_domain.ParameterAt(m_real_curve_domain.NormalizedParameterAt(r)) + // r = m_real_curve_domain.ParameterAt(m_this_domain.NormalizedParameterAt(t)) + // and when m_bReversed==true we have + // t = m_this_domain.ParameterAt(1 - m_real_curve_domain.NormalizedParameterAt(r)) + // r = m_real_curve_domain.ParameterAt(1 - m_this_domain.NormalizedParameterAt(t)) + ON_Interval m_this_domain; + + ON_Interval RealCurveInterval( const ON_Interval* sub_domain ) const; + + +public: + /* + Description: + Get a duplicate of the curve. + Returns: + A duplicate of the curve. + Remarks: + The caller must delete the returned curve. + For non-ON_CurveProxy objects, this simply duplicates the curve using + ON_Object::Duplicate. + For ON_CurveProxy objects, this duplicates the actual proxy curve + geometry and, if necessary, trims and reverse the result to that + the returned curve's parameterization and locus match the proxy curve's. + */ + ON_Curve* DuplicateCurve() const override; + + ///////////////////////////////////////////////////////////////// + // ON_Object overrides + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + void Dump( ON_TextLog& ) const override; // for debugging + + bool Write( // returns false - nothing serialized + ON_BinaryArchive& // open binary file + ) const override; + + bool Read( // returns false - nothing serialized + ON_BinaryArchive& // open binary file + ) override; + + ///////////////////////////////////////////////////////////////// + // ON_Geometry overrides + + int Dimension() const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + bool Transform( + const ON_Xform& + ) override; + + ///////////////////////////////////////////////////////////////// + // ON_Curve overrides + + // Returns: + // domain of the curve. + // Remarks: + // If m_bReverse is true, this returns the reverse + // of m_domain. + ON_Interval Domain() const override; + + /* virtual ON_Curve::SetDomain() override */ + bool SetDomain( + double t0, + double t1 + ) override; + + bool SetDomain( ON_Interval domain ); + + int SpanCount() const override; // number of smooth spans in curve + + bool GetSpanVector( + double* + ) const override; + + int Degree( // returns maximum algebraic degree of any span + // ( or a good estimate if curve spans are not algebraic ) + ) const override; + + // (optional - override if curve is piecewise smooth) + bool GetParameterTolerance( // returns tminus < tplus: parameters tminus <= s <= tplus + double, // t = parameter in domain + double*, // tminus + double* // tplus + ) const override; + + bool IsLinear( // true if curve locus is a line segment between + // between specified points + double = ON_ZERO_TOLERANCE // tolerance to use when checking linearity + ) const override; + + // virtual override of ON_Curve::IsPolyline + int IsPolyline( + ON_SimpleArray* pline_points = nullptr, + ON_SimpleArray* pline_t = nullptr + ) const override; + + bool IsArc( // ON_Arc.m_angle > 0 if curve locus is an arc between + // specified points + const ON_Plane* = nullptr, // if not nullptr, test is performed in this plane + ON_Arc* = nullptr, // if not nullptr and true is returned, then arc parameters + // are filled in + double = ON_ZERO_TOLERANCE // tolerance to use when checking + ) const override; + + bool IsPlanar( + ON_Plane* = nullptr, // if not nullptr and true is returned, then plane parameters + // are filled in + double = ON_ZERO_TOLERANCE // tolerance to use when checking + ) const override; + + bool IsInPlane( + const ON_Plane&, // plane to test + double = ON_ZERO_TOLERANCE // tolerance to use when checking + ) const override; + + bool IsClosed( // true if curve is closed (either curve has + void // clamped end knots and euclidean location of start + ) const override; // CV = euclidean location of end CV, or curve is + // periodic.) + + bool IsPeriodic( // true if curve is a single periodic segment + void + ) const override; + + /* + Description: + Search for a derivatitive, tangent, or curvature discontinuity. + Parameters: + c - [in] type of continity to test for. If ON::continuity::C1_continuous + t0 - [in] search begins at t0 + t1 - [in] (t0 < t1) search ends at t1 + t - [out] if a discontinuity is found, the *t reports the + parameter at the discontinuity. + hint - [in/out] if GetNextDiscontinuity will be called repeatedly, + passing a "hint" with initial value *hint=0 will increase the speed + of the search. + dtype - [out] if not nullptr, *dtype reports the kind of discontinuity + found at *t. A value of 1 means the first derivative or unit tangent + was discontinuous. A value of 2 means the second derivative or + curvature was discontinuous. + cos_angle_tolerance - [in] default = cos(1 degree) Used only when + c is ON::continuity::G1_continuous or ON::continuity::G2_continuous. If the cosine + of the angle between two tangent vectors + is <= cos_angle_tolerance, then a G1 discontinuity is reported. + curvature_tolerance - [in] (default = ON_SQRT_EPSILON) Used only when + c is ON::continuity::G2_continuous or ON::continuity::Gsmooth_continuous. + ON::continuity::G2_continuous: + If K0 and K1 are curvatures evaluated + from above and below and |K0 - K1| > curvature_tolerance, + then a curvature discontinuity is reported. + ON::continuity::Gsmooth_continuous: + If K0 and K1 are curvatures evaluated from above and below + and the angle between K0 and K1 is at least twice angle tolerance + or ||K0| - |K1|| > (max(|K0|,|K1|) > curvature_tolerance, + then a curvature discontinuity is reported. + Returns: + true if a discontinuity was found on the interior of the interval (t0,t1). + Remarks: + Overrides ON_Curve::GetNextDiscontinuity. + */ + bool GetNextDiscontinuity( + ON::continuity c, + double t0, + double t1, + double* t, + int* hint=nullptr, + int* dtype=nullptr, + double cos_angle_tolerance=ON_DEFAULT_ANGLE_TOLERANCE_COSINE, + double curvature_tolerance=ON_SQRT_EPSILON + ) const override; + + /* + Description: + Test continuity at a curve parameter value. + Parameters: + c - [in] continuity to test for + t - [in] parameter to test + hint - [in] evaluation hint + point_tolerance - [in] if the distance between two points is + greater than point_tolerance, then the curve is not C0. + d1_tolerance - [in] if the difference between two first derivatives is + greater than d1_tolerance, then the curve is not C1. + d2_tolerance - [in] if the difference between two second derivatives is + greater than d2_tolerance, then the curve is not C2. + cos_angle_tolerance - [in] default = cos(1 degree) Used only when + c is ON::continuity::G1_continuous or ON::continuity::G2_continuous. If the cosine + of the angle between two tangent vectors + is <= cos_angle_tolerance, then a G1 discontinuity is reported. + curvature_tolerance - [in] (default = ON_SQRT_EPSILON) Used only when + c is ON::continuity::G2_continuous or ON::continuity::Gsmooth_continuous. + ON::continuity::G2_continuous: + If K0 and K1 are curvatures evaluated + from above and below and |K0 - K1| > curvature_tolerance, + then a curvature discontinuity is reported. + ON::continuity::Gsmooth_continuous: + If K0 and K1 are curvatures evaluated from above and below + and the angle between K0 and K1 is at least twice angle tolerance + or ||K0| - |K1|| > (max(|K0|,|K1|) > curvature_tolerance, + then a curvature discontinuity is reported. + Returns: + true if the curve has at least the c type continuity at the parameter t. + Remarks: + Overrides ON_Curve::IsContinuous. + */ + bool IsContinuous( + ON::continuity c, + double t, + int* hint = nullptr, + double point_tolerance=ON_ZERO_TOLERANCE, + double d1_tolerance=ON_ZERO_TOLERANCE, + double d2_tolerance=ON_ZERO_TOLERANCE, + double cos_angle_tolerance=ON_DEFAULT_ANGLE_TOLERANCE_COSINE, + double curvature_tolerance=ON_SQRT_EPSILON + ) const override; + + bool Reverse() override; // reverse parameterizatrion + // Domain changes from [a,b] to [-b,-a] + + bool Evaluate( // returns false if unable to evaluate + double, // evaluation parameter + int, // number of derivatives (>=0) + int, // array stride (>=Dimension()) + double*, // array of length stride*(ndir+1) + int = 0, // optional - determines which side to evaluate from + // 0 = default + // < 0 to evaluate from below, + // > 0 to evaluate from above + int* = 0 // optional - evaluation hint (int) used to speed + // repeated evaluations + ) const override; + + + // override of virtual ON_Curve::Trim + bool Trim( + const ON_Interval& domain + ) override; + + // override of virtual ON_Curve::Split + bool Split( + double t, + ON_Curve*& left_side, + ON_Curve*& right_side + ) const override; + + int GetNurbForm( // returns 0: unable to create NURBS representation + // with desired accuracy. + // 1: success - returned NURBS parameterization + // matches the curve's to wthe desired accuracy + // 2: success - returned NURBS point locus matches + // the curve's to the desired accuracy but, on + // the interior of the curve's domain, the + // curve's parameterization and the NURBS + // parameterization may not match to the + // desired accuracy. + ON_NurbsCurve&, + double = 0.0, + const ON_Interval* = nullptr // OPTIONAL subdomain of ON_CurveProxy::Domain() + ) const override; + + int HasNurbForm( // returns 0: unable to create NURBS representation + // with desired accuracy. + // 1: success - returned NURBS parameterization + // matches the curve's to wthe desired accuracy + // 2: success - returned NURBS point locus matches + // the curve's to the desired accuracy but, on + // the interior of the curve's domain, the + // curve's parameterization and the NURBS + // parameterization may not match to the + // desired accuracy. + ) const override; + + // virtual ON_Curve::GetCurveParameterFromNurbFormParameter override + bool GetCurveParameterFromNurbFormParameter( + double, // nurbs_t + double* // curve_t + ) const override; + + // virtual ON_Curve::GetNurbFormParameterFromCurveParameter override + bool GetNurbFormParameterFromCurveParameter( + double, // curve_t + double* // nurbs_t + ) const override; +}; + + +#endif diff --git a/opennurbs/Include/opennurbs_cylinder.h b/opennurbs/Include/opennurbs_cylinder.h new file mode 100644 index 0000000..e28bfea --- /dev/null +++ b/opennurbs/Include/opennurbs_cylinder.h @@ -0,0 +1,152 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_CYLINDER_INC_) +#define OPENNURBS_CYLINDER_INC_ + +class ON_NurbsSurface; +class ON_RevSurface; +class ON_Brep; + +/* +Description: + ON_Cylinder is a right circular cylinder. +*/ +class ON_CLASS ON_Cylinder +{ +public: + ON_Cylinder(); // zeros all fields - cylinder is invalid + + ON_Cylinder( // infinte cylinder + const ON_Circle& // point on the bottom plane + ); + + ON_Cylinder( // infinte cylinder + const ON_Circle&, // point on the bottom plane + double // height + ); + + ~ON_Cylinder(); + + bool Create( + const ON_Circle& // point on the bottom plane + ); + + bool Create( + const ON_Circle&, // point on the bottom plane + double // height + ); + + bool IsValid() const; // returns true if all fields contain reasonable + // information and equation jibes with point and Z. + + bool IsFinite() const; // returns true if the cylinder is finite + // (height[0] != height[1]) and false if the + // cylinder is infinite. + + const ON_3dVector& Axis() const; + const ON_3dPoint& Center() const; + double Height() const; // returns 0 for infinite cylinder + ON_Circle CircleAt( + double // linear parameter + ) const; + ON_Line LineAt( + double // angular parameter + ) const; + + // evaluate parameters and return point + ON_3dPoint PointAt( + double, // angular parameter [0,2pi] + double // linear parameter (height from base circle's plane) + ) const; + ON_3dPoint NormalAt( + double, // angular parameter [0,2pi] + double // linear parameter (height from base circle's plane) + ) const; + + // returns parameters of point on cylinder that is closest to given point + bool ClosestPointTo( + ON_3dPoint, + double*, // angular parameter [0,2pi] + double* // linear parameter (height from base circle's plane) + ) const; + // returns point on cylinder that is closest to given point + ON_3dPoint ClosestPointTo( + ON_3dPoint + ) const; + + // For intersections see ON_Intersect(); + + // rotate cylinder about its origin + bool Rotate( + double, // sin(angle) + double, // cos(angle) + const ON_3dVector& // axis of rotation + ); + bool Rotate( + double, // angle in radians + const ON_3dVector& // axis of rotation + ); + + // rotate cylinder about a point and axis + bool Rotate( + double, // sin(angle) + double, // cos(angle) + const ON_3dVector&, // axis of rotation + const ON_3dPoint& // center of rotation + ); + bool Rotate( + double, // angle in radians + const ON_3dVector&, // axis of rotation + const ON_3dPoint& // center of rotation + ); + + bool Translate( + const ON_3dVector& + ); + + // parameterization of NURBS surface does not match cylinder's transcendental paramaterization + int GetNurbForm( ON_NurbsSurface& ) const; // returns 0=failure, 2=success + + /* + Description: + Creates a surface of revolution definition of the cylinder. + Parameters: + srf - [in] if not nullptr, then this srf is used. + Result: + A surface of revolution or nullptr if the cylinder is not + valid or is infinite. + */ + ON_RevSurface* RevSurfaceForm( ON_RevSurface* srf = nullptr ) const; + +public: // members left public + // base circle + ON_Circle circle; + + + // If height[0] = height[1], the cylinder is infinite, + // Otherwise, height[0] < height[1] and the center of + // the "bottom" cap is + // + // circle.plane.origin + height[0]*circle.plane.zaxis, + // + // and the center of the top cap is + // + // circle.plane.origin + height[1]*circle.plane.zaxis. + double height[2]; +}; + +#endif diff --git a/opennurbs/Include/opennurbs_date.h b/opennurbs/Include/opennurbs_date.h new file mode 100644 index 0000000..89e668b --- /dev/null +++ b/opennurbs/Include/opennurbs_date.h @@ -0,0 +1,108 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2013 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_DATE_INC_) +#define OPENNURBS_DATE_INC_ + +/* +Description: + Get the day of the year from the year, month and day_of_month. +Parameters: + year - [in] + >= 1582 + month - [in] + >= 1 and <= 12 + day_of_month - [in] + >= 1 and <= last valid day_of_month of the month +Returns: + 0: Invalid input + 1 to 366: Day of Gregorian year. +*/ +ON_DECL +unsigned int ON_DayOfGregorianYear( + unsigned int year, + unsigned int month, + unsigned int day_of_month + ); + +/* +Parameters: + year - [in] + >= 1582 +Returns: + 0: Invalid input + 365: If the year is a common year in the Gregorian calendar + 366: If the year is a leap year in the Gregorian calendar +*/ +ON_DECL +unsigned int ON_DaysInGregorianYear( + unsigned int year + ); +/* +Description: + Get the number of days in a Gregorian month. +Parameters: + year - [in] + >= 1582 + month - [in] + >= 1 and <= 12 +Returns: + 0: Invalid input + 28, 29, 30 or 31: number of days in the specified month. +*/ +ON_DECL +unsigned int ON_DaysInMonthOfGregorianYear( + unsigned int year, + unsigned int month + ); + +/* +Description: + Get the month and day_of_month from the year and day of year. +Parameters: + year - [in] + >= 1582 + day_of_year + >= 1 and <= (ON_IsGregorianLeapYear(year) ? 366 : 365) + month - [out] + >= 1 and <= 12, when input parameters are valid, otherwise 0. + day_of_month - [out] + >= 1 and <= ON_DaysInMonthOfGregorianYear(year,month), + when input parameters are valid, otherwise 0. +Returns: + true: month and day_of_month returned. + false: invalid input. Output values are zero. +*/ +ON_DECL +bool ON_GetGregorianMonthAndDayOfMonth( + unsigned int year, + unsigned int day_of_year, + unsigned int* month, + unsigned int* day_of_month + ); + +/* +Parameters: + year - [in] +Returns: + true if the year is a leap year in the Gregorian calendar. +*/ +ON_DECL +bool ON_IsGregorianLeapYear( + unsigned int year + ); + +#endif diff --git a/opennurbs/Include/opennurbs_defines.h b/opennurbs/Include/opennurbs_defines.h new file mode 100644 index 0000000..187be08 --- /dev/null +++ b/opennurbs/Include/opennurbs_defines.h @@ -0,0 +1,2949 @@ +/* +// Copyright (c) 1993-2016 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +//////////////////////////////////////////////////////////////// +// +// Includes all openNURBS toolkit defines and enums. +// +//////////////////////////////////////////////////////////////// + +#if !defined(OPENNURBS_DEFINES_INC_) +#define OPENNURBS_DEFINES_INC_ + +#if !defined(OPENNURBS_SYSTEM_INC_) +#error Include opennurbs_system.h before opennurbs_defines.h +#endif + +#if defined (cplusplus) || defined(_cplusplus) || defined(__cplusplus) || defined(ON_CPLUSPLUS) +// C++ extern "C" declaration for C linkage + +#if !defined(ON_CPLUSPLUS) +#define ON_CPLUSPLUS +#endif +#define ON_EXTERNC extern "C" +#define ON_BEGIN_EXTERNC extern "C" { +#define ON_END_EXTERNC } + +#define ON_UINT_FROM_ENUM(e) (static_cast(e)) +#define ON_INT_FROM_ENUM(e) ((int)static_cast(e)) + +#else + +/* C file - no extern declaration required or permitted */ + +#define ON_EXTERNC +#define ON_BEGIN_EXTERNC +#define ON_END_EXTERNC + +#endif + + +/* +// Declarations in header (.H) files look like +// +// ON_DECL type function(): +// extern ON_EXTERN_DECL type global_variable; +// class ON_CLASS classname {}; +// ON_TEMPLATE template class ON_CLASS template; +// +*/ + +#define ON_ENUM_FROM_UNSIGNED_CASE(e) case (unsigned int)e: return(e); break +#define ON_ENUM_TO_STRING_CASE(e) case e: return( ON_String(#e) ); break +#define ON_ENUM_TO_WIDE_STRING_CASE(e) case e: return( ON_wString(#e) ); break +#define ON_ENUM_TO_STRING_CASE_SET(e,s) case e: (s)=ON_String(#e); break +#define ON_ENUM_TO_WIDE_STRING_CASE_SET(e,s) case e: (s)=ON_wString(#e); break + +/* export/import */ +#if defined(OPENNURBS_EXPORTS) +/* compiling opennurbs as some type of dynamic linking library */ + +#if defined(ON_COMPILER_MSC) +/* compiling OpenNurbs as a Windows DLL - export classes, functions, templates, and globals */ +#define ON_CLASS __declspec(dllexport) +#define ON_DECL __declspec(dllexport) +#define ON_EXTERN_DECL __declspec(dllexport) +#define ON_DLL_TEMPLATE + +#elif defined(ON_COMPILER_CLANG) +/* compiling opennurbs as an Apple shared library */ +#define ON_CLASS __attribute__ ((visibility ("default"))) +#define ON_DECL __attribute__ ((visibility ("default"))) +#define ON_EXTERN_DECL __attribute__ ((visibility ("default"))) + +#else +#error fill in your compiler dynamic linking decorations +#endif + +#elif defined(OPENNURBS_IMPORTS) +/* dynamically linking with opennurbs in some way */ + +#if defined(ON_COMPILER_MSC) +/* using OpenNurbs as a Windows DLL - import classes, functions, templates, and globals */ +#define ON_CLASS __declspec(dllimport) +#define ON_DECL __declspec(dllimport) +#define ON_EXTERN_DECL __declspec(dllimport) +#define ON_DLL_TEMPLATE extern + +#elif defined(ON_COMPILER_CLANG) +/* using opennurbs as an Apple shared library */ +#define ON_CLASS __attribute__ ((visibility ("default"))) +#define ON_DECL __attribute__ ((visibility ("default"))) +#define ON_EXTERN_DECL __attribute__ ((visibility ("default"))) + +#else +#error fill in your compiler dynamic linking decorations +#endif + +#else + +/* compiling or using OpenNurbs as a static library */ +#define ON_CLASS +#define ON_DECL +#define ON_EXTERN_DECL + +#if defined(ON_DLL_TEMPLATE) +#undef ON_DLL_TEMPLATE +#endif + +#endif + + +// ON_DEPRECATED is used to mark deprecated functions. +#if defined(ON_COMPILER_MSC) +#define ON_DEPRECATED __declspec(deprecated) +#define ON_DEPRECATED_MSG(s) [[deprecated(s)]] +#if defined(OPENNURBS_IN_RHINO) +#define ON_WIP_SDK +#define ON_INTERNAL_SDK +#else +#define ON_WIP_SDK [[deprecated("Do not use! This function is a work in progress and will change.")]] +#define ON_INTERNAL_SDK [[deprecated("Do not use! This function is internal.")]] +#endif +#elif defined(ON_COMPILER_CLANG) +#define ON_DEPRECATED __attribute__((deprecated)) +#define ON_DEPRECATED_MSG(s) [[deprecated(s)]] +#if defined(OPENNURBS_IN_RHINO) +#define ON_WIP_SDK +#define ON_INTERNAL_SDK +#else +#define ON_WIP_SDK [[deprecated("Do not use! This function is a work in progress and will change.")]] +#define ON_INTERNAL_SDK [[deprecated("Do not use! This function is internal.")]] +#endif +#else +#define ON_DEPRECATED +#define ON_DEPRECATED_MSG(s) +#define ON_WIP_SDK +#define ON_INTERNAL_SDK +#endif + +#if defined(PI) +/* double precision ON_PI = 3.141592653589793238462643. ON_PI radians = 180 degrees */ +#define ON_PI PI +#else +/* double precision ON_PI = 3.141592653589793238462643. ON_PI radians = 180 degrees */ +#define ON_PI 3.141592653589793238462643 +#endif + +/* double precision ON_2PI = 2.0*ON_PI. ON_2PI radians = 360 degrees. */ +#define ON_2PI (2.0*ON_PI) + +/* double precision ON_HALFPI = 0.5*ON_PI. ON_HALFPI radians = 90 degrees. */ +#define ON_HALFPI (0.5*ON_PI) + +/* angle_in_degrees = ON_DEGREES_TO_RADIANS*angle_in_radians */ +#define ON_DEGREES_TO_RADIANS (ON_PI/180.0) + +/* angle_in_radians = ON_RADIANS_TO_DEGREES*angle_in_degrees */ +#define ON_RADIANS_TO_DEGREES (180.0/ON_PI) + +/* +Parameters: + angle_in_radians - [in] + Angle measure in radians +Returns: + Angle measure in degrees +*/ +ON_DECL +double ON_DegreesFromRadians( + double angle_in_radians +); + +/* +Parameters: + angle_in_degrees - [in] + Angle measure in degrees +Returns: + Angle measure in radians +*/ +ON_DECL +double ON_RadiansFromDegrees( + double angle_in_degrees +); + +#define ON_SQRT2 1.414213562373095048801689 +#define ON_SQRT3 1.732050807568877293527446 +#define ON_SQRT3_OVER_2 0.8660254037844386467637230 +#define ON_1_OVER_SQRT2 0.7071067811865475244008445 +#define ON_SIN_PI_OVER_12 0.2588190451025207623488990 +#define ON_COS_PI_OVER_12 0.9659258262890682867497433 + +#define ON_LOG2 0.6931471805599453094172321 +#define ON_LOG10 2.302585092994045684017991 + +#define ON_ArrayCount(a) (sizeof(a)/sizeof((a)[0])) + +#if defined(DBL_MAX) +#define ON_DBL_MAX DBL_MAX +#else +#define ON_DBL_MAX 1.7976931348623158e+308 +#endif + +#if defined(DBL_MIN) +#define ON_DBL_MIN DBL_MIN +#else +#define ON_DBL_MIN 2.22507385850720200e-308 +#endif + +// ON_EPSILON = 2^-52 +#if defined(DBL_EPSILON) +#define ON_EPSILON DBL_EPSILON +#else +#define ON_EPSILON 2.2204460492503131e-16 +#endif +#define ON_SQRT_EPSILON 1.490116119385000000e-8 + +#if defined(FLT_EPSILON) +#define ON_FLOAT_EPSILON FLT_EPSILON +#else +#define ON_FLOAT_EPSILON 1.192092896e-07 +#endif +#define ON_SQRT_FLOAT_EPSILON 3.452669830725202719e-4 + + +#if defined(UINT_MAX) +#define ON_UINT_MAX UINT_MAX +#else +#define ON_UINT_MAX (~(0U)) +#endif + +/* +// In cases where lazy evaluation of a double value is +// performed, b-rep tolerances being a notable example, +// this value is used to indicate the value has not been +// computed. This value must be < -1.0e308. and > -ON_DBL_MAX +// +// The reasons ON_UNSET_VALUE is a valid finite number are: +// +// 1) It needs to round trip through fprintf/sscanf. +// 2) It needs to persist unchanged through assigment +/ and not generate exceptions when assigned. +// 3) ON_UNSET_VALUE == ON_UNSET_VALUE needs to be true. +// 4) ON_UNSET_VALUE != ON_UNSET_VALUE needs to be false. +// +// Ideally, it would also have these SNaN attributes +// * When used in a calculation, a floating point exception +// occures. +// * No possibility of a valid calculation would generate +// ON_UNSET_VALUE. +// * float f = (float)ON_UNSET_VALUE would create an invalid +// float and generate an exception. +*/ +#define ON_UNSET_POSITIVE_VALUE 1.23432101234321e+308 +#define ON_UNSET_VALUE -ON_UNSET_POSITIVE_VALUE + +/* +// ON_UNSET_FLOAT is used to indicate a texture coordinate +// value cannot be calculated or is not well defined. +// In hindsight, this value should have been ON_FLT_QNAN +// because many calculation convert float texture coordinates +// to doubles and the "unset"ness attribute is lost. +*/ +#define ON_UNSET_POSITIVE_FLOAT 1.234321e+38f +#define ON_UNSET_FLOAT -ON_UNSET_POSITIVE_FLOAT + +// When unsigned int values are used in a context where +// 0 is a valid index and there needs to be a value that +// indicates the index is not set, use ON_UNSET_UINT_INDEX. +#define ON_UNSET_UINT_INDEX 0xFFFFFFFFU + +// When signed int values are used in a context where +// 0 and small negative values are valid indices and there needs +// to be a value that indicates the index is not set, +// use ON_UNSET_INT_INDEX. This value is INT_MIN+1 +#define ON_UNSET_INT_INDEX ((const int)-2147483647) + +ON_BEGIN_EXTERNC + +// IEEE 754 special values + +extern ON_EXTERN_DECL const double ON_DBL_QNAN; +extern ON_EXTERN_DECL const double ON_DBL_PINF; +extern ON_EXTERN_DECL const double ON_DBL_NINF; + +extern ON_EXTERN_DECL const float ON_FLT_QNAN; +extern ON_EXTERN_DECL const float ON_FLT_PINF; +extern ON_EXTERN_DECL const float ON_FLT_NINF; + + +/* +The ON_PTR_SEMAPHORE* values are used in rare cases +when a special signal must be passed as a pointer argument. +The values must be a multiple of 8 to suppress runtime pointer alignment checks. +The values must never be a valid user heap or stack pointer value. +*/ +#define ON_PTR_SEMAPHORE1 ((ON__UINT_PTR)8) +#define ON_PTR_SEMAPHORE2 ((ON__UINT_PTR)16) +#define ON_PTR_SEMAPHORE3 ((ON__UINT_PTR)24) +#define ON_PTR_SEMAPHORE4 ((ON__UINT_PTR)32) +#define ON_PTR_SEMAPHORE_MAX ((ON__UINT_PTR)32) + + +/* +Description: +Paramters: + x - [out] returned value of x is an SNan + (signalling not a number). +Remarks: + Any time an SNaN passes through an Intel FPU, the result + is a QNaN (quiet nan) and the invalid operation excpetion + flag is set. If this exception is not masked, then the + exception handler is invoked. + + double x, y; + ON_DBL_SNAN(&x); + y = x; // y = QNAN and invalid op exception occurs + z = sin(x) // z = QNAN and invalid op exception occurs + + So, if you want to reliably initialize doubles to SNaNs, + you must use memcpy() or some other method that does not + use the Intel FPU. +*/ +ON_DECL +void ON_DBL_SNAN( double* x ); + +ON_DECL +void ON_FLT_SNAN( float* x ); + +/* +Returns: + ON_UNSET_FLOAT, if x = ON_UNSET_VALUE. + ON_UNSET_POSITIVE_FLOAT, if x = ON_UNSET_POSITIVE_VALUE. + (float)x, otherwise. +*/ +ON_DECL +float ON_FloatFromDouble( + double x +); + +/* +Returns: + ON_UNSET_VALUE, if x = ON_UNSET_FLOAT. + ON_UNSET_POSITIVE_VALUE, if x = ON_UNSET_POSITIVE_FLOAT. + (double)x, otherwise. +*/ +ON_DECL +double ON_DoubleFromFloat( + float x +); + +/* +Returns: + A nonzero runtime unsigned that is incremented every call to ON_NextContentSerialNumber(). + This value is useful as a "content serial number" that can be used to detect + when the content of an object has changed. +*/ +ON__UINT64 ON_NextContentSerialNumber(); + +ON_END_EXTERNC + +#if defined(ON_CPLUSPLUS) +ON_DECL +bool ON_IsNullPtr(const void* ptr); + +ON_DECL +bool ON_IsNullPtr(const ON__UINT_PTR ptr); + +ON_DECL +bool ON_IsNullPtr(const ON__INT_PTR ptr); +#endif + +/* +// In cases where lazy evaluation of a color value is +// performed, this value is used to indicate the value +// has not been computed. +*/ +#define ON_UNSET_COLOR 0xFFFFFFFF + +/* +// In cases when an absolute "zero" tolerance +// is required to compare model space coordinates, +// ON_ZERO_TOLERANCE is used. The value of +// ON_ZERO_TOLERANCE should be no smaller than +// ON_EPSILON and should be several orders of +// magnitude smaller than ON_SQRT_EPSILON +// +*/ +//#define ON_ZERO_TOLERANCE 1.0e-12 +// ON_ZERO_TOLERANCE = 2^-32 +#define ON_ZERO_TOLERANCE 2.3283064365386962890625e-10 + +/* +// In cases when an relative "zero" tolerance is +// required for comparing model space coordinates, +// (fabs(a)+fabs(b))*ON_RELATIVE_TOLERANCE is used. +// ON_RELATIVE_TOLERANCE should be larger than +// ON_EPSILON and smaller than no larger than +// ON_ZERO_TOLERANCE*2^-10. +// +*/ +// ON_RELATIVE_TOLERANCE = 2^-42 +#define ON_RELATIVE_TOLERANCE 2.27373675443232059478759765625e-13 + +/* +// Bugs in geometry calculations involving world coordinates +// values > ON_MAXIMUM_WORLD_COORDINATE_VALUE +// will be a low priority. +*/ +// ON_MAXIMUM_VALUE = 2^27 +#define ON_MAXIMUM_WORLD_COORDINATE_VALUE 1.34217728e8 + +/* +// Any 3d coordinate value >= ON_NONSENSE_WORLD_COORDINATE_VALUE +// will be adjusted as needed. Any calculation creating 3d coordinates +// with values >= ON_NONSENSE_WORLD_COORDINATE_VALUE should be +// inspected for bugs. +*/ +// ON_NONSENSE_WORLD_COORDINATE_VALUE = 1.0e100 +#define ON_NONSENSE_WORLD_COORDINATE_VALUE 1.0e100 + +/* +// The default test for deciding if a curvature value should be +// treated as zero is +// length(curvature) <= ON_ZERO_CURVATURE_TOLERANCE. +// ON_ZERO_CURVATURE_TOLERANCE must be set so that +// ON_ZERO_CURVATURE_TOLERANCE >= sqrt(3)*ON_ZERO_TOLERANCE +// so that K.IsTiny() = true implies |K| <= ON_ZERO_CURVATURE_TOLERANCE +*/ +#define ON_ZERO_CURVATURE_TOLERANCE 1.0e-8 +#define ON_RELATIVE_CURVATURE_TOLERANCE 0.05 + +/* default value for angle tolerances = 1 degree */ +#define ON_DEFAULT_ANGLE_TOLERANCE_RADIANS (ON_PI/180.0) +#define ON_DEFAULT_ANGLE_TOLERANCE_DEGREES (ON_DEFAULT_ANGLE_TOLERANCE_RADIANS * 180.0/ON_PI) +#define ON_DEFAULT_ANGLE_TOLERANCE ON_DEFAULT_ANGLE_TOLERANCE_RADIANS +#define ON_DEFAULT_ANGLE_TOLERANCE_COSINE 0.99984769515639123915701155881391 +#define ON_MINIMUM_ANGLE_TOLERANCE (ON_DEFAULT_ANGLE_TOLERANCE/10.0) + +#define ON_DEFAULT_DISTANCE_TOLERANCE_MM 0.01 + +/* +*/ +ON_DECL +ON__UINT64 ON_SecondsSinceJanOne1970UTC(); + +union ON_U +{ + char b[8]; // 8 bytes + ON__INT64 h; // 64 bit integer + ON__INT32 i; // 32 bit integer + int j[2]; // two 32 bit integers + void* p; + double d; +}; + +#if defined(ON_CPLUSPLUS) + +// pair of integer indices. This +// is intentionally a struct/typedef +// rather than a class so that it +// can be used in other structs. +class ON_CLASS ON_2dex +{ +public: + ON_2dex() = default; + ~ON_2dex() = default; + ON_2dex(const ON_2dex&) = default; + ON_2dex& operator=(const ON_2dex&) = default; + +public: + // do not initialize i, j for performance reasons + int i; + int j; + + ON_2dex(int i, int j); + + static const ON_2dex Unset; // (ON_UNSET_INT_INDEX, ON_UNSET_INT_INDEX); + static const ON_2dex Zero; // (0, 0) +}; + +class ON_CLASS ON_2udex +{ +public: + ON_2udex() = default; + ~ON_2udex() = default; + ON_2udex(const ON_2udex&) = default; + ON_2udex& operator=(const ON_2udex&) = default; + +public: + // do not initialize i, j for performance reasons + unsigned int i; + unsigned int j; + + ON_2udex(unsigned int i, unsigned int j); + + static int DictionaryCompare( + const ON_2udex* lhs, + const ON_2udex* rhs + ); + + static int CompareFirstIndex( + const ON_2udex* lhs, + const ON_2udex* rhs + ); + + static int CompareSecondIndex( + const ON_2udex* lhs, + const ON_2udex* rhs + ); + + static const ON_2udex Unset; // (ON_UNSET_UINT_INDEX, ON_UNSET_UINT_INDEX); + static const ON_2udex Zero; // (0, 0) +}; + +class ON_CLASS ON_3dex +{ +public: + ON_3dex() = default; + ~ON_3dex() = default; + ON_3dex(const ON_3dex&) = default; + ON_3dex& operator=(const ON_3dex&) = default; + +public: + // do not initialize i, j, k for performance reasons + int i; + int j; + int k; + + ON_3dex(int i, int j, int k); + + static const ON_3dex Unset; // (ON_UNSET_UINT_INDEX, ON_UNSET_UINT_INDEX, ON_UNSET_UINT_INDEX); + static const ON_3dex Zero; // (0, 0, 0) +}; + +class ON_CLASS ON_3udex +{ +public: + ON_3udex() = default; + ~ON_3udex() = default; + ON_3udex(const ON_3udex&) = default; + ON_3udex& operator=(const ON_3udex&) = default; + +public: + // do not initialize i, j, k for performance reasons + unsigned int i; + unsigned int j; + unsigned int k; + + ON_3udex(unsigned int i, unsigned int j, unsigned int k); + + static const ON_3udex Unset; // (ON_UNSET_UINT_INDEX, ON_UNSET_UINT_INDEX, ON_UNSET_UINT_INDEX); + static const ON_3udex Zero; // (0, 0, 0) + + static int DictionaryCompare( + const ON_3udex* lhs, + const ON_3udex* rhs + ); + + static int CompareFirstIndex( + const ON_3udex* lhs, + const ON_3udex* rhs + ); + + static int CompareSecondIndex( + const ON_3udex* lhs, + const ON_3udex* rhs + ); + + static int CompareThirdIndex( + const ON_3udex* lhs, + const ON_3udex* rhs + ); + + static int CompareFirstAndSecondIndex( + const ON_3udex* lhs, + const ON_3udex* rhs + ); + +}; + +// quadruplet of integer indices. +class ON_CLASS ON_4dex +{ +public: + ON_4dex() = default; + ~ON_4dex() = default; + ON_4dex(const ON_4dex&) = default; + ON_4dex& operator=(const ON_4dex&) = default; + + + int operator[](int i) const; + int& operator[](int i); +public: + // do not initialize i, j, k, l for performance reasons + int i; + int j; + int k; + int l; + + ON_4dex(int i, int j, int k, int l); + + static const ON_4dex Unset; // (ON_UNSET_INT_INDEX, ON_UNSET_INT_INDEX, ON_UNSET_INT_INDEX, ON_UNSET_INT_INDEX); + static const ON_4dex Zero; // (0, 0, 0, 0) +}; + +class ON_CLASS ON_4udex +{ +public: + ON_4udex() = default; + ~ON_4udex() = default; + ON_4udex(const ON_4udex&) = default; + ON_4udex& operator=(const ON_4udex&) = default; + +public: + // do not initialize i, j, k, l for performance reasons + unsigned int i; + unsigned int j; + unsigned int k; + unsigned int l; + + ON_4udex(unsigned int i, unsigned int j, unsigned int k, unsigned int l); + + static const ON_4udex Unset; // (ON_UNSET_UINT_INDEX, ON_UNSET_UINT_INDEX, ON_UNSET_UINT_INDEX, ON_UNSET_UINT_INDEX); + static const ON_4udex Zero; // (0, 0, 0, 0) +}; + + +enum class ON_StringMapType : int +{ + Identity = 0, + UpperCase = 1, + LowerCase = 2 +}; + +enum class ON_StringMapOrdinalType : int +{ + Identity = 0, + UpperOrdinal = 1, + LowerOrdinal = 2, + MinimumOrdinal = 3 +}; + +enum class ON_DateFormat : int +{ + Unset = 0, + Omit = 1, + + /// + /// February 1st, 2001 = 2001-2-1 + /// + YearMonthDay = 2, + + /// + /// February 1st, 2001 = 2001-1-2 + /// + YearDayMonth = 3, + + /// + /// February 1st, 2001 = 2-1-2001 + /// + MonthDayYear = 4, + + /// + /// February 1st, 2001 = 1-2-2001 + /// + DayMonthYear = 5, + + /// + /// February 1st, 2001 = 2001-32 + /// + YearDayOfYear = 6 +}; + +enum class ON_TimeFormat : int +{ + Unset = 0, + Omit = 1, + HourMinute12 = 2, + HourMinuteSecond12 = 3, + HourMinute24 = 4, + HourMinuteSecond24 = 5 +}; + +ON_DECL +ON_StringMapOrdinalType ON_StringMapOrdinalTypeFromStringMapType( + ON_StringMapType map_type + ); + +/// +/// ON_ChainDirection is used to specify directions when building +/// chains of components like edges or faces. +/// +enum class ON_ChainDirection : unsigned char +{ + Unset = 0, + + /// + /// Search for chain links before the current link. + /// + Previous = 1, + + /// + /// Search for chain links after the current link. + /// + Next = 2, + + /// + /// Search for chain links before and after the current link. + /// + Both = 3 +}; + +/// +///Style of color gradient +/// +enum class ON_GradientType : int +{ + ///No gradient + None = 0, + ///Linear (or axial) gradient between two points + Linear = 1, + ///Radial (or spherical) gradient using a center point and a radius + Radial = 2, + ///Disabled linear gradient. Useful for keeping gradient information around, but not having it displayed + LinearDisabled = 3, + ///Disabled radial gradient. Useful for keeping gradient information around, but not having it displayed + RadialDisabled = 4 +}; + + +// OpenNurbs enums +class ON_CLASS ON +{ +public: + /* + Description: + Call before using openNURBS to ensure all class definitions + are linked. + */ + static void Begin(); + + + /* + Description: + Call when finished with openNURBS. + Remarks: + Currently does nothing. + */ + static void End(); + + /* + Returns: + 0: not initialized + 1: in the body of ON:Begin() + 2: ON::Begin() has finished. + */ + static unsigned int LibraryStatus(); + + /* + Set the library status + */ + static void SetLibraryStatus(unsigned int status); + + /* + Returns: + The value of OPENNURBS_VERSION_NUMBER, which is defined in opennurbs_version.h. + Remarks: + The high bit of this number is set. Do not cast the result as an int. + */ + static + unsigned int Version(); + + /* + Returns: + The value of OPENNURBS_VERSION_MAJOR, which is defined in opennurbs_version.h + (0 to 63). + */ + static + unsigned int VersionMajor(); + + /* + Returns: + 63 = maximum major version number that opennurbs version number utilities can handle. + */ + static + unsigned int VersionMajorMaximum(); + + /* + Returns: + The value of OPENNURBS_VERSION_MINOR, which is defined in opennurbs_version.h + (0 to 127). + */ + static + unsigned int VersionMinor(); + + /* + Returns: + 127 = maximum minor version number that opennurbs version number utilities can handle. + */ + static + unsigned int VersionMinorMaximum(); + + /* + Returns: + The value of OPENNURBS_VERSION_YEAR, which is defined in opennurbs_version.h + > 2014. + */ + static + unsigned int VersionYear(); + + /* + Returns: + The value of OPENNURBS_VERSION_MONTH, which is defined in opennurbs_version.h + 1 to 12. + */ + static + unsigned int VersionMonth(); + + /* + Returns: + The value of OPENNURBS_VERSION_DAY_OF_MONTH, which is defined in opennurbs_version.h + (1 to 31). + */ + static + unsigned int VersionDayOfMonth(); + + /* + Returns: + The value of OPENNURBS_VERSION_HOUR, which is defined in opennurbs_version.h + (0 to 23). + */ + static + unsigned int VersionHour(); + + /* + Returns: + The value of OPENNURBS_VERSION_MINUTE, which is defined in opennurbs_version.h + (0 to 59). + */ + static + unsigned int VersionMinute(); + + /* + Returns: + The value of OPENNURBS_VERSION_BRANCH, which is defined in opennurbs_version.h + 0: developer build + 1: Windows Commercial build + 2: Mac Commercial build + 3: Windows BETA build + 4: Mac Beta build + 5: Windows WIP build + 6: Mac WIP build + */ + static + unsigned int VersionBranch(); + + /* + Description: + Get the opennurbs version number as a quartet of values. + Parameters: + version_quartet - [out] + version_quartet[0] = ON::VersionMajor() + version_quartet[1] = ON::VersionMinor() + version_quartet[2] = (year - 2000)*1000 + day_of_year + version_quartet[3] = (hour*1000 + minute*10 + OPENNURBS_VERSION_BRANCH) + Returns: + The value of OPENNURBS_VERSION_NUMBER, which is defined in opennurbs_version.h. + Remarks: + The high bit of the returned value is set. Do not cast the result as an int. + */ + static + unsigned int VersionGetQuartet( + unsigned int version_quartet[4] + ); + + + /* + Returns: + The value of OPENNURBS_VERSION_QUARTET_STRING, which is defined in opennurbs_version.h. + Remarks: + The high bit of this number is set. Do not cast the result as an int. + */ + static + const char* VersionQuartetAsString(); + + /* + Returns: + The value of OPENNURBS_VERSION_QUARTET_WSTRING, which is defined in opennurbs_version.h. + Remarks: + The high bit of this number is set. Do not cast the result as an int. + */ + static + const wchar_t* VersionQuartetAsWideString(); + + /* + Returns: + Empty string or the git hash of the revison of the source code used to build this application. + The git hash is a hexadecimal number represented in UTF-8 string. + Remarks: + Developer builds return "". + Build system builds return the git revsion hash. + */ + static const char* SourceGitRevisionHash(); + + /* + Returns: + Empty string or the name of the git branch containing the source code used to build this application. + Remarks: + Developer builds return "". + Build system builds return the git branch name or "". + */ + static const char* SourceGitBranchName(); + + /* + Returns: + A string that identifies the McNeel version control system source code to build this application. + Remarks: + Developer builds return "". + Build system builds return the git @ or "". + */ + static const char* SourceIdentification(); + + //// File open/close for DLL use /////////////////////////////////////////////// + + static + FILE* OpenFile( // like fopen() - needed when OpenNURBS is used as a DLL + const char* filename, + const char* filemode + ); + + static + FILE* OpenFile( // like fopen() - needed when OpenNURBS is used as a DLL + const wchar_t* filename, + const wchar_t* filemode + ); + + static + int CloseFile( // like fclose() - needed when OpenNURBS is used as a DLL + FILE* // pointer returned by OpenFile() + ); + + static + int CloseAllFiles(); // like _fcloseall() - needed when OpenNURBS is used as a DLL + + /* + Description: + Uses the flavor of fstat that is appropriate for the platform. + Parameters: + filename - [in] + fp - [in] + filesize - [out] (can be nullptr if you do not want filesize) + create_time - [out] (can be nullptr if you do not want last create time) + lastmodify_time - [out] (can be nullptr if you do not want last modification time) + Returns: + True if file exists, can be opened for read, and fstat worked. + */ + static + bool GetFileStats( const wchar_t* filename, + size_t* filesize, + time_t* create_time, + time_t* lastmodify_time + ); + + static + bool GetFileStats( FILE* fp, + size_t* filesize, + time_t* create_time, + time_t* lastmodify_time + ); + + /* + Returns true if pathname is a directory. + */ + static bool IsDirectory( const wchar_t* pathname ); + static bool IsDirectory( const char* utf8pathname ); + + /* + Returns + If the file is an opennurbs file, the version of the file + is returned (2,3,4,50,...). + If the file is not an opennurbs file, 0 is returned. + */ + static int IsOpenNURBSFile( const wchar_t* pathname ); + static int IsOpenNURBSFile( const char* utf8pathname ); + static int IsOpenNURBSFile( FILE* fp ); + +#pragma region RH_C_SHARED_ENUM [ON::RuntimeEnvironment] [Rhino.RuntimeEnvironment] [byte] + ///////////////////////////////////////////////////////////////// + /// + /// ON::RuntimeEnvironment identifies a runtime environment (operating system). + /// This value is saved in binary archives so appropriate adjustments + /// to resources provided by runtime environments, like fonts, can be made + /// when an archive created in one runtime environment is used in another. + /// + enum class RuntimeEnvironment : unsigned char + { + /// + /// ON::RuntimeEnvironment::Unset indicates no runtime is set. + /// + Unset = 0, + + /// + /// ON::RuntimeEnvironment::None indicates no runtime. + /// This is a different condition from ON::Runtime::Unset. + /// + None = 1, + + /// + /// ON::RuntimeEnvironment::Windows indicates some version of Microsoft Windows. + /// + Windows = 2, + + /// + /// ON::RuntimeEnvironment::Apple indicates some version of Apple OS X or iOS. + /// + Apple = 3, + + /// + /// ON::RuntimeEnvironment::Android indicates some version of Google Android. + /// + Android = 4, + + /// + /// ON::RuntimeEnvironment::Linux indicates some version of Linux. + /// + Linux = 5 + }; +#pragma endregion + + static ON::RuntimeEnvironment RuntimeEnvironmentFromUnsigned( + unsigned int runtime_environment_as_unsigned + ); + + /* + Returns: + Current runtime environment. + */ + static ON::RuntimeEnvironment CurrentRuntimeEnvironment(); + + +#pragma region RH_C_SHARED_ENUM [ON::ReadFileResult] [Rhino.ReadFileResult] [byte] + /// + /// ON::ReadFileResult reports what happened when a file read was attempted. + /// + enum class ReadFileResult : unsigned char + { + /// + /// No result is available. + /// + Unset = 0, + + /// + /// Read completed with no errors. + /// + Completed = 1, + + /// + /// Read completed with non fatal errors. + /// + CompletedWithErrors = 2, + + /// + /// Read failed. + /// + Failed = 3 + }; +#pragma endregion + + static ON::ReadFileResult ReadFileResultFromUnsigned( + unsigned int read_file_result_as_unsigned + ); + + /* + Returns: + True if the value of read_file_result is one indicating partial to complete success. + False if read_file_result is ON::ReadFileResult::Unset or ON::ReadFileResult::Failed. + */ + static bool ReadFileCompleted( + ON::ReadFileResult read_file_result + ); + + /* + Returns: + True if the value of read_file_result is one indicating total failure. + False if read_file_result is ON::ReadFileResult::Unset or a value indicating partial to complete success. + */ + static bool ReadFileFailed( + ON::ReadFileResult read_file_result + ); + + + // Defines the current working space. + enum active_space : unsigned char + { + no_space = 0, + model_space = 1, // 3d modeling or "world" space + page_space = 2 // page/layout/paper/printing space + }; + + static active_space ActiveSpace(int); // convert integer to active_space enum + +#pragma region RH_C_SHARED_ENUM [ON::LengthUnitSystem] [Rhino.UnitSystem] [byte] + // unit_system /////////////////////////////////////////////////////////////// + /// + /// ON::LengthUnitSystem identifies a length unit system + /// United States customary length units references: + /// http://www.nist.gov/pml/wmd/metric/upload/frn-59-5442-1959.pdf + /// http://en.wikipedia.org/wiki/United_States_customary_units + /// http://en.wikipedia.org/wiki/International_yard_and_pound + /// + enum class LengthUnitSystem : unsigned char + { + /// + /// ON::LengthUnitSystem::None indicates no length unit system. The scale factor + /// when converting between a specified unit system and None is always 1.0. + /// ON::LengthUnitSystem::None is used as a unit system for models and + /// instance defitions that should be imported or referenced with no + /// scaling applied. + /// + None = 0, + + /// + /// 1 angstroms = 1.0e-10 meters + /// + Angstroms = 12, + + // SI (metric) units + + /// + /// 1 nanometer = 1.0e-9 meters + /// + Nanometers = 13, + + /// + /// 1 micron = 1.0e-6 meters + /// + Microns = 1, + + /// + /// 1 millimeter = 1.0e-3 meters + /// + Millimeters = 2, + + /// + /// 1 centimeter = 1.0e-2 meters + /// + Centimeters = 3, + + /// + /// 1 decimeter = 1.0e-1 meters + /// + Decimeters = 14, + + /// + /// SI meter length unit + /// + Meters = 4, + + /// + /// 1 dekameter = 1.0e+1 meters + /// + Dekameters = 15, // 1.0e+1 meters + + /// + /// 1 hectometer = 1.0e+2 meters + /// + Hectometers = 16, + + /// + /// 1 kilometer = 1.0e+3 meters + /// + Kilometers = 5, + + /// + /// 1 megameter = 1.0e+6 meters + /// + Megameters = 17, + + /// + /// 1 gigameter = 1.0e+9 meters + /// + Gigameters = 18, + + /// + /// 1 microinches = 2.54e-8 meters = 1.0e-6 inches + /// + Microinches = 6, + + /// + /// 1 mil = 2.54e-5 meters = 0.001 inches + /// + Mils = 7, + + /// + /// 1 inch = 0.0254 meters = 1/12 foot + /// + Inches = 8, + + /// + /// 1 foot = 0.3048 meters (12 inches) + /// + Feet = 9, + + /// + /// 1 foot = 0.3048 meters = 12 inches + /// + Yards = 19, + + /// + /// 1 US statute mile = 1609.344 meters = 5280 feet + /// + Miles = 10, + + /// + /// 1 printer point = 1/72 inch + /// + PrinterPoints = 20, + + /// + /// 1 printer pica = 1/6 inch + /// + PrinterPicas = 21, + + // terrestrial distances + + /// + /// 1 nautical mile = 1852 meters + /// Approximately 1 minute of arc on a terrestrial great circle. + /// Reference: http://en.wikipedia.org/wiki/Nautical_mile + /// + NauticalMiles = 22, + + // astronomical distances + + /// + /// 1 astronomical unit = 1.4959787e+11 meters + /// An astronomical unit (au) is the mean distance from the + /// center of the earth to the center of the sun. + /// References: + /// http://en.wikipedia.org/wiki/Astronomical_unit (1.4959787e+11 meters) + /// http://units.nist.gov/Pubs/SP811/appenB9.htm (1.495979e+11 meters) + /// + AstronomicalUnits = 23, + + /// + /// 1 light year = 9.4607304725808e+15 meters + /// A light year is the distance light travels in one Julian year. + /// The speed of light is exactly 299792458 meters/second. + /// A Julian year is exactly 365.25 * 86400 seconds and is + /// approximately the time it takes for one earth orbit. + /// References: + /// http://en.wikipedia.org/wiki/Light_year (9.4607304725808e+15 meters) + /// http://units.nist.gov/Pubs/SP811/appenB9.htm (9.46073e+15 meters) + /// + LightYears = 24, + + /// + /// 1 parsec = 3.08567758e+16 meters + /// References: + /// http://en.wikipedia.org/wiki/Parsec (3.08567758e+16 meters) + /// http://units.nist.gov/Pubs/SP811/appenB9.htm (3.085678e+16) + /// + Parsecs = 25, + + /// + /// The name of a custom unit and the conversion to meters + /// are saved in the ON_UnitSystem class. + /// + CustomUnits = 11, + + /// + /// The ON::LengthUnitSystem::Unset is used to indicate no unit system is set. + /// This is a differnt condition from ON::LengthUnitSystem::None. + /// + Unset = 255 + }; +#pragma endregion + + static ON::LengthUnitSystem LengthUnitSystemFromUnsigned( + unsigned int length_unit_system_as_unsigned + ); + + /* + Parameters: + model_serial_number - [in] + One good way to get this value is from ON_ModelComponent::ModelSerialNumber(). + ON_DimStyle, ON_Layer, ... are all derived from ON_ModelComponent. + Returns: + The length unit system used by the model + */ + static ON::LengthUnitSystem ModelLengthUnitSystem( + ON__UINT_PTR model_serial_number + ); + + + static void RegisterModelLengthUnitSystemCallback( + ON::LengthUnitSystem (*func_ModelLengthUnitSystemCallback)(ON__UINT_PTR) + ); + +public: + + /* + Returns + True if the length unit is one of + LengthUnitSystem::Angstroms + LengthUnitSystem::Nanometers + LengthUnitSystem::Microns + LengthUnitSystem::Millimeters + LengthUnitSystem::Centimeters + LengthUnitSystem::Decimeters + LengthUnitSystem::Meters + LengthUnitSystem::Dekameters + LengthUnitSystem::Hectometers + LengthUnitSystem::Kilometers + LengthUnitSystem::Megameters + LengthUnitSystem::Gigameters + LengthUnitSystem::NauticalMiles + LengthUnitSystem::AstronomicalUnits + LengthUnitSystem::LightYears + LengthUnitSystem::Parsecs + */ + static bool IsMetricLengthUnit( + ON::LengthUnitSystem length_unit_system + ); + + /* + Returns + True if the length unit is one of + LengthUnitSystem::Microinches + LengthUnitSystem::Mils + LengthUnitSystem::Inches + LengthUnitSystem::Feet + LengthUnitSystem::Yards + LengthUnitSystem::Miles + LengthUnitSystem::PrinterPoints + LengthUnitSystem::PrinterPicas + */ + static bool IsUnitedStatesCustomaryLengthUnit( + ON::LengthUnitSystem length_unit_system + ); + + /* + Returns + True if the length unit is one of + LengthUnitSystem::Millimeters + LengthUnitSystem::Centimeters + LengthUnitSystem::Decimeters + LengthUnitSystem::Meters + LengthUnitSystem::Dekameters + LengthUnitSystem::Hectometers + LengthUnitSystem::Kilometers + LengthUnitSystem::Inches + LengthUnitSystem::Feet + LengthUnitSystem::Yards + LengthUnitSystem::Miles + LengthUnitSystem::NauticalMiles + */ + static bool IsTerrestrialLengthUnit( + ON::LengthUnitSystem length_unit_system + ); + + /* + Returns + True if the length unit is one of + LengthUnitSystem::AstronomicalUnits + LengthUnitSystem::LightYears + LengthUnitSystem::Parsecs + */ + static bool IsExtraTerrestrialLengthUnit( + ON::LengthUnitSystem length_unit_system + ); + + /* + Returns + True if the length unit is one of + LengthUnitSystem::Angstroms + LengthUnitSystem::Nanometers + LengthUnitSystem::Microns + LengthUnitSystem::Microinches + LengthUnitSystem::Mils + */ + static bool IsMicroscopicLengthUnit( + ON::LengthUnitSystem length_unit_system + ); + + /* + Returns + True if the length unit is one of + LengthUnitSystem::PrinterPoints + LengthUnitSystem::PrinterPicas + */ + static bool IsUnitedStatesPrinterLengthUnit( + ON::LengthUnitSystem length_unit_system + ); + + /* + Description: + Scale factor for changing unit "standard" systems. + Parameters: + us_from - [in] + us_to - [in] + For example: + + 100.0 = ON::UnitScale( ON::LengthUnitSystem::Meters, ON::LengthUnitSystem::Centimeters ) + 2.54 = ON::UnitScale( ON::LengthUnitSystem::Inches, ON::LengthUnitSystem::Centimeters ) + 12.0 = ON::UnitScale( ON::LengthUnitSystem::Feet, ON::LengthUnitSystem::Inches ) + + Remarks: + If you are using custom unit systems, use the version that takes ON_UnitSystem + or ON_3dmUnitsAndTolerances parameters. + If either parameter is ON::LengthUnitSystem::Unset, then ON_DBL_QNAN is returned. + If either parameter is ON::LengthUnitSystem::None, then 1.0 is returned. + If either parameter is ON::LengthUnitSystem::CustomUnits, then 1.0 is returned. + */ + static double UnitScale( + ON::LengthUnitSystem us_from, + ON::LengthUnitSystem us_to + ); + static double UnitScale( + const class ON_UnitSystem& us_from, + const class ON_UnitSystem& us_to + ); + static double UnitScale( + ON::LengthUnitSystem us_from, + const class ON_UnitSystem& us_to + ); + static double UnitScale( + const class ON_UnitSystem& us_from, + ON::LengthUnitSystem us_to + ); + static double UnitScale( + const class ON_3dmUnitsAndTolerances& us_from, + const class ON_3dmUnitsAndTolerances& us_to + ); + + +#pragma region RH_C_SHARED_ENUM [ON::AngleUnitSystem] [Rhino.AngleUnitSystem] [byte] + /// + /// ON::AngleUnitSystem identifies an angle unit system + /// + enum class AngleUnitSystem : unsigned char + { + /// + /// ON::AngleUnitSystem::None indicates no angle unit system + /// is specified and model angle unit system should be used. + /// + None = 0, + + /// + /// 1 turn = 2pi radians. + /// + Turns = 1, + + /// + /// 1 turn = 2pi radians. + /// + Radians = 2, // 2pi radians = 1 turn + + /// + /// 360 arc degrees = 1 turn = 2pi radians + /// + Degrees = 3, + + /// + /// 60 arc minutes = 1 arc degree + /// + Minutes = 4, + + /// + /// 60 arc seconds = 1 arc minute + /// + Seconds = 5, + + /// + /// 400 gradians = 2pi radians. + /// + Gradians = 6, + + /// + /// The ON::AngleUnitSystem::Unset is used to indicates no angle unit system + /// has been specified in user interface code. + /// + Unset = 255 + }; +#pragma endregion + + static ON::AngleUnitSystem AngleUnitSystemFromUnsigned( + unsigned int angle_unit_system_as_unsigned + ); + + static double AngleUnitScale( + ON::AngleUnitSystem us_from, + ON::AngleUnitSystem us_to + ); + + + /// + /// ON::EarthCoordinateSystem identifies the standard used to define Earth latitude, longitude, and elevation coordinates. + /// + enum class EarthCoordinateSystem : unsigned char + { + /// + /// ON::EarthCoordinateSystem::Unset + /// + Unset = 0, + + /// + /// ON::EarthCoordinateSystem::GroundLevel Not well defined, but latitude and longitude will be good enough for architecture sun studies. + /// + GroundLevel = 1, /// Ground level - coordinates vary with time and location + + /// + /// ON::EarthCoordinateSystem::MeanSeaLevel Not well defined, but latitude and longitude will be good enough for architecture sun studies. + /// + MeanSeaLevel = 2, + + /// + /// ON::EarthCoordinateSystem::CenterOfEarth Not well defined. The Earth's center of mass and center of volume are at different locations. + /// + CenterOfEarth = 3, + + /// + /// ON::EarthCoordinateSystem::WGS1984 World Geodetic System 1984 standard. (Current GPS standard.) + /// + WGS1984 = 5, + + /// + /// ON::EarthCoordinateSystem::EGM2008 Earth Gravitational Model 2008 standard. + /// + EGM2008 = 6 + }; + + static ON::EarthCoordinateSystem EarthCoordinateSystemFromUnsigned( + unsigned int earth_coordinte_system_as_unsigned + ); + + /// + /// ON::ComponentNameConflictResolution identifies a method to use + /// when components are being added to model, the component name must + /// be unique, and the name of the new is already in use in the context. + /// The function ON_ModelComponent::UniqueNameRequired(ON_ModelComponent::Type) + /// can be used to determine if a component requires a unique name. + /// + enum class ComponentNameConflictResolution : unsigned char + { + /// + /// A method to resolve name conflicts has not been specified. + /// + Unset = 0, + + /// + /// Interactivly ask the user to choose one of the following methods + /// to resolve component name conflicts. + /// + QueryMethod = 1, + + /// + /// Use the existing component, discard the new component. + /// All references to the discarded component are changed to reference the + /// the surviving component. + /// + UseExistingComponent = 2, + + /// + /// Replace the existing component with the new component. + /// All references to the discarded component are changed reference the + /// the surviving component. + /// + ReplaceExistingComponent = 3, + + /// + /// Keep both components. + /// Resolve the name conflict by automatically assigning a name new component. + /// This is typically done by appending an integer to the original name. + /// + KeepBothComponentsAutomaticRename = 4, + + /// + /// Keep both components. + /// Resolve the name conflict by interactivly asking for an unused name + /// to assign to the new component. + /// + KeepBothComponentsQueryRename = 5, + + /// + /// No name conflict was detected and no special action is required. + /// This can occur when the names in question are unique or unique names are not required. + /// + NoConflict = 0xFF + }; + + static ON::ComponentNameConflictResolution ComponentNameConflictResolutionFromUnsigned( + unsigned int component_name_conflict_resolution_as_unsigned + ); + + //// distance_display_mode /////////////////////////////////// + + + // Obsolete - use ON_DimStyle::DimensionLengthDisplay + enum class OBSOLETE_DistanceDisplayMode : unsigned char + { + // Obsolete - Obsolete - use ON_DimStyle::DimensionLengthDisplay::ModelUnits + Decimal = 0, + + // Obsolete - Obsolete - use ON_DimStyle::DimensionLengthDisplay::InchesFractional + Fractional = 1, + + // Obsolete - Obsolete - use ON_DimStyle::DimensionLengthDisplay::FeetAndInches + FeetInches = 2 + }; + + static ON::OBSOLETE_DistanceDisplayMode DistanceDisplayModeFromUnsigned( + unsigned int distance_display_mode_as_unsigned + ); + + + //// point_style /////////////////////////////////////////////////////////////// + enum point_style + { + unknown_point_style = 0, + not_rational = 1, + homogeneous_rational = 2, + euclidean_rational = 3, + intrinsic_point_style = 4, // point format used in definition + point_style_count = 5 + }; + + static point_style PointStyle(int); // convert integer to point_style enum + + //// knot_style /////////////////////////////////////////////////////////////// + enum knot_style // if a knot vector meets the conditions of two styles, + { // then the style with the lowest value is used + unknown_knot_style = 0, // unknown knot style + uniform_knots = 1, // uniform knots (ends not clamped) + quasi_uniform_knots = 2, // uniform knots (clamped ends, degree >= 2) + piecewise_bezier_knots = 3, // all internal knots have full multiplicity + clamped_end_knots = 4, // clamped end knots (with at least 1 interior non-uniform knot) + non_uniform_knots = 5, // known to be none of the above + knot_style_count = 6 + }; + + static knot_style KnotStyle(int); // convert integer to knot_style enum + + //// continuity //////////////////////////////////////////////////////////////// + enum class continuity : unsigned int + { + unknown_continuity = 0, + + // These test for parametric continuity. In particular, + // all types of ON_Curves are considered infinitely + // continuous at the start/end of the evaluation domain. + C0_continuous = 1, // continuous function + C1_continuous = 2, // continuous first derivative + C2_continuous = 3, // continuous first and second derivative + G1_continuous = 4, // continuous unit tangent + G2_continuous = 5, // continuous unit tangent and curvature + + // 20 March 2003 Dale Lear added these. + // + // Continuity tests using the following enum values + // are identical to tests using the preceding enum values + // on the INTERIOR of a curve's domain. At the END of + // a curve a "locus" test is performed in place of a + // parametric test. In particular, at the END of a domain, + // all open curves are locus discontinuous. At the END of + // a domain, all closed curves are at least C0_locus_continuous. + // By convention all ON_Curves are considered + // locus continuous at the START of the evaluation domain. + // This convention is not strictly correct, but is was + // adopted to make iterative kink finding tools easier to + // use and so that locus discontinuities are reported once + // at the end parameter of a curve rather than twice. + C0_locus_continuous = 6, // locus continuous function + C1_locus_continuous = 7, // locus continuous first derivative + C2_locus_continuous = 8, // locus continuous first and second derivative + G1_locus_continuous = 9, // locus continuous unit tangent + G2_locus_continuous = 10, // locus continuous unit tangent and curvature + + Cinfinity_continuous = 11, // analytic discontinuity + Gsmooth_continuous = 12 // aesthetic discontinuity + }; + + /* + Description: + Convert int to ON::continuity enum value + */ + static continuity Continuity(int); + + /* + Description: + Convert int to ON::continuity enum value and + convert the locus flavored values to the parametric + flavored values. + */ + static continuity ParametricContinuity(int); + + /* + Description: + Convert int to ON::continuity enum value and + convert the higher order flavored values to + the corresponding C1 or G1 values needed to + test piecewise linear curves. + */ + static continuity PolylineContinuity(int); + + //// curve_style /////////////////////////////////////////////////////////////// + enum curve_style + { + unknown_curve_style = 0, + line = 1, + circle = 2, + ellipse = 3, // with distinct foci (not a circle) + parabola = 4, + hyperbola = 5, + planar_polyline = 6, // not a line segment + polyline = 7, // non-planar polyline + planar_freeform_curve = 8, // planar but none of the above + freeform_curve = 9, // known to be none of the above + curve_style_count = 10 + }; + + static curve_style CurveStyle(int); // convert integer to curve_style enum + + //// surface_style /////////////////////////////////////////////////////////////// + enum surface_style + { + unknown_surface_style = 0, + plane = 1, + circular_cylinder = 2, // portion of right circular cylinder + elliptical_cylinder = 3, // portion of right elliptical cylinder + circular_cone = 4, // portion of right circular cone + elliptical_cone = 5, // portion of right elliptical cone + sphere = 6, // portion of sphere + torus = 7, // portion of torus + surface_of_revolution = 8, // portion of surface of revolution that is none of the above + ruled_surface = 9, // portion of a ruled surface this is none of the above + freeform_surface = 10, // known to be none of the above + surface_style_count = 11 + }; + + static surface_style SurfaceStyle(int); // convert integer to surface_style enum + + //// sort_algorithm /////////////////////////////////////////////////////////////// + enum class sort_algorithm : unsigned int + { + heap_sort = 0, + quick_sort = 1 + }; + + static sort_algorithm SortAlgorithm(int); // convert integer to sort_method enum + + //// endian-ness /////////////////////////////////////////////////////////////// + enum class endian : unsigned int + { + little_endian = 0, // least significant byte first or reverse byte order - Intel x86, ... + big_endian = 1 // most significant byte first - Motorola, Sparc, MIPS, ... + }; + + static endian Endian(int); // convert integer to endian enum + static endian Endian(); // returns endian-ness of current CPU + + //// archive modes ////////////////////////////////////////////////////////////// + enum class archive_mode : unsigned int + { + unset_archive_mode = 0, + read = 1, // all read modes have bit 0x0001 set + write = 2, // all write modes have bit 0x0002 set + readwrite = 3, + read3dm = 5, + write3dm = 6 + }; + static archive_mode ArchiveMode(int); // convert integer to endian enum + + + //// view projections /////////////////////////////////////////////////////////// + + // The x/y/z_2pt_perspective_view projections are ordinary perspective + // projection. Using these values insures the ON_Viewport member + // fuctions properly constrain the camera up and camera direction vectors + // to preserve the specified perspective vantage. + enum view_projection : unsigned int + { + unknown_view = 0, + parallel_view = 1, + perspective_view = 2 + }; + + /* + Description: + Converts integer into ON::view_projection enum value. + Parameters: + i - [in] + Returns: + ON::view_projection enum with same value as i. + If i is not an ON::view_projection enum value, + then ON::unknow_view is returned. + */ + static view_projection ViewProjection(int i); + + /* + Parameters: + projection - [in] + Returns: + True if projection is ON::perspective_view. + */ + static bool IsPerspectiveProjection( ON::view_projection projection ); + + + /* + Parameters: + projection - [in] + Returns: + True if projection is ON::parallel_view. + */ + static bool IsParallelProjection( ON::view_projection projection ); + + //// view coordinates /////////////////////////////////////////////////////////// + + enum coordinate_system + { + world_cs = 0, + camera_cs = 1, + clip_cs = 2, + screen_cs = 3 + }; + + static coordinate_system CoordinateSystem(int); // convert integer to coordinate_system enum + + //// exception types /////////////////////////////////////////////////////////// + enum exception_type + { + unknown_exception = 0, + out_of_memory, + corrupt_object, // invalid object encountered - continuing would crash or + // result in corrupt object being saved in archive. + unable_to_write_archive, // write operation failed - out of file space/read only mode/...? + unable_to_read_archive, // read operation failed - truncated archive/locked file/... ? + unable_to_seek_archive, // seek operation failed - locked file/size out of bounds/... ? + unexpected_end_of_archive, // truncated archive + unexpected_value_in_archive // corrupt archive? + }; + static exception_type ExceptionType(int); // convert integer to exception_type enum + + //// layer mode /////////////////////////////////////////////////////////// + // OBSOLETE + enum layer_mode + { + normal_layer = 0, // visible, objects on layer can be selected and changed + hidden_layer = 1, // not visible, objects on layer cannot be selected or changed + locked_layer = 2, // visible, objects on layer cannot be selected or changed + layer_mode_count = 3 + }; + static layer_mode LayerMode(int); // convert integer to layer_mode enum + + //// object mode /////////////////////////////////////////////////////////// + enum object_mode + { + normal_object = 0, // object mode comes from layer + hidden_object = 1, // not visible, object cannot be selected or changed + locked_object = 2, // visible, object cannot be selected or changed + idef_object = 3, // object is part of an ON_InstanceDefinition. The + // ON_InstanceDefinition m_object_uuid[] array will + // contain this object attribute's uuid. + object_mode_count = 4 + }; + static object_mode ObjectMode(int); // convert integer to object_mode enum + + //// object display color ///////////////////////////////////////////////////////// + enum object_color_source + { + color_from_layer = 0, // use color assigned to layer + color_from_object = 1, // use color assigned to object + color_from_material = 2, // use diffuse render material color + color_from_parent = 3 // for objects with parents (like objects in instance references, use parent linetype) + // if no parent, treat as color_from_layer + }; + static object_color_source ObjectColorSource(int); // convert integer to object_color_source enum + + //// object plot color ///////////////////////////////////////////////////////// + enum plot_color_source + { + plot_color_from_layer = 0, // use plot color assigned to layer + plot_color_from_object = 1, // use plot color assigned to object + plot_color_from_display = 2, // use display color + plot_color_from_parent = 3 // for objects with parents (like objects in instance references, use parent plot color) + // if no parent, treat as plot_color_from_layer + }; + static plot_color_source PlotColorSource(int); // convert integer to plot_color_source enum + + //// object plot weight ///////////////////////////////////////////////////////// + enum plot_weight_source + { + plot_weight_from_layer = 0, // use plot color assigned to layer + plot_weight_from_object = 1, // use plot color assigned to object + plot_weight_from_parent = 3 // for objects with parents (like objects in instance references, use parent plot color) + // if no parent, treat as plot_color_from_layer + }; + static plot_weight_source PlotWeightSource(int); // convert integer to plot_color_source enum + + //// object linetype ///////////////////////////////////////////////////////// + enum object_linetype_source + { + linetype_from_layer = 0, // use line style assigned to layer + linetype_from_object = 1, // use line style assigned to object + linetype_from_parent = 3 // for objects with parents (like objects in instance references, use parent linetype) + // if not parent, treat as linetype_from_layer. + }; + static object_linetype_source ObjectLinetypeSource(int); // convert integer to object_linetype_source enum + + //// object material ///////////////////////////////////////////////////////// + enum object_material_source + { + material_from_layer = 0, // use material assigned to layer + material_from_object = 1, // use material assigned to object + material_from_parent = 3 // for objects with parents, like + // definition geometry in instance + // references and faces in polysurfaces, + // this value indicates the material + // definition should come from the parent. + // If the object does not have an + // obvious "parent", then treat + // it the same as material_from_layer. + }; + static object_material_source ObjectMaterialSource(int); // convert integer to object_color_source enum + + //// light style ///////////////////////////////////////////////////////////// + enum light_style + { + unknown_light_style = 0, + //view_directional_light = 1, // light location and direction in clip coordinates + //view_point_light = 2, + //view_spot_light = 3, + camera_directional_light = 4, // light location and direction in camera coordinates + camera_point_light = 5, // +x points to right, +y points up, +z points towards camera + camera_spot_light = 6, + world_directional_light = 7, // light location and direction in world coordinates + world_point_light = 8, + world_spot_light = 9, + ambient_light = 10, // pure ambient light + world_linear_light = 11, + world_rectangular_light = 12, + light_style_count = 13 + }; + static light_style LightStyle(int); // convert integer to light_style enum + + //// curvature style ///////////////////////////////////////////////////////// + enum curvature_style + { + unknown_curvature_style = 0, + gaussian_curvature = 1, + mean_curvature = 2, // unsigned mean curvature + min_curvature = 3, // minimum unsigned radius of curvature + max_curvature = 4, // maximum unsigned radius of curvature + curvature_style_count = 5 + }; + static curvature_style CurvatureStyle(int); // convert integer to curvature_style enum + + ///////////////////////////////////////////////////////////////// + // + // Legacy V3 display mode enum values. + // Beginning with V4, opennurbs and Rhino us an ON_UUID to identify + // display modes. The standard display mode ids are static + // values in ON_StandardDisplayModeId. + enum v3_display_mode + { + v3_default_display = 0, // default display + v3_wireframe_display = 1, // wireframe display + v3_shaded_display = 2, // shaded display + v3_renderpreview_display = 3 // render preview display + }; + static ON::v3_display_mode V3DisplayMode(int); // convert integer to legacy v3_display_mode enum + + enum view_type + { + model_view_type = 0, // standard model space 3d view + page_view_type = 1, // a.k.a "paper space", "plot view", etc. + // A page view must be orthographic, + // the camera frame x,y,z direction must be + // world x,y,z (which means the camera direction + // is always (0,0,-1)). + nested_view_type = 2, // This view is a "model" view that is nested + // in another view. The nesting and parent + // information is saved in ON_3dmView. + }; + static view_type ViewType(int); // convert integer to display_mode enum + + + //// texture mapping mode /////////////////////////////////////////////////// + // + // OBSOLETE + enum texture_mode + { + no_texture = 0, // texture disabled + modulate_texture = 1, // modulate with material diffuse color + decal_texture = 2 // decal + }; + // OBSOLETE + static texture_mode TextureMode(int); // convert integer to texture_mode enum + // OBSOLETE + // + ///////////////////////////////////////////////////////////////////////////// + + + /// + /// Rich text style + /// + /// The way rich text specifies fonts and other information depends on what + /// created the rich text. The interpretation of the rich text "specification" + /// varies widely and depends on the application, platform, and operating system. + /// + enum class RichTextStyle : unsigned char + { + /// Unset" + Unset = 0, + + /// Rich text for use with the Windows 10 SDK. The font table uses Windows LOGFONT names. + Windows10SDK = 1, + + /// Rich text for use with the Apple OS X SDK. The font table uses Postscript names. + AppleOSXSDK = 2, + }; + static ON::RichTextStyle RichTextStyleFromUnsigned(unsigned int u); + + /* + Returns: + ON::RichTextStyle::Windows10SDK on Windows and ON::RichTextStyle::AppleOSXSDK on OS X. + */ + static ON::RichTextStyle RichTextStyleFromCurrentPlatform(); + + + //// object_type /////////////////////////////////////////////////// + enum object_type + { + // Use with ON_Object::ObjectType() in situations where + // using a switch() is better than a long string of if else if ... + // if ( ON_Curve::Cast() ) ... else if ( ON_Surface::Cast() ) ... + // ... + unknown_object_type = 0, + + point_object = 1, // some type of ON_Point + pointset_object = 2, // some type of ON_PointCloud, ON_PointGrid, ... + curve_object = 4, // some type of ON_Curve like ON_LineCurve, ON_NurbsCurve, etc. + surface_object = 8, // some type of ON_Surface like ON_PlaneSurface, ON_NurbsSurface, etc. + brep_object = 0x10, // some type of ON_Brep + mesh_object = 0x20, // some type of ON_Mesh + layer_object = 0x40, // some type of ON_Layer + material_object = 0x80, // some type of ON_Material + light_object = 0x100, // some type of ON_Light + annotation_object = 0x200, // some type of ON_Annotation + userdata_object = 0x400, // some type of ON_UserData + instance_definition = 0x800, // some type of ON_InstanceDefinition + instance_reference = 0x1000, // some type of ON_InstanceRef + text_dot = 0x2000, // some type of ON_TextDot + grip_object = 0x4000, // selection filter value - not a real object type + detail_object = 0x8000, // some type of ON_DetailView + hatch_object = 0x10000, // some type of ON_Hatch + morph_control_object = 0x20000, // some type of ON_MorphControl + subd_object = 0x40000, // some type of ON_SubD, ON_SubDRef, ON_SubDComponentRef, ON_SubD.... + loop_object = 0x80000, // some type of ON_BrepLoop + brepvertex_filter = 0x100000, // selection filter value - not a real object type (ON_BrepVertex) + polysrf_filter = 0x200000, // selection filter value - not a real object type + edge_filter = 0x400000, // selection filter value - not a real object type (ON_BrepEdge with associated ON_BrepTrim) + polyedge_filter = 0x800000, // selection filter value - not a real object type + + + // NOTE WELL: + // The "mesh" vertex/edge/face filters and "meshcomponent_reference" + // are used to identify ON_Mesh and ON_SubD components. + // By the time subd_object was added, there were not enough unused bits + // for separate subd component filters. + meshvertex_filter = 0x01000000, // selection filter value - not a real object type (ON_MeshTopologyVertex, ON_SubDVertex) + meshedge_filter = 0x02000000, // selection filter value - not a real object type (ON_MeshTopologyEdge, ON_SubDEdge) + meshface_filter = 0x04000000, // selection filter for ON_Mesh triangle, quad, ngon, or ON_SubDFace - not a real object type + meshcomponent_reference = 0x07000000, // an ON_MeshComponentRef or ON_SubDComponentRef) + + cage_object = 0x08000000, // some type of ON_NurbsCage + phantom_object = 0x10000000, + clipplane_object = 0x20000000, + extrusion_object = 0x40000000, // some type of ON_Extrusion + + any_object = 0xFFFFFFFF + + // Please discuss any changes with Dale Lear + }; + + static object_type ObjectType(int); // convert integer to object_type enum + + //// bitmap_type /////////////////////////////////////////////////// + enum bitmap_type + { + unknown_bitmap_type = 0, + windows_bitmap = 1, // BITMAPINFO style + opengl_bitmap = 2, // unpacked OpenGL RGB or RGBA + png_bitmap = 3 + }; + static bitmap_type BitmapType(int); // convert integer to bitmap_type enum + + enum object_decoration + { + no_object_decoration = 0, + start_arrowhead = 0x08, // arrow head at start + end_arrowhead = 0x10, // arrow head at end + both_arrowhead = 0x18 // arrow heads at start and end + }; + static object_decoration ObjectDecoration(int); // convert integer to line_pattern enum + + enum mesh_type + { + default_mesh = 0, + render_mesh = 1, + analysis_mesh = 2, + preview_mesh = 3, + any_mesh = 4 + }; + static mesh_type MeshType(int); // convert integer to mesh_type enum + + + // Types of object snapping. + // In situations where more than one type of snap applies, + // snaps with higher value take precedence. + // enum values must be a power of 2. + // ON_ObjRef saves these values in files. Do not change + // the values. The reason for the gaps between the enum + // values is to leave room for future snaps with prededence + // falling between existing snaps + enum osnap_mode + { + os_none = 0, + os_near = 2, + os_focus = 8, + os_center = 0x20, + os_vertex = 0x40, + os_knot = 0x80, + os_quadrant = 0x200, + os_midpoint = 0x800, + os_intersection = 0x2000, + os_end = 0x20000, + os_perpendicular = 0x80000, + os_tangent = 0x200000, + os_point = 0x08000000, + os_all_snaps = 0xFFFFFFFu + }; + static osnap_mode OSnapMode(int); // convert integer to osnap_mode enum + + + //// Types of Curves /////////////////////////////////////////////////////////// + enum eCurveType + { + ctCurve, // nothing + ctArc, + ctCircle, + ctLine, + ctNurbs, + ctOnsurface, + ctProxy, + ctPolycurve, + ctPolyline, + }; + + + //// surface_loft_end_condition ////////////////////////////////////////////// + // + // End condition paramter values for ON_Curve::CreateCubicLoft() and + // ON_Surface::CreateCubicLoft(). + enum cubic_loft_end_condition + { + cubic_loft_ec_quadratic = 0, + cubic_loft_ec_linear = 1, + cubic_loft_ec_cubic = 2, + cubic_loft_ec_natural = 3, + cubic_loft_ec_unit_tangent = 4, + cubic_loft_ec_1st_derivative = 5, + cubic_loft_ec_2nd_derivative = 6, + cubic_loft_ec_free_cv = 7 + }; + + /* + Description: + Convert an integer to cubic_loft_end_condition enum. + Parameters: + i - [in] + Returns: + corresponding cubic_loft_end_condition enum value. + Remarks: + If i does not correspond to a cubic_loft_end_condition + enum value, then cubic_loft_ec_quadratic is returned. + */ + static + cubic_loft_end_condition CubicLoftEndCondition(int i); + + +public: + +#pragma region RH_C_SHARED_ENUM [ON::AnnotationType] [Rhino.Geometry.AnnotationType] [byte] + + /// + /// ON::AnnotationType identifies the type of an annotation object derived from ON_Annotation. + /// + enum class AnnotationType : unsigned char + { + /// + /// Not a valid annotation type. + /// + Unset = 0, + + /// + /// Linear distance between two points with dimension line parallel to the dimensioned points. + /// + Aligned = 1, + + /// + /// Angle bewteen two lines. + /// + Angular = 2, + + /// + /// Arc or circle diameter dimension. + /// + Diameter = 3, + + /// + /// Arc or circle radius dimension. + /// + Radius = 4, + + /// + /// Linear distance between two points with dimension line horizontal, vertical or rotated by a specified amount. + /// + Rotated = 5, + + /// + /// Ordinate dimension. Typically used to document an offset distance between the center of a circle and a reference point. + /// + Ordinate = 6, + + /// + /// Arc length of a curve. + /// + ArcLen = 7, + + /// + /// Center mark dimension. Typically used to document the center of an arc or circle. + /// + CenterMark = 8, + + /// + /// Text. Stand alone text with a wide variety of uses. + /// + Text = 9, + + /// + /// Leader. Text and a curve with an arrow head. + /// + Leader = 10, + + /// + /// Angular3pt. Angle defined by 3 points. + /// + Angular3pt = 11 + }; + +#pragma endregion + + static ON::AnnotationType AnnotationTypeFromUnsigned( + unsigned int annotation_type_as_unsigned + ); + + + +#pragma region RH_C_SHARED_ENUM [ON::TextVerticalAlignment] [Rhino.DocObjects.TextVerticalAlignment] [byte] + /// + /// Vertical location of text attach point relative to text + /// + enum class TextVerticalAlignment : unsigned char + { + /// + /// Attach to top of an "I" on the first line. (Independent of glyphs being displayed.) + /// + Top = 0, + /// + /// Attach to middle of an "I" on the first line. (Independent of glyphs being displayed.) + /// + MiddleOfTop = 1, + /// + /// Attach to baseline of first line. (Independent of glyphs being displayed.) + /// + BottomOfTop = 2, + /// + /// Attach to middle of text vertical advance. (Independent of glyphs being displayed.) + /// + Middle = 3, + /// + /// Attach to middle of an "I" on the last line. (Independent of glyphs being displayed.) + /// + MiddleOfBottom = 4, + /// + /// Attach to the basline of the last line. (Independent of glyphs being displayed.) + /// + Bottom = 5, + /// + /// Attach to the bottom of the boudning box of the visible glyphs. + /// + BottomOfBoundingBox = 6, // TODO - changed to BottomOfBoundingBox + }; +#pragma endregion + + static ON::TextVerticalAlignment TextVerticalAlignmentFromUnsigned( + unsigned int vertical_alignment_as_unsigned + ); + + static ON::TextVerticalAlignment TextVerticalAlignmentFromV5Justification( + unsigned int v5_justification_bits + ); + +#pragma region RH_C_SHARED_ENUM [ON::TextHorizontalAlignment] [Rhino.DocObjects.TextHorizontalAlignment] [byte] + /// + /// Horizontal location of text attach point relative to text + /// + enum class TextHorizontalAlignment : unsigned char + { + /// + /// Attach at left of text lines (Independent of glyphs being displayed.) + /// + Left = 0, + /// + /// Attach point at center of text horizontal advance (not glyph bounding box) + /// + Center = 1, + /// + /// Attach point at right text horizontal advance (not glyph bounding box) + /// + Right = 2, + /// + /// Used for Leaders only + /// Attach point adjusts to Right or Left depending on leader tail direction in view + /// If tail direction is to the Left, alignment is Right + /// If tail direction is to the Right, alignment is Left + /// + Auto = 3, + }; +#pragma endregion + + static ON::TextHorizontalAlignment TextHorizontalAlignmentFromUnsigned( + unsigned int horizontal_alignment_as_unsigned + ); + + static ON::TextHorizontalAlignment TextHorizontalAlignmentFromV5Justification( + unsigned int v5_justification_bits + ); + +#pragma region RH_C_SHARED_ENUM [ON::TextOrientation] [Rhino.DocObjects.TextOrientation] [byte] + /// + /// Method for getting rotation for drawing text + /// + enum class TextOrientation : unsigned char + { + /// + /// Text has fixed rotation on a world coordinate plane + /// + InPlane = 0, + /// + /// Text is drawn on a plane perpendicular to view direction horizontal to the screen + /// + InView = 1, + }; + +#pragma endregion + + static ON::TextOrientation TextOrientationFromUnsigned( + unsigned int orientation_as_unsigned + ); + + + +private: + // ON::Begin() sets m_opennurbs_library_status + // 0 = not initialized + // 1 = in the body of ON::Begin() + // 2 = ON:Begin() finished. + static unsigned int m_opennurbs_library_status; + +private: + // prohibit instantiaion + //ON(); // no implementation + //ON( const ON& ); // no implementation + //~ON(); // no implementation +}; + +/* +Description: + Component indices are used to provide a persistent way + to identify portions of complex objects. + +*/ +class ON_CLASS ON_COMPONENT_INDEX +{ +public: + + // Do not change these values; they are stored in 3dm archives + // and provide a persistent way to indentify components of + // complex objects. + enum TYPE + { + invalid_type = 0, + + brep_vertex = 1, + brep_edge = 2, + brep_face = 3, + brep_trim = 4, + brep_loop = 5, + + mesh_vertex = 11, + meshtop_vertex = 12, + meshtop_edge = 13, + mesh_face = 14, + mesh_ngon = 15, + + idef_part = 21, + + polycurve_segment = 31, + + pointcloud_point = 41, + + group_member = 51, + + + extrusion_bottom_profile = 61, // 3d bottom profile curves + // index identifies profile component + extrusion_top_profile = 62, // 3d top profile curves + // index identifies profile component + extrusion_wall_edge = 63, // 3d wall edge curve + // index/2: identifies profile component + // index%2: 0 = start, 1 = end + extrusion_wall_surface = 64, // side wall surfaces + // index: identifies profile component + extrusion_cap_surface = 65, // bottom and top cap surfaces + // index: 0 = bottom, 1 = top + extrusion_path = 66, // extrusion path (axis line) + // index -1 = entire path, 0 = start point, 1 = endpoint + + ////////////////////////////////////////////////////// + // + // ON_SubD component index + // + // Use ON_SubD.ComponentPtrFromComponentIndex() to convert an ON_COMPONENT_INDEX + // into a component pointer. + // See also + // ON_SubD.VertexFromId() + // ON_SubD.EdgeFromId() + // ON_SubD.FaceFromId() + // + subd_vertex = 71, // m_index = ON_SubDVertex.m_id, use ON_SubD.ComponentPtrFromComponentIndex() + subd_edge = 72, // m_index = ON_SubDEdge.m_id + subd_face = 73, // m_index = ON_SubDFace.m_id + + hatch_loop = 81, // m_index = ON_Hatch::m_loops[] array index + + dim_linear_point = 100, + dim_radial_point = 101, + dim_angular_point = 102, + dim_ordinate_point = 103, + dim_text_point = 104, + dim_centermark_point = 105, + dim_leader_point = 106, + + no_type = 0xFFFFFFFu + }; + + /* + Description: + Safe conversion of integer value to TYPE enum. + Parameters: + i - [in] integer with value equal to one of the TYPE enums. + Returns: + The TYPE enum with the same numeric value + or ON_COMPONENT_INDEX::invalid_type if no corresponding enum + exists. + */ + static + ON_COMPONENT_INDEX::TYPE Type(int i); + + /* + Description: + Compare on m_type (as an int). + */ + static + int CompareType( const ON_COMPONENT_INDEX* lhs, const ON_COMPONENT_INDEX* rhs); + + /* + Description: + Dictionary compare on m_type, m_index as ints. + Returns: + < 0: a < b + = 0: a = b + > 0: a > b + */ + static + int Compare( const ON_COMPONENT_INDEX* a, const ON_COMPONENT_INDEX* b); + + /* + Description: + UnsetComponentIndex.m_type = invalid_type + UnsetComponentIndex.m_index = -1 as int + = ON_UNSET_UINT_INDEX as unsigned int + */ + static const ON_COMPONENT_INDEX UnsetComponentIndex; + + /* + Description: + Default constructor has value ON_COMPONENT_INDEX UnsetComponentIndex. + */ + ON_COMPONENT_INDEX(); + + /* + Description: + Sets m_type = type and m_index = index. + */ + ON_COMPONENT_INDEX(ON_COMPONENT_INDEX::TYPE type,int index); + + bool operator==(const ON_COMPONENT_INDEX& other) const; + bool operator!=(const ON_COMPONENT_INDEX& other) const; + bool operator<(const ON_COMPONENT_INDEX& other) const; + bool operator<=(const ON_COMPONENT_INDEX& other) const; + bool operator>(const ON_COMPONENT_INDEX& other) const; + bool operator>=(const ON_COMPONENT_INDEX& other) const; + + void Set(ON_COMPONENT_INDEX::TYPE type,int index); + void Set(ON_COMPONENT_INDEX::TYPE type,unsigned int index); + + /* + Description: + Sets m_type = invalid_type and m_index = -1. + */ + void UnSet(); + + /* + Returns: + True if m_type is set to a TYPE enum value between + brep_vertex and dim_leader_point. + */ + bool IsSet() const; + + bool IsNotSet() const; + + /* + Returns: + True if m_type is set to one of the mesh or meshtop + TYPE enum values and m_index >= 0. + */ + bool IsMeshComponentIndex() const; + + /* + Returns: + True if m_type is set to one of the subd + TYPE enum values and m_index >= 0. + */ + bool IsSubDComponentIndex() const; + + /* + Returns: + True if m_type is set to one of the + brep TYPE enum values and m_index >= 0. + */ + bool IsBrepComponentIndex() const; + + /* + Returns: + True if m_type = idef_part and m_index >= 0. + */ + bool IsIDefComponentIndex() const; + + /* + Returns: + True if m_type = polycurve_segment and m_index >= 0. + */ + bool IsPolyCurveComponentIndex() const; + + /* + Returns: + True if m_type = group_member and m_index >= 0. + */ + bool IsGroupMemberComponentIndex() const; + + /* + Returns: + True if m_type = extrusion_bottom_profile or extrusion_top_profile + and m_index >= 0. + */ + bool IsExtrusionProfileComponentIndex() const; + + /* + Returns: + True if m_type = extrusion_path and -1 <= m_index <= 1. + */ + bool IsExtrusionPathComponentIndex() const; + + /* + Returns: + True if m_type = extrusion_wall_edge and m_index >= 0. + */ + bool IsExtrusionWallEdgeComponentIndex() const; + + /* + Returns: + True if m_type = extrusion_wall_surface and m_index >= 0. + */ + bool IsExtrusionWallSurfaceComponentIndex() const; + + /* + Returns: + True if m_type = extrusion_wall_surface or extrusion_wall_edge + and m_index >= 0. + */ + bool IsExtrusionWallComponentIndex() const; + + /* + Returns: + True if m_type = extrusion_bottom_profile, extrusion_top_profile, + extrusion_wall_edge, extrusion_wall_surface, extrusion_cap_surface + or extrusion_path and m_index is reasonable. + */ + bool IsExtrusionComponentIndex() const; + + /* + Returns: + True if m_type = pointcloud_point and m_index >= 0. + */ + bool IsPointCloudComponentIndex() const; + + /* + Returns: + True if m_type = dim_... and m_index >= 0. + */ + bool IsAnnotationComponentIndex() const; + + /* + Returns: + True if m_type = hatch_loop and m_index >= 0. + */ + bool IsHatchLoopComponentIndex() const; + + void Dump( + class ON_TextLog& text_log + )const; + + void AppendToString( + class ON_String& s + )const; + + void AppendToString( + class ON_wString& s + )const; + + + TYPE m_type; + + /* + The interpretation of m_index depends on the m_type value. + + m_type m_index interpretation (0 based indices) + + no_type used when context makes it clear what array is being index + brep_vertex ON_Brep.m_V[] array index + brep_edge ON_Brep.m_E[] array index + brep_face ON_Brep.m_F[] array index + brep_trim ON_Brep.m_T[] array index + brep_loop ON_Brep.m_L[] array index + mesh_vertex ON_Mesh.m_V[] array index + meshtop_vertex ON_MeshTopology.m_topv[] array index + meshtop_edge ON_MeshTopology.m_tope[] array index + mesh_face ON_Mesh.m_F[] array index + mesh_ngon ON_Mesh.Ngon() array index + idef_part ON_InstanceDefinition.m_object_uuid[] array index + polycurve_segment ON_PolyCurve::m_segment[] array index + + extrusion_bottom_profile Use ON_Extrusion::Profile3d() to get 3d profile curve + extrusion_top_profile Use ON_Extrusion::Profile3d() to get 3d profile curve + extrusion_wall_edge Use ON_Extrusion::WallEdge() to get 3d line curve + extrusion_wall_surface Use ON_Extrusion::WallSurface() to get 3d wall surface + extrusion_cap_surface 0 = bottom cap, 1 = top cap + extrusion_path -1 = entire path, 0 = start of path, 1 = end of path + + hatch_loop ON_Hatch::m_loops[] array index + + dim_linear_point linear dimension point index + dim_radial_point radial dimension point index + dim_angular_point angular dimension point index + dim_ordinate_point ordinate dimension point index + dim_text_point annotation text object point + */ + + unsigned int UnsignedIndex() const + { + return (unsigned int)m_index; + } + + int m_index; +}; + +class ON_CLASS ON_ComponentIndexAndNumber +{ +public: + ON_ComponentIndexAndNumber() = default; + ~ON_ComponentIndexAndNumber() = default; + ON_ComponentIndexAndNumber(const ON_ComponentIndexAndNumber&) = default; + ON_ComponentIndexAndNumber& operator=(const ON_ComponentIndexAndNumber&) = default; + +public: + static const ON_ComponentIndexAndNumber UnsetAndNan; + static const ON_ComponentIndexAndNumber UnsetAndZero; + static const ON_ComponentIndexAndNumber Create( + ON_COMPONENT_INDEX ci, + double x + ); + +public: + + /* + Description: + Compare Component() using ON_COMPONENT_INDEX::Compare(). + */ + static int CompareComponent( + const ON_ComponentIndexAndNumber* a, + const ON_ComponentIndexAndNumber* b + ); + + + /* + Description: + Compare Number() nans are treated as equal and sort last. + */ + static int CompareNumber( + const ON_ComponentIndexAndNumber* a, + const ON_ComponentIndexAndNumber* b + ); + + /* + Description: + Dictionary compare Component() 1st and Number() 2nd. + */ + static int CompareComponentAndNumber( + const ON_ComponentIndexAndNumber* a, + const ON_ComponentIndexAndNumber* b + ); + + +public: + const ON_COMPONENT_INDEX Component() const; + void SetComponent(ON_COMPONENT_INDEX ci); + + double Number() const; + void SetNumber(double x); + +public: + ON_COMPONENT_INDEX m_ci = ON_COMPONENT_INDEX::UnsetComponentIndex; + double m_x = ON_DBL_QNAN; +}; + +#endif + +ON_BEGIN_EXTERNC + +// on_wcsicmp() is a wrapper for case insensitive wide string compare +// and calls one of _wcsicmp() or wcscasecmp() depending on OS. +ON_DECL +int on_wcsicmp( const wchar_t*, const wchar_t* ); + +// on_wcsupr() calls _wcsupr() or wcsupr() depending on OS +ON_DECL +wchar_t* on_wcsupr(wchar_t*); + +// on_wcslwr() calls _wcslwr() or wcslwr() depending on OS +ON_DECL +wchar_t* on_wcslwr(wchar_t*); + +// on_wcsrev() calls _wcsrev() or wcsrev() depending on OS +ON_DECL +wchar_t* on_wcsrev(wchar_t*); + +// on_stricmp() is a wrapper for case insensitive string compare +// and calls one of _stricmp(), stricmp(), or strcasecmp() +// depending on OS. +ON_DECL +int on_stricmp(const char*, const char*); + +// on_stricmp() is a wrapper for case insensitive string compare +// and calls one of _strnicmp() or strncasecmp() +// depending on OS. +ON_DECL +int on_strnicmp(const char * s1, const char * s2, int n); + +// on_strupr() calls _strupr() or strupr() depending on OS +ON_DECL +char* on_strupr(char*); + +// on_strlwr() calls _strlwr() or strlwr() depending on OS +ON_DECL +char* on_strlwr(char*); + +// on_strrev() calls _strrev() or strrev() depending on OS +ON_DECL +char* on_strrev(char*); + +/* +Description: + Calls ON_ConvertWideCharToUTF8() +*/ +ON_DECL +int on_WideCharToMultiByte( + const wchar_t*, // lpWideCharStr, + int, // cchWideChar, + char*, // lpMultiByteStr, + int // cchMultiByte, + ); + +/* +Description: + Calls ON_ConvertUTF8ToWideChar() +*/ +ON_DECL +int on_MultiByteToWideChar( + const char*, // lpMultiByteStr, + int, // cchMultiByte, + wchar_t*, // lpWideCharStr, + int // cchWideChar + ); + +/* +Description: + Find the locations in a path the specify the drive, directory, + file name and file extension. +Parameters: + path - [in] + UTF-8 encoded string that is a legitimate path to a file. + volume - [out] (pass null if you don't need the volume) + If volume is not null and the path parameter begins with + a Windows volum specification, the value of *volume will + equal the input value of path. Otherwise *volume will be nullptr. + A Windows volume specification can be either a single A-Z or a-z + letter followed by a colon ( C: ) or a Windows UNC host name + (\\MY_SERVER). + dir - [out] (pass null if you don't need the directory) + If dir is not null and the path parameter contains a + directory specification, then the returned value of *dir + will point to the character in path where the directory + specification begins. + fname - [out] (pass null if you don't need the file name) + If fname is not null and the path parameter contains a + file name specification, then the returned value of *fname + will point to the character in path where the file name + specification begins. + ext - [out] (pass null if you don't need the extension) + If ext is not null and the path parameter contains a + file extension specification, then the returned value of + *ext will point to the '.' character in path where the file + extension specification begins. +Remarks: + This function will treat a front slash ( / ) and a back slash + ( \ ) as directory separators. Because this function parses + file names store in .3dm files and the .3dm file may have been + written on a Windows computer and then read on a another + computer, it looks for a volume specification even when the + operating system is not Windows. + This function will not return an directory that does not + end with a trailing slash. + This function will not return an empty filename and a non-empty + extension. + This function parses the path string according to these rules. + It does not check the actual file system to see if the answer + is correct. +See Also: + ON_String::SplitPath +*/ +ON_DECL void on_splitpath( + const char* path, + const char** volume, + const char** dir, + const char** fname, + const char** ext + ); + +/* +Description: + Find the locations in a path the specify the drive, directory, + file name and file extension. +Parameters: + path - [in] + A legitimate file system path to a file. + volume - [out] (pass null if you don't need the volume) + If volume is not null and the path parameter begins with + a Windows volum specification, the value of *volume will + equal the input value of path. Otherwise *volume will be nullptr. + A Windows volume specification can be either a single A-Z or a-z + letter followed by a colon ( C: ) or a Windows UNC host name + (\\MY_SERVER). + dir - [out] (pass null if you don't need the directory) + If dir is not null and the path parameter contains a + directory specification, then the returned value of *dir + will point to the character in path where the directory + specification begins. + fname - [out] (pass null if you don't need the file name) + If fname is not null and the path parameter contains a + file name specification, then the returned value of *fname + will point to the character in path where the file name + specification begins. + ext - [out] (pass null if you don't need the extension) + If ext is not null and the path parameter contains a + file extension specification, then the returned value of + *ext will point to the '.' character in path where the file + extension specification begins. +Remarks: + This function will treat a front slash ( / ) and a back slash + ( \ ) as directory separators. Because this function parses + file names store in .3dm files and the .3dm file may have been + written on a Windows computer and then read on a another + computer, it looks for a volume specification even when the + operating system is not Windows. + This function will not return an directory that does not + end with a trailing slash. + This function will not return an empty filename and a non-empty + extension. + This function parses the path string according to these rules. + It does not check the actual file system to see if the answer + is correct. +See Also: + ON_wString::SplitPath +*/ +ON_DECL void on_wsplitpath( + const wchar_t* path, + const wchar_t** volume, + const wchar_t** dir, + const wchar_t** fname, + const wchar_t** ext + ); + +ON_END_EXTERNC + + +#endif diff --git a/opennurbs/Include/opennurbs_detail.h b/opennurbs/Include/opennurbs_detail.h new file mode 100644 index 0000000..db699c8 --- /dev/null +++ b/opennurbs/Include/opennurbs_detail.h @@ -0,0 +1,95 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_DETAIL_OBJECTY_INC_) +#define ON_DETAIL_OBJECTY_INC_ + +class ON_CLASS ON_DetailView : public ON_Geometry +{ + ON_OBJECT_DECLARE(ON_DetailView); + +public: + ON_DetailView(); + ~ON_DetailView(); + + // C++ defaults for copy constructor and + // operator= work fine. + + ////////////////////////////////////////////////////// + // + // virtual ON_Object overrides + // + void MemoryRelocate() override; + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + void Dump( ON_TextLog& ) const override; + + unsigned int SizeOf() const override; + + bool Write( + ON_BinaryArchive& binary_archive + ) const override; + + bool Read( + ON_BinaryArchive& binary_archive + ) override; + + ON::object_type ObjectType() const override; // returns ON::detail_object + + ////////////////////////////////////////////////////// + // + // virtual ON_Geometry overrides + // The m_boundary determines all bounding boxes + // + int Dimension() const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + // virtual ON_Geometry GetTightBoundingBox override + bool GetTightBoundingBox( class ON_BoundingBox& tight_bbox, bool bGrowBox = false, const class ON_Xform* xform = nullptr ) const override; + + bool Transform( const ON_Xform& xform ) override; + + // m_page_per_model_ratio is the ratio of page length / model length + // where both lengths are in the same unit system + // (ex. 1/4" on page = 1' in model = 0.25/12 = 0.02083) + // ( 1mm on page = 1m in model = 1/1000 = 0.001) + // If m_page_per_model_ratio > 0.0, then the detail + // is drawn using the specified scale. + double m_page_per_model_ratio; + + // A view with ON_3dmView::m_view_type = ON::nested_view_type + // This field is used for IO purposes only. Runtime detail + // view projection information is on CRhDetailViewObject. + ON_3dmView m_view; + + // 2d curve in page layout coordinates in mm + // (0,0) = lower left corner of page + ON_NurbsCurve m_boundary; + + // Update frustum to match bounding box and detail scale + bool UpdateFrustum( + ON::LengthUnitSystem model_units, + ON::LengthUnitSystem paper_units + ); +}; + + + +#endif + diff --git a/opennurbs/Include/opennurbs_dimension.h b/opennurbs/Include/opennurbs_dimension.h new file mode 100644 index 0000000..22daf01 --- /dev/null +++ b/opennurbs/Include/opennurbs_dimension.h @@ -0,0 +1,1161 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_DIMENSION_INC_) +#define OPENNURBS_DIMENSION_INC_ + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_ClassArray< class ON_DimStyle >; +#endif + +class ON_CLASS ON_Dimension : public ON_Annotation +{ + ON_OBJECT_DECLARE(ON_Dimension); + +public: +#pragma region RH_C_SHARED_ENUM [ON_Dimension::ForceArrow] [Rhino.Geometry.Dimension.ForceArrow] [nested:int] + /// + /// OBSOLETE enum do not use. + /// + enum class ForceArrow : unsigned int + { + /// + Auto = 0, + /// + Inside = 1, + /// + Outside = 2, + }; +#pragma endregion + + static ON_Dimension::ForceArrow ForceArrowFromUnsigned( + unsigned int force_arrow_as_unsigned); + +#pragma region RH_C_SHARED_ENUM [ON_Dimension::ForceText] [Rhino.Geometry.Dimension.ForceText] [nested:int] + /// + /// OBSOLETE enum do not use. + /// + enum class ForceText : unsigned int + { + /// + Auto = 0, + /// + Inside = 1, + /// + Right = 2, + /// + Left = 3, + /// + HintRight = 4, + /// + HintLeft = 5, + }; +#pragma endregion + + static ON_Dimension::ForceText ForceTextFromUnsigned( + unsigned int force_text_as_unsigned); + + +protected: + ON_Dimension( ON::AnnotationType annotation_type ); + ~ON_Dimension(); + ON_Dimension(const ON_Dimension& src); + ON_Dimension& operator=(const ON_Dimension& src); + +private: + ON_Dimension() = delete; + void Internal_Destroy(); + void Internal_CopyFrom(const ON_Dimension& src); + +public: + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + virtual ON_2dPoint DefaultTextPoint() const; + virtual bool UseDefaultTextPoint() const; + virtual void SetUseDefaultTextPoint(bool usedefault); + + // Text center-midpoint in dimension plane + ON_2dPoint TextPoint() const; + void Set2dTextPoint(const ON_2dPoint& textpoint); + + const wchar_t* UserText() const; + void SetUserText(const wchar_t* text); + const wchar_t* PlainUserText() const; + + // Computes measurement value as a number + virtual double Measurement() const = 0; + + // Add to natural rotation + ON_DEPRECATED_MSG("ON_Dimension::TextRotation() is a mistake. Use ON_Annotation::TextRotationRadians().") + double TextRotation() const; + + ON_DEPRECATED_MSG("ON_Dimension::SetTextRotation() is a mistake. Use ON_Annotation::SetTextRotationRadians().") + void SetTextRotation(double rotation_radians); + + bool ArrowIsFlipped(int i) const; + void FlipArrow(int i, bool flip) const; + + // If the dimension is a paper space object and the geometry being dimensioned is in + // model space, in a detail viewport, DetailMeasured() will have the UUID of the detail + // that the dimension references. Otherwise DetailMeasured() will be ON_nil_uuid. + ON_UUID DetailMeasured() const; + void SetDetailMeasured(ON_UUID uuid); + + // If DetailMeasured() returns ON_nil_uuid, DistanceScale() has no meaning + // If the dimension is in page space and measures model space geometry, + // DistanceScale() is the conversion from the model space distance being measured + // to the paper space distance spanned by the dimension geometry. + // When the zoom factor of the detail view changes, the distance scale will change + double DistanceScale() const; + void SetDistanceScale(double distance_scale) const; + + //virtual bool GetBBox( + // const ON_Viewport* vp, + // double dimscale, + // const ON_DimStyle* dimstyle, + // double* boxmin, + // double* boxmax, + // bool bGrow = 0) const = 0; + + virtual bool GetTextRect(ON_3dPoint text_rect[4]) const; + + // Remakes dimension text geometry object and sets it on the dimension + virtual bool UpdateDimensionText( + ON::LengthUnitSystem units_in, + const ON_DimStyle* dimstyle + ) const; + + // Makes text geometry for a dimension + ON_TextContent* RebuildDimensionText( + ON::LengthUnitSystem units_in, + const ON_DimStyle* dimstyle, + bool expandanglebrackets // replace <> with the formatted distance + ) const; + + virtual bool GetDistanceDisplayText( + ON::LengthUnitSystem units_in, + const ON_DimStyle* dimstyle, + ON_wString& displaytext) const; + + static bool GetCentermarkDisplay( + const ON_Plane& plane, + const ON_2dPoint center, + double marksize, + double radius, + ON_DimStyle::centermark_style style, + ON_Line lines[6], + bool isline[6], + int maxlines + ); + + static bool GetCentermarkSnapPoints( + const ON_Plane& plane, + const ON_2dPoint center, + double marksize, + double radius, + ON_DimStyle::centermark_style style, + ON_3dPoint points[13], + bool ispoint[13]); + + // Obsolete + ON_DEPRECATED_MSG("ON_Dimension::ArrowFit(const ON_DimStyle* parent_style)") + ON_Dimension::ForceArrow ForceArrowPosition() const; + + ON_DEPRECATED_MSG("ON_Dimension::SetArrowFit(const ON_DimStyle* parent_style,ON_DimStyle::arrow_fit arrowfit)") + void SetForceArrowPosition(ForceArrow force); + + ON_DEPRECATED_MSG("ON_Dimension::TextFit(const ON_DimStyle* parent_style)") + ON_Dimension::ForceText ForceTextPosition() const; + + ON_DEPRECATED_MSG("ON_Dimension::SetTextFit(const ON_DimStyle* parent_style,ON_DimStyle::text_fit textfit)") + void SetForceTextPosition(ForceText force); + + void SetForceDimLine( + const ON_DimStyle* parent_style, + bool forcedimline + ); + + bool ForceDimLine( + const ON_DimStyle* parent_style) const; + + void SetTextFit( + const ON_DimStyle* parent_style, + ON_DimStyle::text_fit textfit); + + ON_DimStyle::text_fit TextFit( + const ON_DimStyle* parent_style) const; + + void SetArrowFit( + const ON_DimStyle* parent_style, + ON_DimStyle::arrow_fit arrowfit); + + ON_DimStyle::arrow_fit ArrowFit( + const ON_DimStyle* parent_style) const; + + + +protected: + ON_wString m_user_text = L"<>"; // If user overridden, or "<>" to use default + double m_reserved = 0.0; + mutable ON_wString m_plain_user_text; + + bool m_use_default_text_point = true; + ON_2dPoint m_user_text_point = ON_2dPoint::UnsetPoint; // Text point if default isn't used + + mutable bool m_flip_arrow_1 = false; + mutable bool m_flip_arrow_2 = false; + mutable bool m_text_outside = false; + unsigned int m_reserved98 = 0; + unsigned int m_reserved99 = 0; + + + // UUID of detail if dimension is in page space measuring model space geometry + ON_UUID m_detail_measured = ON_nil_uuid; + // Conversion from model space size to paper space size if dimension is in page space measuring model space geometry + mutable double m_distance_scale = 1.0; + + bool Internal_WriteDimension( + ON_BinaryArchive& // serialize definition to binary archive + ) const; + + bool Internal_ReadDimension( + ON_BinaryArchive& // restore definition from binary archive + ); +}; + +class ON_CLASS ON_DimLinear : public ON_Dimension +{ + ON_OBJECT_DECLARE(ON_DimLinear); + +public: + ON_DimLinear(); + ~ON_DimLinear() = default; + ON_DimLinear(const ON_DimLinear& src) = default; + ON_DimLinear& operator=(const ON_DimLinear& src) = default; + + static const ON_DimLinear Empty; + + /* + Description: + Create a V6 linear dimension from a V5 linear dimension + The function is used when reading V5 files. + Parameters: + V5_linear_dimension -[in] + annotation_context - [in] + Dimstyle and other information referenced by V5_linear_dimension or nullptr if not available. + destination - [in] + If destination is not nullptr, then the V6 linear dimension is constructed + in destination. If destination is nullptr, then the new V6 linear dimension + is allocated with a call to new ON_DimLinear(). + */ + static ON_DimLinear* CreateFromV5DimLinear( + const class ON_OBSOLETE_V5_DimLinear& V5_linear_dimension, + const class ON_3dmAnnotationContext* annotation_context, + ON_DimLinear* destination + ); + + + /* + Parameters: + annotation_type - [in] + annotation type to test + Returns: + True if input parameter is one of the valid linear dimension types + ON::AnnotationType::Aligned or ON::AnnotationType::Rotated. + */ + static bool IsValidLinearDimensionType( + ON::AnnotationType annotation_type + ); + + /* + Parameters: + linear_dimension_type - [in] + ON::AnnotationType::Aligned or ON::AnnotationType::Rotated. + Returns: + True if input parameter is valid and type is set. + */ + bool SetLinearDimensionType( + ON::AnnotationType linear_dimension_type + ); + + bool Write( + ON_BinaryArchive& // serialize definition to binary archive + ) const override; + + bool Read( + ON_BinaryArchive& // restore definition from binary archive + ) override; + + bool Transform(const ON_Xform& xform) override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + bool GetAnnotationBoundingBox( + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + double* boxmin, + double* boxmax, + bool bGrow = false + ) const override; // ON_Annotation override + + // Gets transform for dimension text from ON_xy_plane to 3d display location + bool GetTextXform( + const ON_Xform* model_xform, + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + ON_Xform& text_xform_out + ) const; + + bool GetTextXform( + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + ON_Xform& text_xform_out + ) const override; + + bool Create( + ON::AnnotationType dim_type, + const ON_UUID style_id, + const ON_Plane& plane, + const ON_3dVector& ref_horizontal, + const ON_3dPoint& def_pt1, + const ON_3dPoint& def_pt2, + const ON_3dPoint& dimline_pt, + double rotation_in_plane = 0.0 + ); + + /* + Description: + Create an aligned linear dimension. The dimension line is + parallel to the segment connecting the extension points. + Parameters: + extension_point0 - [in] + extension_point1 - [in] + locations of one of the points being dimensioned. + The dimension line will be parallel to the segment + connecting these points. + dimension_line_point - [in] + a point on the linear dimension line. + plane_normal - [in] + A vector perpindcular to the line between the extension points + that defines the orientation of the dimension's plane. + dim_style_id - [in] + destination - [in] + If nullptr, the returned ON_DimLinear is allocated by operator new. + Otherwise, the reuturned ON_DimLinear is created in destination. + */ + static ON_DimLinear* CreateAligned( + ON_3dPoint extension_point0, + ON_3dPoint extension_point1, + ON_3dPoint dimension_line_point, + ON_3dVector plane_normal, + ON_UUID style_id, + ON_DimLinear* destination + ); + + /* + Description: + Create a rotated linear dimension to the document. + The dimension line is explicitly specified. + Parameters: + extension_point0 - [in] + extension_point1 - [in] + locations of one of the points being dimensioned. + The dimension line will be parallel to the segment + connecting these points. + dimension_line - [in] + the dimension line. This is treated as an infinite + line and the points are automatically calculated. + plane_normal - [in] + A vector perpindcular to the line between the extension points + that defines the orientation of the dimension's plane. + The dimension line is projected to this plane. + dim_style_id - [in] + destination - [in] + If nullptr, the returned ON_DimLinear is allocated by operator new. + Otherwise, the reuturned ON_DimLinear is created in destination. + */ + static ON_DimLinear* CreateRotated( + ON_3dPoint extension_point0, + ON_3dPoint extension_point1, + ON_Line dimension_line, + ON_3dVector plane_normal, + ON_UUID style_id, + ON_DimLinear* destination + ); + + // virtual + double Measurement() const override; + ON_2dPoint DefaultTextPoint() const override; + + // DefPoint1 is m_plane.origin + // Meaasurement is between DefPoint1 and DefPoint2 + // parallel to the m_plane x-axis. + ON_2dPoint DefPoint1() const; + ON_2dPoint DefPoint2() const; + ON_2dPoint DimlinePoint() const; + + void Set2dDefPoint1(ON_2dPoint pt); + void Set2dDefPoint2(ON_2dPoint pt); + void Set2dDimlinePoint(ON_2dPoint pt); + + void Set3dDefPoint1(ON_3dPoint pt); + void Set3dDefPoint2(ON_3dPoint pt); + void Set3dDimlinePoint(ON_3dPoint pt); + + ON_2dPoint ArrowPoint1() const; // Calculated + ON_2dPoint ArrowPoint2() const; // Calculated + + bool Get3dPoints( + ON_3dPoint* defpt1, + ON_3dPoint* defpt2, + ON_3dPoint* arrowpt1, + ON_3dPoint* arrowpt2, + ON_3dPoint* dimline, + ON_3dPoint* textpt) const; + + bool GetDisplayLines( + const ON_Viewport* vp, + const ON_DimStyle* style, + double dimscale, + ON_3dPoint text_rect[4], + ON_Line lines[4], + bool isline[4], + int maxlines) const; + + void GetArrowXform( + int which_end, + double scale, + bool arrowflipped, + bool from_the_back, + ON_Xform& arrow_xform_out) const; + +public: + bool GetTextXform( + const ON_Xform* model_xform, + const ON_3dVector view_x, + const ON_3dVector view_y, + const ON_3dVector view_z, + ON::view_projection projection, + bool bDrawForward, + const ON_DimStyle* dimstyle, + double dimscale, + ON_Xform& text_xform_out + ) const; + + +protected: + ON_2dPoint m_def_pt_2 = ON_2dPoint::UnsetPoint; + ON_2dPoint m_dimline_pt = ON_2dPoint::UnsetPoint; +}; + +//--------------------------------------------------------------------- + +class ON_CLASS ON_DimAngular : public ON_Dimension +{ + ON_OBJECT_DECLARE(ON_DimAngular); + +public: + ON_DimAngular(); + ~ON_DimAngular() = default; + ON_DimAngular(const ON_DimAngular& src) = default; + ON_DimAngular& operator=(const ON_DimAngular& src) = default; + + static const ON_DimAngular Empty; + + /* + Parameters: + annotation_type - [in] + annotation type to test + Returns: + True if input parameter is one of the valid linear dimension types + ON::AnnotationType::Angular or ON::AnnotationType::Angular3pt. + */ + static bool IsValidAngularDimensionType( + ON::AnnotationType annotation_type + ); + + /* + Parameters: + angular_dimension_type - [in] + ON::AnnotationType::Angular or ON::AnnotationType::Angular3pt. + Returns: + True if input parameter is valid and type is set. + */ + bool SetAngularDimensionType( + ON::AnnotationType angular_dimension_type + ); + + static ON_DimAngular* CreateFromV5DimAngular( + const class ON_OBSOLETE_V5_DimAngular& V5_dim_angle, + const class ON_3dmAnnotationContext* annotation_context, + ON_DimAngular* destination + ); + + bool Write( + ON_BinaryArchive& // serialize definition to binary archive + ) const override; + + bool Read( + ON_BinaryArchive& // restore definition from binary archive + ) override; + + bool Transform(const ON_Xform& xform) override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + bool GetAnnotationBoundingBox( + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + double* boxmin, + double* boxmax, + bool bGrow = false + ) const override; // ON_Annotation override + +// Gets transform for dimension text from ON_xy_plane to 3d display location + bool GetTextXform( + const ON_Xform* model_xform, + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + ON_Xform& text_xform_out + ) const; + + bool GetTextXform( + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + ON_Xform& text_xform_out + ) const override; + + /* + Parameters: + dim_style - [in] + Pass nullptr if a dim_style is not available. + arc - [in] + arc being dimensioned + offset - [in] + distance from the arc being dimensioned to the angular dimension arc. + When offset > 0, the dimension is outside the arc's circle. + When offset < 0 and > - arc.Radius(), the dimension is inside the arc's circle. + In all other cases, the angular dimension arc is on the arc. + Returns: + True if successful. + False if input is not valid. In this case ON_DimAngle::Empty settings are returned. + */ + bool Create( + const ON_DimStyle* dim_style, + ON_Arc arc, + double offset + ); + + /* + Description: + The angle between the lines is dimensioned. + + If the lines intersect in a single point, that point is used as the center + of the angular dimension arc. In this case, there are eight possible angles + to dimension. The point_on_angular_dimension_arc and point_on_line parameters + are used to select the correct angle to dimension. If a point_on_line parameter + is not set, the corresponding line's midpoint is used. + + If the lines are colinear, the point on the line closest to + point_on_angular_dimension_arc is the center of the angular dimension arc. + + Parameters: + dim_style - [in] + Pass nullptr if a dim_style is not available. + line1 - [in] + point_on_line1 - [in] + If point_on_line1 is specified, it inidicates which semi-infinite portion of line1 to dimension. + Otherwise the midpoint of lne1 as a segment is used. + When in doubt, pass ON_3dPoint::UnsetPoint. + line2 - [in] + point_on_line2 - [in] + If point_on_line2 is specified, it inidicates which semi-infinite portion of line2 to dimension. + Otherwise the midpoint of line2 as a segment is used. + When in doubt, pass ON_3dPoint::UnsetPoint. + point_on_angular_dimension_arc - [in] + A point on the interior of the angular dimension arc. + bSetExtensionPoints - [in] + If bSetExtensionPoints is true, and a point_on_line parameter is valid, that point + is used as the extension point. Otherwise the angular dimension arc endpoint is used. + Returns: + True if successful. + False if input is not valid. In this case ON_DimAngle::Empty settings are returned. + */ + bool Create( + const ON_DimStyle* dim_style, + ON_Line line1, + ON_3dPoint point_on_line1, + ON_Line line2, + ON_3dPoint point_on_line2, + ON_3dPoint point_on_angular_dimension_arc, + bool bSetExtensionPoints + ); + + bool Create( + const ON_UUID style_id, + const ON_Plane& plane, + const ON_3dVector& ref_horizontal, + const ON_3dPoint& center_pt, + const ON_3dPoint& extension_pt1, // point on first extension vector + const ON_3dPoint& extension_pt2, // point on second extension vector + const ON_3dPoint& dimline_pt // point on dimension line + ); + + bool Create( + const ON_UUID style_id, + const ON_Plane& plane, + const ON_3dVector& ref_horizontal, + const ON_3dPoint& extension_pt1, // start of first extension line + const ON_3dPoint& extension_pt2, // start of second extension line + const ON_3dPoint& direction_pt1, // point on first extension vector + const ON_3dPoint& direction_pt2, // point on second extension vector + const ON_3dPoint& dimline_pt // point on dimension line + ); + + bool AdjustFromPoints( + const ON_Plane& plane, + const ON_3dPoint& center_pt, + const ON_3dPoint& extension_pt1, // point on first extension vector + const ON_3dPoint& extension_pt2, // point on second extension vector + const ON_3dPoint& dimline_pt // point on dimension line + ); + + bool AdjustFromPoints( + const ON_Plane& plane, + const ON_3dPoint& extension_pt1, // start of first extension line + const ON_3dPoint& extension_pt2, // start of second extension line + const ON_3dPoint& direction_pt1, // point on first extension vector + const ON_3dPoint& direction_pt2, // point on second extension vector + const ON_3dPoint& dimline_pt // point on dimension line + ); + + static bool FindAngleVertex( + ON_Line lines[2], + ON_3dPoint pickpoints[2], + const ON_Plane& plane, + ON_3dPoint& centerpoint_out); + + + bool UpdateDimensionText(const ON_DimStyle* dimstyle) const; + + bool GetAngleDisplayText(const ON_DimStyle* dimstyle, ON_wString& displaytext) const; + + // virtual + double Measurement() const override; // angle in radians + ON_2dPoint DefaultTextPoint() const override; + bool GetAngles(double* start_ang, double* end_ang, double* mid_ang) const; + double Radius() const; + + // CenterPoint is m_plane.origin + // Measurement is angle between m_vec_1 & m_vec_2 in radians + ON_2dPoint CenterPoint() const; + ON_2dPoint DefPoint1() const; // Start of first extension + ON_2dPoint DefPoint2() const; // Start of second extension + ON_2dPoint DimlinePoint() const; // Point on dimension arc + ON_2dPoint UserTextPoint() const; // Text point if user positioned + ON_2dVector ExtDir1() const; // Direction of first extension + ON_2dVector ExtDir2() const; // Direction of second extension + void SetExtDir1(const ON_2dVector& dir1); + void SetExtDir2(const ON_2dVector& dir2); + + void SetUserTextPoint(const ON_3dPoint& point); + + void Set2dCenterPoint(ON_2dPoint pt); // Apex of angle + void Set2dDefPoint1(ON_2dPoint pt); // Point where first extension starts + void Set2dDefPoint2(ON_2dPoint pt); // Point where second extension starts + void Set2dDimlinePoint(ON_2dPoint pt); // Point on dimension arc + + //void Set2dDefPoint1(ON_2dPoint pt); // Point where first extension starts + //void Set2dDefPoint2(ON_2dPoint pt); // Point where second extension starts + //void Set2dDimlinePoint(ON_2dPoint pt); // Point on dimension arc + + //void Set3dCenterPoint(ON_3dPoint pt); + //void Set3dDefPoint1(ON_3dPoint pt); + //void Set3dDefPoint2(ON_3dPoint pt); + //void Set3dDimlinePoint(ON_3dPoint pt); + + ON_2dPoint ArrowPoint1() const; // Calculated - start of arc + ON_2dPoint ArrowPoint2() const; // Calculated - end of arc + + bool Get3dPoints( + ON_3dPoint* center, + ON_3dPoint* defpt1, + ON_3dPoint* defpt2, + ON_3dPoint* arrowpt1, + ON_3dPoint* arrowpt2, + ON_3dPoint* dimline, + ON_3dPoint* textpt) const; + + bool GetDisplayLines( + const ON_Viewport* vp, + const ON_DimStyle* style, + double dimscale, + const ON_3dPoint text_rect[4], + ON_Line lines[2], + bool isline[2], + ON_Arc arcs[2], + bool isarc[2], + int maxlines, + int maxarcs) const; + + void GetArrowXform( + int which_end, + double arrowlength, + bool arrowflipped, + bool from_the_back, + ON_Xform& arrow_xform_out) const; + + bool UpdateDimensionText( + ON::LengthUnitSystem units_in, + const ON_DimStyle* dimstyle) const override; + + bool GetDistanceDisplayText( + ON::LengthUnitSystem units_in, + const ON_DimStyle* dimstyle, + ON_wString& displaytext) const override; + +protected: + // Center point is at plane origin (0,0) + ON_2dVector m_vec_1 = ON_2dVector::XAxis; + ON_2dVector m_vec_2 = ON_2dVector::YAxis; + double m_ext_offset_1 = 0.0; // distance along m_vec_1 to start extension line 1 + double m_ext_offset_2 = 0.0; // distance along m_vec_2 to start extension line 2 + ON_2dPoint m_dimline_pt = ON_2dPoint(1.0, 1.0); // point on interior of dimension arc +}; + +//--------------------------------------------------------------------- + +class ON_CLASS ON_DimRadial : public ON_Dimension +{ + ON_OBJECT_DECLARE(ON_DimRadial); + +public: + ON_DimRadial(); + ~ON_DimRadial() = default; + ON_DimRadial(const ON_DimRadial& src) = default; + ON_DimRadial& operator=(const ON_DimRadial& src) = default; + + static const ON_DimRadial Empty; + + + /* + Description: + Create a V6 radial dimension from a V5 radial dimension + The function is used when reading V5 files. + Parameters: + V5_radial_dimension -[in] + annotation_context - [in] + Dimstyle and other information referenced by V5_radial_dimension or nullptr if not available. + destination - [in] + If destination is not nullptr, then the V6 radial dimension is constructed + in destination. If destination is nullptr, then the new V6 radial dimension + is allocated with a call to new ON_DimRadial(). + */ + static ON_DimRadial* CreateFromV5DimRadial( + const class ON_OBSOLETE_V5_DimRadial& V5_radial_dimension, + const class ON_3dmAnnotationContext* annotation_context, + ON_DimRadial* destination + ); + + /* + Parameters: + annotation_type - [in] + annotation type to test + Returns: + True if input parameter is one of the valid radial dimension types + ON::AnnotationType::Radius or ON::AnnotationType::Diameter. + */ + static bool IsValidRadialDimensionType( + ON::AnnotationType annotation_type + ); + + /* + Parameters: + radial_dimension_type - [in] + ON::AnnotationType::Radius or ON::AnnotationType::Diameter. + Returns: + True if input parameter is valid and type is set. + */ + bool SetRadialDimensionType( + ON::AnnotationType radial_dimension_type + ); + + bool Write( + ON_BinaryArchive& // serialize definition to binary archive + ) const override; + + bool Read( + ON_BinaryArchive& // restore definition from binary archive + ) override; + + bool Transform(const ON_Xform& xform) override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + bool GetAnnotationBoundingBox( + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + double* boxmin, + double* boxmax, + bool bGrow = false + ) const override; // ON_Annotation override + + // Gets transform for dimension text from ON_xy_plane to 3d display location + bool GetTextXform( + const ON_Xform* model_xform, + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + ON_Xform& text_xform_out + ) const; + + bool GetTextXform( + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + ON_Xform& text_xform_out + ) const override; + + bool Create( + ON::AnnotationType type, + const ON_UUID style_id, + const ON_Plane& plane, + const ON_3dPoint& center_pt, + const ON_3dPoint& radius_pt, + const ON_3dPoint& dimline_pt + ); + + bool AdjustFromPoints( + const ON_Plane& plane, + const ON_3dPoint& center_pt, + const ON_3dPoint& radius_pt, + const ON_3dPoint& dimline_pt + ); + + double Measurement() const override; + + ON_2dPoint DefaultTextPoint() const override; + ON_2dPoint CenterPoint() const; + ON_2dPoint RadiusPoint() const; // Point on arc being measured + ON_2dPoint DimlinePoint() const; // Endpoint of leader tail, not including landing + ON_2dPoint KneePoint() const; // Point where leader tail bends + + void Set2dCenterPoint(ON_2dPoint pt); + void Set2dRadiusPoint(ON_2dPoint pt); + void Set2dDimlinePoint(ON_2dPoint pt); + + void Set3dCenterPoint(ON_3dPoint pt); + void Set3dRadiusPoint(ON_3dPoint pt); + void Set3dDimlinePoint(ON_3dPoint pt); + + bool Get3dPoints( + ON_3dPoint* center_pt, + ON_3dPoint* radius_pt, + ON_3dPoint* dimline_pt, + ON_3dPoint* knee_pt) const; + + bool GetDisplayLines( + const ON_DimStyle* style, + double dimscale, + ON_3dPoint text_rect[4], + ON_Line lines[9], + bool isline[9], + int maxlines) const; + + void GetArrowXform( + double scale, + ON_Xform& arrow_xform_out) const; + +protected: + ON_2dPoint m_radius_pt = ON_2dPoint::UnsetPoint; + ON_2dPoint m_dimline_pt = ON_2dPoint::UnsetPoint; +}; + + +//--------------------------------------------------------------------- +// + dimpt +// | +// | +// | +// + kinkpt2 +// \ +// \ kinkoffset2 +// \ +// + kinkpt1 +// | +// | kinkoffset1 +// | +// + ldrpt +// 1 +// 2 +// 3 + +class ON_CLASS ON_DimOrdinate : public ON_Dimension +{ + ON_OBJECT_DECLARE(ON_DimOrdinate); + +public: + ON_DimOrdinate(); + ~ON_DimOrdinate() = default; + ON_DimOrdinate(const ON_DimOrdinate& src) = default; + ON_DimOrdinate& operator=(const ON_DimOrdinate& src) = default; + + static const ON_DimOrdinate Empty; + +#pragma region RH_C_SHARED_ENUM [ON_DimOrdinate::MeasuredDirection] [Rhino.Geometry.OrdinateDimension.MeasuredDirection] [nested:byte] + /// + /// Ordinate dimension measures x or y direction + /// + enum class MeasuredDirection : unsigned char + { + /// + Unset = 0, + /// Measures horizontal distance + Xaxis = 1, + /// Measures vertical distance + Yaxis = 2, + }; +#pragma endregion + + static ON_DimOrdinate::MeasuredDirection MeasuredDirectionFromUnsigned( + unsigned int measured_direction_as_unsigned + ); + + static ON_DimOrdinate* CreateFromV5DimOrdinate( + const class ON_OBSOLETE_V5_DimOrdinate& V5_dim_ordinate, + const class ON_3dmAnnotationContext* annotation_context, + ON_DimOrdinate* destination + ); + + bool Write( + ON_BinaryArchive& archive + ) const override; + + bool Read( + ON_BinaryArchive& archive + ) override; + + bool Transform(const ON_Xform& xform) override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + bool GetAnnotationBoundingBox( + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + double* boxmin, + double* boxmax, + bool bGrow = false + ) const override; // ON_Annotation override + + // Gets transform for dimension text from ON_xy_plane to 3d display location + bool GetTextXform( + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + ON_Xform& text_xform_out + ) const override; + + bool GetTextXform( + const ON_Xform* model_xform, + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + ON_Xform& text_xform_out + ) const; + + bool Create( + const ON_UUID style_id, + const ON_Plane& plane, + MeasuredDirection direction, + const ON_3dPoint& basept, + const ON_3dPoint& defpt, + const ON_3dPoint& ldrpt, + double kinkoffset1, + double kinkoffset2 + ); + + bool AdjustFromPoints( + const ON_Plane& plane, + MeasuredDirection direction, + const ON_3dPoint& basept, + const ON_3dPoint& defpt, + const ON_3dPoint& ldrpt, + double kinkoffset1, + double kinkoffset2 + ); + + ON_2dPoint DefPt() const; + ON_2dPoint LeaderPt() const; + ON_2dPoint KinkPt1() const; + ON_2dPoint KinkPt2() const; + double KinkOffset1() const; + double KinkOffset2() const; + + void Set2dDefPt(ON_2dPoint pt); + void Set2dLeaderPt(ON_2dPoint pt); + void SetKinkOffset1(double d); + void SetKinkOffset2(double d); + + void Set3dBasePoint(ON_3dPoint pt); + void Set3dDefPt(ON_3dPoint pt); + void Set3dLeaderPt(ON_3dPoint pt); + + ON_3dPoint Get3dBasePoint() const; + ON_3dPoint Get3dDefPt() const; + ON_3dPoint Get3dLeaderPt() const; + ON_3dPoint Get3dKinkPt1(double default_kink_offset = 1.0) const; + ON_3dPoint Get3dKinkPt2(double default_kink_offset = 1.0) const; + + bool Get3dPoints( + ON_3dPoint* base_pt, + ON_3dPoint* def_pt, + ON_3dPoint* ldr_pt, + ON_3dPoint* kink_pt1, + ON_3dPoint* kink_pt2, + double default_kink_offset = 1.0) const; + + bool GetDisplayLines( + const ON_DimStyle* style, + double dimscale, + ON_3dPoint text_rect[4], + ON_Line lines[3], + bool isline[3], + int maxlines) const; + + bool CalcKinkPoints( + ON_2dPoint defpt, + ON_2dPoint ldrpt, + MeasuredDirection direction, + double default_kink_offset, + ON_2dPoint& kinkpt1_out, + ON_2dPoint& kinkpt2_out) const; + + MeasuredDirection ImpliedDirection( + ON_2dPoint defpt, + ON_2dPoint ldrpt + ) const; + + MeasuredDirection GetMeasuredDirection() const; + void SetMeasuredDirection(MeasuredDirection direction); + + double Measurement() const override; + +protected: + // Plane origin is base for measurements + // Measurements are from plane origin to dimension point + // in either x or y axis direction + MeasuredDirection m_direction = MeasuredDirection::Unset; + + ON_2dPoint m_def_pt = ON_2dPoint::UnsetPoint; + ON_2dPoint m_ldr_pt = ON_2dPoint::UnsetPoint; + + double m_kink_offset_1 = ON_UNSET_VALUE; // measures from defpt1 toward defpt2 to kink1 + double m_kink_offset_2 = ON_UNSET_VALUE; // measures from kink1 toward defpt2 to kink2 +}; + + +//--------------------------------------------------------------------- + +class ON_CLASS ON_Centermark : public ON_Dimension +{ + ON_OBJECT_DECLARE(ON_Centermark); + +public: + ON_Centermark(); + ~ON_Centermark() = default; + ON_Centermark(const ON_Centermark& src) = default; + ON_Centermark& operator=(const ON_Centermark& src) = default; + + static const ON_Centermark Empty; + + bool Write( + ON_BinaryArchive& // serialize definition to binary archive + ) const override; + + bool Read( + ON_BinaryArchive& // restore definition from binary archive + ) override; + + bool Transform(const ON_Xform& xform) override; + + bool GetTextXform( + const ON_Viewport*, + const ON_DimStyle*, + double, + ON_Xform& + ) const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + bool GetAnnotationBoundingBox( + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + double* boxmin, + double* boxmax, + bool bGrow = false + ) const override; // ON_Annotation override + + bool Create( + const ON_UUID style_id, + const ON_Plane& plane, + const ON_3dPoint& center_pt, + const double radius + ); + + bool AdjustFromPoints( + const ON_Plane& plane, + const ON_3dPoint& center_pt + ); + + double Measurement() const override; + + ON_2dPoint CenterPoint() const; + void Set2dCenterPoint(ON_2dPoint pt); + void Set3dCenterPoint(ON_3dPoint pt); + + bool GetDisplayLines( + const ON_DimStyle* style, + double dimscale, + ON_Line lines[6], + bool isline[6], + int maxlines) const; + + double Radius() const; // radius of marked circle + void SetRadius(double radius); + +private: + double m_radius = 0.0; +}; + + + + +#endif + diff --git a/opennurbs/Include/opennurbs_dimensionformat.h b/opennurbs/Include/opennurbs_dimensionformat.h new file mode 100644 index 0000000..b209305 --- /dev/null +++ b/opennurbs/Include/opennurbs_dimensionformat.h @@ -0,0 +1,87 @@ + +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +// ON_Table class +#ifndef OPENNURBS_NUMBERFORMAT_H_INCLUDED +#define OPENNURBS_NUMBERFORMAT_H_INCLUDED + +class ON_NumberFormatter +{ + ON_NumberFormatter(); +public: + static bool bFormatIsAccurate; + + static void Fraction( + double value, + int& wholenumber, + int& numerator, + int& denominator, + int precision); + + static double RoundOff( + double number, + double round_off); + + static void SuppressZeros( + ON_wString& dist, + ON_DimStyle::suppress_zero sz); + + // When FormatNumber() or FormatLength() is called with + // output_lengthformat == ON_DimStyle::OBSOLETE_length_format::FeetInches + // distance must be in decimal feet units to get the right answer. + static bool FormatNumber( + double distance, + ON_DimStyle::OBSOLETE_length_format output_lengthformat, // dec, frac, ft-in + double round_off, + int resolution, + ON_DimStyle::suppress_zero zero_suppress, + bool bracket_fractions, + ON_wString& output); + + // When FormatNumber() or FormatLength() is called with + // output_lengthformat == ON_DimStyle::LengthDisplay::FeetAndInches + // distance must be in decimal feet units to get the right answer. + static bool FormatLength( + double distance, + ON_DimStyle::LengthDisplay output_lengthdisplay, + double round_off, + int resolution, + ON_DimStyle::suppress_zero zero_suppress, + bool bracket_fractions, + ON_wString& output); + + static bool FormatAngleStringDMS( + double angle_radians, + int resolution, + ON_wString& formatted_string); + + static bool FormatAngleStringDMS( + double angle_degrees, + ON_wString& formatted_string); + + static bool FormatAngleStringDecimal( + double angle_radians, + int resolution, + double roundoff, + ON_DimStyle::suppress_zero zero_suppression, + ON_wString& formatted_string); + + +}; + +#endif + diff --git a/opennurbs/Include/opennurbs_dimensionstyle.h b/opennurbs/Include/opennurbs_dimensionstyle.h new file mode 100644 index 0000000..6818e80 --- /dev/null +++ b/opennurbs/Include/opennurbs_dimensionstyle.h @@ -0,0 +1,2580 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_DIMENSIONSTYLE_INC_) +#define OPENNURBS_DIMENSIONSTYLE_INC_ + + +class ON_CLASS ON_Arrowhead +{ +public: + ON_Arrowhead() = default; + ~ON_Arrowhead() = default; + ON_Arrowhead(const ON_Arrowhead&) = default; + ON_Arrowhead& operator=(const ON_Arrowhead&) = default; + + bool operator==(const ON_Arrowhead& other) const; + bool operator!=(const ON_Arrowhead& other) const; + + +#pragma region RH_C_SHARED_ENUM [ON_Arrowhead::arrow_type] [Rhino.DocObjects.DimensionStyle.ArrowType] [nested:int] + /// + /// Defines enumerated values for arrowhead shapes. + /// + enum class arrow_type : unsigned int + { + /// + None = 0, + /// + UserBlock = 1, + /// + SolidTriangle = 2, // 2:1 + /// + Dot = 3, + /// + Tick = 4, + /// + ShortTriangle = 5, // 1:1 + /// + OpenArrow = 6, + /// + Rectangle = 7, + /// + LongTriangle = 8, // 4:1 + /// + LongerTriangle = 9, // 6:1 + }; +#pragma endregion + + static ON_Arrowhead::arrow_type ArrowTypeFromUnsigned( + unsigned int type_as_unsigned + ); + + arrow_type ArrowheadType() const; + void SetArrowheadType(arrow_type type); + ON_UUID ArrowBlockId() const; + void SetArrowBlockId(ON_UUID id); + + static ON__UINT32 GetPoints( + arrow_type type, + const double*& points); + + static ON__UINT32 GetPoints( + arrow_type type, + ON_2dPointArray& points); + + static bool GetArrowheadBoundingBox( + ON_Arrowhead::arrow_type arrow_type, + ON_UUID arrow_block_id, + ON_Xform xform, + ON_BoundingBox& bbox, + bool grow); + + static + ON_Arrowhead::arrow_type DefaultArrowType(); + +private: + arrow_type m_arrowhead_type = ON_Arrowhead::arrow_type::SolidTriangle; + ON_UUID m_arrow_block_id = ON_nil_uuid; + +}; + +class ON_CLASS ON_TextMask +{ +public: + +#pragma region RH_C_SHARED_ENUM [ON_TextMask::MaskType] [Rhino.DocObjects.DimensionStyle.MaskType] [nested:byte] + /// + /// Text mask drawn with background color or explicit color + /// + enum class MaskType : unsigned char + { + /// + /// Text mask drawn with background color + /// + BackgroundColor = 0, + /// + /// Text mask drawn with explicit color + /// + MaskColor = 1, + }; +#pragma endregion + + static ON_TextMask::MaskType MaskTypeFromUnsigned( + unsigned int mask_border_as_unsigned + ); + +#pragma region RH_C_SHARED_ENUM [ON_TextMask::MaskFrame] [Rhino.DocObjects.DimensionStyle.MaskFrame] [nested:byte] + /// + /// Draw a frame stroke around the text mask area + /// + enum class MaskFrame : unsigned char + { + /// + /// Text mask frame not drawn + /// + NoFrame = 0, + /// + /// Text mask frame outline rectangle drawn + /// + RectFrame = 1, + }; +#pragma endregion + + static ON_TextMask::MaskFrame MaskFrameFromUnsigned( + unsigned int mask_frame_as_unsigned + ); + +public: + + /* + The default constructor content is idenical to ON_TextMask::None. + */ + ON_TextMask() = default; + ~ON_TextMask() = default; + ON_TextMask(const ON_TextMask& src) = default; + ON_TextMask& operator=(const ON_TextMask& src) = default; + +public: + + /* + ON_TextMask::None has no effect on text appearance. + */ + static const ON_TextMask None; + + /* + Description: + ON_TextMask::Compare() compares content in a repeatable + and well ordered way. + Returns: + 0: lhs and rhs have identical content. + <0: lhs content is less than rhs content + >0: lhs content is greater than rhs content + */ + static int Compare( + const ON_TextMask& lhs, + const ON_TextMask& rhs + ); + + // Specifies whether or not to draw a Text Mask + bool DrawTextMask() const; + void SetDrawTextMask(bool bDraw); + + // Determines where to get the color to draw a Text Mask + // Can be background color or a specific color + ON_TextMask::MaskType MaskFillType() const; + void SetMaskFillType(ON_TextMask::MaskType source); + + // Determines whether or not to draw a rectangular frame around a text mask + ON_TextMask::MaskFrame MaskFrameType() const; + void SetMaskFrameType(ON_TextMask::MaskFrame frame); + + /* + Returns: + Mask color. + Remarks: + The mask color is applied only when MaskFillType() = ON_TextMask::MaskType::MaskColor + */ + ON_Color MaskColor() const; + + void SetMaskColor( + ON_Color color + ); + + /* + Returns: + Width of border area around text to be masked. The default value is 0.0. + */ + double MaskBorder() const; + + void SetMaskBorder(double offset); + + bool Write( + ON_BinaryArchive& archive + ) const; + + bool Read( + ON_BinaryArchive& archive + ); + + /* + Returns: + A SHA1 of the values defining the text mask. + Two text masks have the same + content if and only if they have identical content hash values. + */ + const ON_SHA1_Hash& ContentHash() const; + +private: + bool m_bDrawMask = false; + ON_TextMask::MaskType m_mask_type = ON_TextMask::MaskType::BackgroundColor; + ON_TextMask::MaskFrame m_mask_frame = ON_TextMask::MaskFrame::NoFrame; + + unsigned char m_reserved2 = 0; + + ON_Color m_mask_color = ON_Color::White; + double m_mask_border = 0.0; + + // At some point, the reserved fields may have the name changed and be + // used to store additional informtion of how to draw the mask, + // (feathered edges, rounded corners, etc.). + unsigned int m_reserved3 = 0; + mutable ON_SHA1_Hash m_content_hash = ON_SHA1_Hash::ZeroDigest; +}; + +bool operator==( + const class ON_TextMask& lhs, + const class ON_TextMask& rhs + ); + +bool operator!=( + const class ON_TextMask& lhs, + const class ON_TextMask& rhs + ); + + +class ON_CLASS ON_DimStyle : public ON_ModelComponent +{ + ON_OBJECT_DECLARE(ON_DimStyle); +private: + friend class ON_V5x_DimStyle; + +public: + // Predefined default dimension styles always available + static const ON_DimStyle Unset; // index = ON_UNSET_INT_INDEX, id = nil. + static const ON_DimStyle Default; // index = -1, unique and persistent id. + static const ON_DimStyle DefaultInchDecimal; // index = -2, unique and persistent id. + static const ON_DimStyle DefaultInchFractional; // index = -3, unique and persistent id. + static const ON_DimStyle DefaultFootInchArchitecture; // index = -4, unique and persistent id. + static const ON_DimStyle DefaultMillimeterSmall; // index = -5, unique and persistent id. + static const ON_DimStyle DefaultMillimeterLarge; // index = -6, unique and persistent id. + static const ON_DimStyle DefaultMillimeterArchitecture; // index = -7, unique and persistent id. + static const ON_DimStyle DefaultFeetDecimal; // index = -8, unique and persistent id. + static const ON_DimStyle DefaultFeetEngrave; // index = -9, unique and persistent id. + static const ON_DimStyle DefaultMillimeterEngrave; // index = -10, unique and persistent id. + static const ON_DimStyle DefaultModelUnitsDecimal; // index = -11, unique and persistent id. + static const ON_DimStyle DefaultModelUnitsEngrave; // index = -12, unique and persistent id. + +public: + /* + Parameters: + dimstyle - [in] + Returns: + If dimstyle not nullptr, then dimstyle is returned. + Otherwise a non-null pointer to a persistent dimstyle is returned. + A null pointer is never returned. + Remarks: + This function is used when a dimension style is required. + */ + static const class ON_DimStyle& DimStyleOrDefault( + const class ON_DimStyle* dimstyle + ); + + /* + Parameters: + id - [in] + Returns: + If the id is not nil and identifies one of the above system dimstyles, that + dimstyle is returned. Otherwise, ON_DimStyle::Unset is returned. + */ + static const ON_DimStyle& SystemDimstyleFromId( + ON_UUID id + ); + + /* + Parameters: + index - [in] + Returns: + If the id is not nil and identifies one of the above system dimstyles, that + dimstyle is returned. Otherwise, ON_DimStyle::Unset is returned. + */ + static const ON_DimStyle& SystemDimstyleFromIndex( + int index + ); + + /* + Parameters: + name_hash - [in] + Returns: + If the id is not nil and identifies one of the above system dimstyles, that + dimstyle is returned. Otherwise, ON_DimStyle::Unset is returned. + */ + static const ON_DimStyle& SystemDimstyleFromName( + const ON_NameHash& name_hash + ); + + /* + Parameters: + name_hash - [in] + Returns: + If the id is not nil and identifies one of the above system dimstyles, that + dimstyle is returned. Otherwise, ON_DimStyle::Unset is returned. + */ + static const ON_DimStyle& SystemDimstyleFromContentHash( + const ON_SHA1_Hash& content_hash + ); + +private: + /* + Parameters: + system_dimstyle_list - [out] + Returns: + Number of system dimstyles. + Remarks: + ON_DimStyle::Unset is not added system_dimstyle_list[]. + */ + static unsigned int Internal_GetSystemDimstyleList( + ON_SimpleArray& system_dimstyle_list + ); + +public: + + /* + Parameters: + model_component_reference - [in] + none_return_value - [in] + value to return if ON_DimStyle::Cast(model_component_ref.ModelComponent()) + is nullptr + Returns: + If ON_DimStyle::Cast(model_component_ref.ModelComponent()) is not nullptr, + that pointer is returned. Otherwise, none_return_value is returned. + */ + static const ON_DimStyle* FromModelComponentRef( + const class ON_ModelComponentReference& model_component_reference, + const ON_DimStyle* none_return_value + ); + + /* + Description: + Create a clean dimension style that has the specified font. + With the exception of the name, the resulting dimension style + will have an unset ON_ModelComponent properties (id, index, ...). + Parameters: + font_characteristics - [in] + If nullptr, then &ON_Font::Default is used. + model_space_text_scale - [in] + If model_space_text_scale is > 0.0, then it is used to set + the DimScale() value. + dimstyle_settings - [in] + Setting for non-font dimstyle properties. + If nullptr, then &ON_DimStyle::Default is used. + manifest - [in] + If manifest is not nullptr, then it is used to generate + a unique name. + destination - [in] + If destination is not nullptr, the result is stored here. + Otherwise operator new is used to construct an ON_DimStyle on the heap. + */ + static ON_DimStyle* CreateFromFont( + const ON_Font* font_characteristics, + double model_space_text_scale, + const ON_DimStyle* dimstyle_settings, + const class ON_ComponentManifest* manifest, + ON_DimStyle* destination + ); + +public: + // Default constructor result is identical to ON_DimStyle::Unset; + ON_DimStyle(); + + ~ON_DimStyle() = default; + ON_DimStyle(const ON_DimStyle& src) = default; + ON_DimStyle& operator=(const ON_DimStyle&) = default; + +public: + // Used when reading V5 and earlier archives + ON_DimStyle( + ON::LengthUnitSystem model_length_unit_system, + const class ON_V5x_DimStyle& src + ); + +public: + ON_DimStyle(const ON_3dmAnnotationSettings& src); + + /* + Returns: + True: + "this" and src have identical names, dimension style appearance attributes, + and identical atttributes inherited from the same parent dimension style. + ON_ModelComponent settings other than Name() and ParentId() are + not compared. + Remaraks: + A better name for this function would be EqualForAllPracticalPurposes(). + */ + bool CompareDimstyle(const ON_DimStyle& src) const; + + /* + Returns: + True if this and src have identical dimension style appearance attributes + and the same parent dimension style id. + CompareFields() ignores Name, Index, Id() values. + CompareFields() ignores differences in IsOverride(field_id) values. + Remaraks: + A better name for this function would be EqualAppearanceSettings(). + */ + bool CompareFields(const ON_DimStyle& src) const; + +private: + /* + Returns: + True: + If a.IsFieldOverride(field_id) == b.IsFieldOverride(field_id) + for all ON_DimStyle::field enum values. + */ + static bool Internal_EqualOverrideParentFields( + const ON_DimStyle& a, + const ON_DimStyle& b + ); +public: + + ////////////////////////////////////////////////////////////////////// + // + // ON_Object overrides + + // virtual + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + // virtual + void Dump(ON_TextLog&) const override; // for debugging + + // virtual + bool Write( + ON_BinaryArchive& // serialize definition to binary archive + ) const override; + + // virtual + bool Read( + ON_BinaryArchive& // restore definition from binary archive + ) override; + + ////////////////////////////////////////////////////////////////////// + // Interface + + void EmergencyDestroy(); + + ////////////////////////////////////////////////////////////////////// + // Interface + +#pragma region RH_C_SHARED_ENUM [ON_DimStyle::LengthDisplay] [Rhino.DocObjects.DimensionStyle.LengthDisplay] [nested:int] + /// + /// Dimension display length unit system and style + /// + enum class LengthDisplay : unsigned int + { + /// + /// Decimal current model units + /// + ModelUnits = 0, + + /// + /// Decimal Millimeters + /// + Millmeters = 3, + + /// + /// Decimal Centimeters + /// + Centimeters = 4, + + /// + /// Decimal Meters + /// + Meters = 5, + + /// + /// Decimal Kilometers + /// + Kilometers = 6, + + /// + /// Decimal Inches + /// + InchesDecimal = 7, + + /// + /// Fractional Inches ( 1.75 inches displays as 1-3/4 ) + /// + InchesFractional = 1, + + /// + /// Decimal Feet + /// + FeetDecimal = 8, + + /// + /// Feet and Inches ( 14.75 inches displays as 1'-2-3/4" ) + /// + FeetAndInches = 2, + + /// + /// Decimal Miles + /// + Miles = 9 + }; + +#pragma endregion + + static ON_DimStyle::LengthDisplay LengthDisplayFromUnsigned( + unsigned int length_display_as_unsigned + ); + + /* + Returns: + true if length_display selects a decimal format. + false if length_display is ON_DimStyle::LengthDisplay::FeetAndInches + or ON_DimStyle::LengthDisplay::InchesFractional. + */ + static bool LengthDisplayIsDecimal( + ON_DimStyle::LengthDisplay dimension_length_display + ); + + static ON::LengthUnitSystem LengthUnitSystemFromLengthDisplay( + ON_DimStyle::LengthDisplay dimension_length_display + ); + + +#pragma region RH_C_SHARED_ENUM [ON_DimStyle::tolerance_format] [Rhino.DocObjects.DimensionStyle.ToleranceDisplayFormat] [nested:byte] + /// + /// Style of tolerance display for dimensions + /// + enum class tolerance_format : unsigned char + { + /// + /// No tolerance display + /// + None = 0, + /// + /// Symmetrical +/- tolerance + /// + Symmetrical = 1, + /// + /// Distance +tol, -tol + /// + Deviation = 2, + /// + /// Distance upper and lower limits + /// + Limits = 3, + }; +#pragma endregion + + static ON_DimStyle::tolerance_format ToleranceFormatFromUnsigned( + unsigned int format_as_unsigned + ); + + +#pragma region RH_C_SHARED_ENUM [ON_DimStyle::ContentAngleStyle] [Rhino.DocObjects.DimensionStyle.LeaderContentAngleStyle] [nested:byte] + /// + /// Angle for text or other leader or dimension content + /// + enum class ContentAngleStyle : unsigned char + { + /// + /// Annotation text is horizontal in annotation object's plane + /// + Horizontal = 0, + /// + /// Aligned with last leader direction or dimension line + /// + Aligned = 1, + /// + /// Explicit angle + /// + Rotated = 2, + }; +#pragma endregion + + static ON_DimStyle::ContentAngleStyle ContentAngleStyleFromUnsigned( + unsigned int alignment_as_unsigned + ); + +#pragma region RH_C_SHARED_ENUM [ON_DimStyle::leader_curve_type] [Rhino.DocObjects.DimensionStyle.LeaderCurveStyle] [nested:byte] + /// + /// Type of leader curve + /// + enum class leader_curve_type : unsigned char + { + /// + /// + /// + None = 0, + /// + /// + /// + Polyline = 1, + /// + /// + /// + Spline = 2 + }; +#pragma endregion + + static ON_DimStyle::leader_curve_type LeaderCurveTypeFromUnsigned( + unsigned int type_as_unsigned + ); + +#pragma region RH_C_SHARED_ENUM [ON_DimStyle::field] [Rhino.DocObjects.DimensionStyle.Field] [nested:int] + // Don't change these enum values. They are used in file reading and writing. + /// + /// Field identifiers used for file i/o and getting/setting values + /// + enum class field : unsigned int + { + /// + Unset = 0, + + /// Dimension style Name property. Cannot be inherited from parent. + Name = 1, + + /// Dimension style runtime model component index property. Cannot be inherited from parent. + Index = 2, + + /// + ExtensionLineExtension = 3, + /// + ExtensionLineOffset = 4, + /// + Arrowsize = 5, + /// + LeaderArrowsize = 6, + /// + Centermark = 7, + /// + TextGap = 8, + /// + TextHeight = 9, + /// Linear, angular, and ordinate dimension text location above/in/below + DimTextLocation = 10, + + //OBSOLETE_LengthFormat_ = 11, + /// Text mask frame + MaskFrameType = 11, + + /// + LengthResolution = 12, + /// + AngleFormat = 13, + /// + AngleResolution = 14, + /// + Font = 15, + + /// + /// LengthFactor is a rarely used. It applies when a model is being + /// drawn to a scale and the dimension length values should be + /// reverse scaled. For example, if a model is drawn at 1/4 scale, + /// a line 5 units long indicates the real world line is 20 units + /// long. In this case setting LengthFactor to 4 would cause + /// a linear dimension applied to that line to display a value of 20. + /// + LengthFactor = 16, + + /// + Alternate = 17, + + /// + /// AlternateLengthFactor is a rarely used. See Length factor for + /// a discription of this property. + /// + AlternateLengthFactor = 18, + + //OBSOLETE_AlternateLengthFormat_ = 19, + + /// + AlternateLengthResolution = 20, + /// + Prefix = 21, + /// + Suffix = 22, + /// + AlternatePrefix = 23, + /// + AlternateSuffix = 24, + /// + DimensionLineExtension = 25, + /// + SuppressExtension1 = 26, + /// + SuppressExtension2 = 27, + /// + ExtLineColorSource = 28, + /// + DimLineColorSource = 29, + /// + ArrowColorSource = 30, + /// + TextColorSource = 31, + /// + ExtLineColor = 32, + /// + DimLineColor = 33, + /// + ArrowColor = 34, + /// + TextColor = 35, + /// + ExtLinePlotColorSource = 36, + /// + DimLinePlotColorSource = 37, + /// + ArrowPlotColorSource = 38, + /// + TextPlotColorSource = 39, + /// + ExtLinePlotColor = 40, + /// + DimLinePlotColor = 41, + /// + ArrowPlotColor = 42, + /// + TextPlotColor = 43, + /// + ExtLinePlotWeightSource = 44, + /// + DimLinePlotWeightSource = 45, + /// + ExtLinePlotWeight_mm = 46, + /// + DimLinePlotWeight_mm = 47, + /// + ToleranceFormat = 48, + /// + ToleranceResolution = 49, + /// + ToleranceUpperValue = 50, + /// + ToleranceLowerValue = 51, + /// + AltToleranceResolution = 52, + /// + ToleranceHeightScale = 53, + /// + BaselineSpacing = 54, + /// + DrawMask = 55, + /// + MaskColorSource = 56, + /// + MaskColor = 57, + /// + MaskBorder = 58, + /// + DimensionScale = 59, + /// + DimscaleSource = 60, + /// + FixedExtensionLength = 61, + /// + FixedExtensionOn = 62, + /// + TextRotation = 63, + /// + SuppressArrow1 = 64, + /// + SuppressArrow2 = 65, + /// + TextmoveLeader = 66, + /// + ArclengthSymbol = 67, + /// + StackTextheightScale = 68, + /// + StackFormat = 69, + /// + AltRound = 70, + /// + Round = 71, + /// + AngularRound = 72, + /// + AltZeroSuppress = 73, + + //OBSOLETE ToleranceZeroSuppress = 74, + + /// + AngleZeroSuppress = 75, + /// + ZeroSuppress = 76, + /// + AltBelow = 77, + /// + ArrowType1 = 78, + /// + ArrowType2 = 79, + /// + LeaderArrowType = 80, + /// + ArrowBlockId1 = 81, + /// + ArrowBlockId2 = 82, + /// + LeaderArrowBlock = 83, + /// Radial dimension text location above/in/below + DimRadialTextLocation = 84, + /// + TextVerticalAlignment = 85, + /// + LeaderTextVerticalAlignment = 86, + /// + LeaderContentAngleStyle = 87, + /// + LeaderCurveType = 88, + /// + LeaderContentAngle = 89, + /// + LeaderHasLanding = 90, + /// + LeaderLandingLength = 91, + /// + MaskFlags = 92, + /// + CentermarkStyle = 93, + /// + TextHorizontalAlignment = 94, + /// + LeaderTextHorizontalAlignment = 95, + /// + DrawForward = 96, + /// + SignedOrdinate = 97, + + /// + /// Unit system for dimension rendering sizes like TextHeight, TextGap, ArrowSize, ExtOffset, + /// and dozens of other properties that control the appearance and placement of the components + /// used to render a dimension. + /// + UnitSystem = 98, + + /// + TextMask = 99, + /// + TextOrientation = 100, + /// + LeaderTextOrientation = 101, + /// + DimTextOrientation = 102, + /// + DimRadialTextOrientation = 103, + /// + DimTextAngleStyle = 104, + /// + DimRadialTextAngleStyle = 105, + /// + TextUnderlined = 106, + + //OBSOLETE_DimensionUnitSystem_ = 107, + //OBSOLETE_AlternateDimensionUnitSystem_ = 108, + + /// + /// Dimension length display. See ON_DimStyle::DimensionLengthDisplay() for a descpription of this parameter. + /// + DimensionLengthDisplay = 109, + + /// + /// Alternate dimension length display. See ON_DimStyle::AlternateDimensionLengthDisplay() for a descpription of this parameter. + /// + AlternateDimensionLengthDisplay = 110, + + /// + /// Force dimension line to draw when text is moved outside + /// + ForceDimLine = 111, + + /// + /// Arrow position when arrows won't fit between extensions + /// + ArrowFit = 112, + + /// + /// Text position when text won't fit between extensions + /// + TextFit = 113, + + /// + /// Character to use for decimal separator in dimension text + /// + DecimalSeparator = 114, + + /// Every enum UINT value that identifies a valid dimension style property is less than the UINT value of Count. + Count = 115 + }; + +#pragma endregion + + enum : unsigned int + { + // must be 1 + the maximum value of an ON_DimStyle::field enum value. + FieldCount = (unsigned int)field::Count + }; + + static ON_DimStyle::field FieldFromUnsigned( + unsigned int field_as_unsigned + ); + + +#pragma region RH_C_SHARED_ENUM [ON_DimStyle::angle_format] [Rhino.DocObjects.DimensionStyle.AngleDisplayFormat] [nested:byte] + /// + /// Display format for angles + /// + enum class angle_format : unsigned char + { + /// Decimal Degrees + DecimalDegrees = 0, + /// Degrees Minutes Seconds + DegMinSec = 1, + /// Decimal Radians + Radians = 2, + /// Decimal Gradians + Grads = 3 + }; +#pragma endregion + + static ON_DimStyle::angle_format AngleFormatFromUnsigned( + unsigned int format_as_unsigned + ); + +#pragma region RH_C_SHARED_ENUM [ON_DimStyle::OBSOLETE_length_format] [Rhino.DocObjects.DimensionStyle.LengthDisplayFormat] [nested:byte] + /// + /// Obsolete format for length display - use ON_DimStyle::DimensionLengthDisplay instead + /// + enum class OBSOLETE_length_format : unsigned char + { + /// Obsolete - use ON_DimStyle::DimensionLengthDisplay::ModelUnits. + Decimal = 0, + + /// Obsolete - use ON_DimStyle::DimensionLengthDisplay::InchesFractional + Fractional = 1, + + /// Obsolete - use ON_DimStyle::DimensionLengthDisplay::FeetAndInches + FeetInches = 2, + + /// Obsolete - use ON_DimStyle::DimensionLengthDisplay::FeetAndInches enum. + FeetDecimalInches = 3 + }; +#pragma endregion + + + static ON_DimStyle::OBSOLETE_length_format OBSOLETE_LengthFormatFromUnsigned( + unsigned int format_as_unsigned + ); + + /* + Parameters: + dimension_length_display - [in] + model_serial_number - [in] + 0: Ignore model settings + >0: dimstyle.ModelSerialNumber() + */ + static ON_DimStyle::OBSOLETE_length_format OBSOLETE_LengthFormatFromLengthDisplay( + ON_DimStyle::LengthDisplay dimension_length_display, + unsigned int model_serial_number + ); + + static ON_DimStyle::OBSOLETE_length_format OBSOLETE_LengthFormatFromLengthDisplay( + ON_DimStyle::LengthDisplay dimension_length_display, + ON::LengthUnitSystem model_unit_system + ); + +#pragma region RH_C_SHARED_ENUM [ON_DimStyle::TextLocation] [Rhino.DocObjects.DimensionStyle.TextLocation] [nested:byte] + /// + /// The location of text in linear, angular, radial, and ordinate dimensions. + /// + enum class TextLocation : unsigned char + { + /// Text is above dimension line. + AboveDimLine = 0, + /// Text is centered in dimension line. + InDimLine = 1, + /// Text is below dimension line. + BelowDimLine = 2 + }; +#pragma endregion + + static ON_DimStyle::TextLocation TextLocationFromUnsigned( + unsigned int dim_text_location_as_unsigned + ); + + // convert ON_DimStyle::OBSOLETE_length_format enum to ON::OBSOLETE_DistanceDisplayMode enum + static ON::OBSOLETE_DistanceDisplayMode DistanceDisplayModeFromLengthFormat( + ON_DimStyle::OBSOLETE_length_format + ); + + // convert ON::OBSOLETE_DistanceDisplayMode enum to ON_DimStyle::OBSOLETE_length_format enum + static ON_DimStyle::OBSOLETE_length_format LengthFormatFromDistanceDisplayMode( + ON::OBSOLETE_DistanceDisplayMode + ); + + +#pragma region RH_C_SHARED_ENUM [ON_DimStyle::suppress_zero] [Rhino.DocObjects.DimensionStyle.ZeroSuppression] [nested:byte] + /// + /// Marks leading and trailing zeros for removal. + /// + enum class suppress_zero : unsigned char + { + /// No zero suppression. + None = 0, + /// Suppress leading zeros. + SuppressLeading = 1, + /// Suppress trailing zeros. + SuppressTrailing = 2, + /// Suppress leading and trailing zeros. + SuppressLeadingAndTrailing = 3, + /// Suppress zero feet. + SuppressZeroFeet = 4, + /// Suppress zero inches. + SuppressZeroInches = 8, + /// Suppress zero feet and zero inches. + SuppressZeroFeetAndZeroInches = 12 + }; +#pragma endregion + + static ON_DimStyle::suppress_zero ZeroSuppressFromUnsigned( + unsigned int suppress_ero_as_unsigned + ); + +#pragma region RH_C_SHARED_ENUM [ON_DimStyle::stack_format] [Rhino.DocObjects.DimensionStyle.StackDisplayFormat] [nested:byte] + /// + /// Format of stacked fractions + /// + enum class stack_format : unsigned char + { + /// No stacking + None = 0, + /// Stack with horizontal line + StackHorizontal = 1, + /// Stack with angled line + StackDiagonal = 2, + }; +#pragma endregion + + static ON_DimStyle::stack_format StackFormatFromUnsigned( + unsigned int format_as_unsigned + ); + +#pragma region RH_C_SHARED_ENUM [ON_DimStyle::centermark_style] [Rhino.DocObjects.DimensionStyle.CenterMarkStyle] [nested:byte] + /// + /// Style for drawing centermark for Radial dimensions and Centermark objects + /// + enum class centermark_style : unsigned char + { + /// + /// No centermark display + /// + None = 0, + /// + /// + mark only + /// + Mark = 1, + /// + /// + mark and lines to radius + /// + MarkAndLines = 2, + }; +#pragma endregion + + static ON_DimStyle::centermark_style CentermarkStyleFromUnsigned( + unsigned int centermark_as_unsigned + ); + + +#pragma region RH_C_SHARED_ENUM [ON_DimStyle::arrow_fit] [Rhino.DocObjects.DimensionStyle.ArrowFit] [nested:byte] + /// + /// Arrow display position inside or outside extension lines + /// + enum class arrow_fit : unsigned char + { + /// Auto - Display when space permits + Auto = 0, + /// Force arrows inside extensions + ArrowsInside = 1, + /// Force arrows outside extensions + ArrowsOutside = 2, + }; +#pragma endregion + + static ON_DimStyle::arrow_fit ArrowFitFromUnsigned( + unsigned int arrow_fit_as_unsigned + ); + +#pragma region RH_C_SHARED_ENUM [ON_DimStyle::text_fit] [Rhino.DocObjects.DimensionStyle.TextFit] [nested:byte] + /// + /// Text display position inside or outside extension lines + /// + enum class text_fit : unsigned char + { + /// Auto - Display inside when space permits + Auto = 0, + /// Force text inside extensions + TextInside = 1, + /// Force text outside to the right of extensions + TextRight = 2, + /// Force text outside to the left of extensions + TextLeft = 3, + /// Move text outside to the right of extensions when it won't fit inside + TextHintRight = 4, + /// Move text outside to the left of extensions when it won't fit inside + TextHintLeft = 5, + }; +#pragma endregion + + static ON_DimStyle::text_fit TextFitFromUnsigned( + unsigned int text_fit_as_unsigned + ); + + static ON_DimStyle::LengthDisplay LengthDisplayFromUnitsAndFormat( + ON::LengthUnitSystem units, + ON_DimStyle::OBSOLETE_length_format lengthformat + ); + + /// + /// Dimension length units and format + /// + ON_DimStyle::LengthDisplay DimensionLengthDisplay() const; + + /// + /// Set dimension length units and format + /// + ON_DimStyle::LengthDisplay AlternateDimensionLengthDisplay() const; + + /// + /// Alternate dimension length units and format + /// + void SetDimensionLengthDisplay(ON_DimStyle::LengthDisplay length_display); + + /// + /// Set alternate dimension length units and format + /// + void SetAlternateDimensionLengthDisplay(ON_DimStyle::LengthDisplay length_display); + + /// + /// Parameters: + /// model_sn - 0, a model serial number, or ON_UNSET_UINT_INDEX to + /// use the dimstyle's ModelSerialNumber() value. + /// Returns + /// Unit system for dimension length display. + /// If DimensionLengthDisplay() == ON_DimStyle::LengthDisplay::ModelUnits + /// and model_sn > 0, then the value of ON::LengthUnitSystemFromModelSerialNumber(model_sn) + /// is returned. + /// If DimensionLengthDisplay() == ON_DimStyle::LengthDisplay::ModelUnits + /// and model_sn == 0, then ON::LengthUnitSystem::None is returned. + /// + ON::LengthUnitSystem DimensionLengthDisplayUnit( + unsigned int model_sn + ) const; + + /// + /// Parameters: + /// model_sn - 0, a model serial number, or ON_UNSET_UINT_INDEX to + /// use the dimstyle's ModelSerialNumber() value. + /// Returns + /// Unit system for dimension length display. + /// If DimensionLengthDisplay() == ON_DimStyle::LengthDisplay::ModelUnits + /// and model_sn > 0, then the value of ON::LengthUnitSystemFromModelSerialNumber(model_sn) + /// is returned. + /// If DimensionLengthDisplay() == ON_DimStyle::LengthDisplay::ModelUnits + /// and model_sn == 0, then ON::LengthUnitSystem::None is returned. + /// + ON::LengthUnitSystem AlternateDimensionLengthDisplayUnit( + unsigned int model_sn + ) const; + + +private: + /* + Returns: + true if value was changed. + */ + bool Internal_SetBoolMember( + ON_DimStyle::field field_id, + bool value, + bool& class_member + ); + /* + Returns: + true if value was changed. + */ + bool Internal_SetUnsignedCharMember( + ON_DimStyle::field field_id, + unsigned char value, + unsigned char& class_member + ); + /* + Returns: + true if value was changed. + */ + bool Internal_SetIntMember( + ON_DimStyle::field field_id, + int value, + int& class_member + ); + /* + Returns: + true if value was changed. + */ + bool Internal_SetColorMember( + ON_DimStyle::field field_id, + ON_Color value, + ON_Color& class_member + ); + /* + Returns: + true if value was changed. + */ + bool Internal_SetDoubleMember( + ON_DimStyle::field field_id, + double value, + double& class_member + ); + /* + Returns: + true if value was changed. + */ + bool Internal_SetIdMember( + ON_DimStyle::field field_id, + ON_UUID value, + ON_UUID& class_member + ); + /* + Returns: + true if value was changed. + */ + bool Internal_SetStringMember( + ON_DimStyle::field field_id, + const wchar_t* value, + ON_wString& class_member + ); + + void Internal_SetOverrideDimStyleCandidateFieldOverride(ON_DimStyle::field field_id); + +public: + // Extension line extension + double ExtExtension() const; + void SetExtExtension(const double); + + // Extension line offset + double ExtOffset() const; + void SetExtOffset(const double); + + // Arrow size + double ArrowSize() const; + void SetArrowSize(const double); + + // Arrow size + double LeaderArrowSize() const; + void SetLeaderArrowSize(const double); + + // Centermark size + double CenterMark() const; + void SetCenterMark(const double); + + // Centermark style + ON_DimStyle::centermark_style CenterMarkStyle() const; + void SetCenterMarkStyle(ON_DimStyle::centermark_style style); + + // The location of text relative to the dimension line in linear, angular, and ordinate dimensions. + ON_DimStyle::TextLocation DimTextLocation() const; + void SetDimTextLocation(ON_DimStyle::TextLocation); + + // The location of text relative to the dimension line in radial dimensions. + ON_DimStyle::TextLocation DimRadialTextLocation() const; + void SetDimRadialTextLocation(ON_DimStyle::TextLocation); + + angle_format AngleFormat() const; + void SetAngleFormat(angle_format format); + + // Display resolution for distance measurements + int LengthResolution() const; + void SetLengthResolution(int); + + // Display resolution for angle measurements + int AngleResolution() const; + void SetAngleResolution(int); + +public: + /* + Description: + Set the font used to render text. + Parameters: + font_characteristics - [in] + This parameter does not have to be a managed font. + Remarks: + If the parameter is a managed font (font_characteristics.IsManagedFont() is true), + then the identical value is returned by ON_DimStyle.Font(). + If the parameter is not a managed font (font_characteristics.IsManagedFont() is false), + then the ON_Font::GetManagedFont(font_characteristics) will be returned by + ON_DimStyle.Font(). + */ + void SetFont( + const class ON_Font& font_characteristics + ); + + /* + Returns: + The managed font used to render text. + */ + const class ON_Font& Font() const; + + /* + Returns: + If a parent dimstyle is in play, this is the managed font used by the parent dimstyle. + Otherwise, this is the font returned by Font(). + */ + const class ON_Font& ParentDimStyleFont() const; + + /* + Returns: + A copy of the font_characteristics information. + Remarks: + You probably want to use Font(). This function is only useful + in isolated situations and is typically used to study font + substitutions when a model moves between computers or platforms. + */ + const class ON_Font& FontCharacteristics() const; + + /* + Returns: + True if the font returned by Font() is a substitute + for the font passed to SetFont(). + Remarks: + Font substitution can occur when a model is moved between + computers that have different fonts installed. + */ + const bool FontSubstituted() const; + +public: + /* + Description: + Two dimension styles have identical text orientation, glyph content, + and size parameters if and only if the have identical values of + TextPositionPropertiesHash(). + Returns: + A SHA-1 hash of the information that controls text position and size. + Remarks: + Independent of id, parent id, name, and index. + */ + const class ON_SHA1_Hash TextPositionPropertiesHash() const; + + /* + Description: + Two dimension styles have identical content if and only + if they have identical values of ContentHash(). + Returns: + A SHA-1 hash of the information that controls annotation appearance. + Remarks: + Independent of id, parent id, name, and index. + */ + const class ON_SHA1_Hash& ContentHash() const; + +private: + void Internal_TextPositionPropertiesChange(); + +public: + + // Distance from dimension lines to text + double TextGap() const; + void SetTextGap(double gap); + + // Height of dimension text + double TextHeight() const; + void SetTextHeight(double height); + + /* + Returns: + Width of an em space (U+2003), also called a mutton, in the same units as TextHeight() + using the current settings for TextHeight() and Font(). + */ + double TextWidthOfSpace() const; + + /* + Returns: + Width of an em space (U+2003), also called a mutton, in the same units as TextHeight() + using the current settings for TextHeight() and Font(). + */ + double TextWidthOfEmSpace() const; + + /* + Returns: + Width of an en space (U+2002), also called a nut, in the same units as TextHeight() + using the current settings for TextHeight() and Font(). + */ + double TextWidthOfEnSpace() const; + + /* + Returns: + Width of a figure space (U+2007) in the same units as TextHeight() + using the current settings for TextHeight() and Font(). + Remarks: + Typically close to the average with of a decimal digit (0123456789) and used + to line up colmns of numeric values. + */ + double TextWidthOfFigureSpace() const; + + /* + Returns: + Width of an ideographic space (U+3000) in the same units as TextHeight() + using the current settings for TextHeight() and Font(). + Remarks: + The width of ideographic (CJK) characters. + */ + double TextWidthOfIdeographicSpace() const; + + /* + Returns: + Width of a medium mathematical space (U+205F) in the same units as TextHeight() + using the current settings for TextHeight() and Font(). + */ + double TextWidthOfMediumMathematicalSpace() const; + + /* + Parameters: + unicode_code_point - [in] + Returns: + The advande for a single code point glyph in the same units as TextHeight() using the current settings + for TextHeight() and Font(). + Remarks: + When sequences of code points are rendered, using the per glyph advance does not + create the best looking text. Text rendering tools like DirectWrite that look at the + entire string adjust advance based on the locale, neighboring glyphs, and other contextual + information. + */ + double TextAdvanceOfCodePoint( + unsigned unicode_code_point + ) const; + + + /// + /// LengthFactor is a rarely used. It applies when a model is being + /// drawn to a scale and the dimension length values should be + /// reverse scaled. For example, if a model is drawn at 1/4 scale, + /// a line 5 units long indicates the real world line is 20 units + /// long. In this case setting LengthFactor to 4 would cause + /// a linear dimension applied to that line to display a value of 20. + /// + double LengthFactor() const; + + /// + /// LengthFactor is a rarely used. It applies when a model is being + /// drawn to a scale and the dimension length values should be + /// reverse scaled. For example, if a model is drawn at 1/4 scale, + /// a line 5 units long indicates the real world line is 20 units + /// long. In this case setting LengthFactor to 4 would cause + /// a linear dimension applied to that line to display a value of 20. + /// + void SetLengthFactor(double); + + // Additional measurement display toggle + bool Alternate() const; + void SetAlternate(bool); + + // Distance scale factor for alternate display + /// + /// AlternateLengthFactor is a rarely used. See Length factor for + /// a discription of this property. + /// + double AlternateLengthFactor() const; + + /// + /// AlternateLengthFactor is a rarely used. See Length factor for + /// a discription of this property. + /// + void SetAlternateLengthFactor(double); + + // Display resolution for alternate length measurements + int AlternateLengthResolution() const; + void SetAlternateLengthResolution(int); + + // Dimension prefix text + const ON_wString& Prefix() const; + void SetPrefix(const wchar_t*); + + // Dimension suffix text + const ON_wString& Suffix() const; + void SetSuffix(const wchar_t*); + + // Dimension alternate prefix text + const ON_wString& AlternatePrefix() const; + void SetAlternatePrefix(const wchar_t*); + + // Dimension alternate suffix text + const ON_wString& AlternateSuffix() const; + void SetAlternateSuffix(const wchar_t*); + + // Suppress first dimension extension line + bool SuppressExtension1() const; + void SetSuppressExtension1(bool); + + // Suppress second dimension extension line + bool SuppressExtension2() const; + void SetSuppressExtension2(bool); + + // Extension of dimension line past extension lines + double DimExtension() const; + void SetDimExtension(const double e); + + + //// Colors of Text + //ON_Color TextColor() const; + //void SetTextColor(ON_Color color); + // + // Combines a field id and a field value + // Dimensions will have an array of DimstyleField's to record + // dimension style overrides for individual dimensions + class DimstyleField + { + public: + DimstyleField() + : m_next(nullptr) + , m_field_id(ON_DimStyle::field::Unset) + { + m_val.s_val = nullptr; + } + ~DimstyleField() + { + if (nullptr != m_next) + { + delete m_next; + m_next = nullptr; + } + if (nullptr != m_val.s_val) + { + delete m_val.s_val; + m_val.s_val = nullptr; + } + } + + DimstyleField* m_next; + ON_DimStyle::field m_field_id; + union + { + bool b_val; + int i_val; + unsigned char uc_val; + double d_val; + unsigned int c_val; + const ON_wString* s_val; + } m_val; + }; + + /* + Parameters: + field_id - [in] + Returns: + false: (default) + The setting identified by field_id is inherited from the parent dimension style identified by ParentId(). + true: + The setting identified by field_id is independet of any parent dimension style. + */ + bool IsFieldOverride(ON_DimStyle::field field_id) const; + + /* + Parameters: + field_id - [in] + bOverrideParent - [in] + false: + The setting identified by field_id is inherited from the parent dimension style identified by ParentId(). + true: + The setting identified by field_id is independent of any parent dimension style. + */ + void SetFieldOverride(ON_DimStyle::field field_id, bool bOverrideParent); + + /* + Parameters: + bOverrideParent - [in] + true - if a field permits overriding, set it to true. + false - set all field override values to false. + */ + void SetFieldOverrideAll(bool bOverrideParent); + + /* + Description: + All dimension style settings identified the ON_DimStyle::field enum, + except Name and Id, are inherited from the parent dimension style. + */ + void ClearAllFieldOverrides(); + + /* + Returns: + false: (default) + Every setting identified by a ON_DimStyle::field enum value, except name and id, + is inherited from the parent dimension style identified by ParentId(). + true: + At least one setting identified by a ON_DimStyle::field enum value is + is independent of any parent dimension style. + */ + bool HasOverrides() const; + + /* + Returns: + The number of DimStyle fields that are overridden. Name, Id and Index are not counted. + */ + ON__UINT32 OverrideCount() const; + + /* + Returns: + The content hash of the parent dimstyle. If there is no parent dimstyle, then + ON_SHA1_Hash::EmptyContent is returned. + */ + const ON_SHA1_Hash& ParentContentHash() const; + + /* + Description: + Create a dimstyle from this that is configured to be customized for use + in creating a new annotation object. + Example: + ON_DimStyleContext = dim_style_context = ...; + ON_DimStyle my_dim_style = dim_style_context.CurrentDimStyle().CreateOverrideCandidate(). + // Customize my_dim_style + my_dim_style.Set...(...); + Returns: + An ON_DimStyle configured to be modified and used as an override dimstyle for annotation objects. + */ + const ON_DimStyle CreateOverrideCandidate() const; + + /* + Description: + Get an ON_DimStyle with the specified properties. + Parameters: + parent_dim_style - [in] + If you are getting ready to modify and existing annotation object, + a good options for this paramter is the dimstyle returned by ON_Annotation.DimStyle(); + If you are getting ready to create a new annotation object, then get + an ON_DimStyleContext class and pass ON_DimStyleContext.CurrentDimStyle(). + In Rhino, use CRhinoDoc.DimStyleContext() to get an ON_DimStyleContext. + In an ONX_Model, use ONX_Model.DimStyleContext() to get an ON_DimStyleContext. + In other situations, you can pass on of the system dimstyles like + ON_DimStyle::DefaultMillimeterSmall or ON_DimStyle::DefaultMillimeterArchitectural. + The worst possible choices are ON_DimStyle::Default or ON_DimStyle::Unset. + annotation_type - [in] + ON::AnnotationType::Unset if style will be used for multiple types of annotation + or a specific type. For example, if you are making a text object, pass ON::AnnotationType::Text; + if you are making a leader, pass ON::AnnotationType::Leader, and so on. + font - [in] + nullptr for current default or specify the font you want. + When in doubt, pass nullptr + model_space_text_scale - [in] + If > 0, then ON_DimStyle.DimScale() is set, otherwise current default is used. + When in doubt, pass ON_UNSET_VALUE. + text_height - [in] + text_height_unit_system - [in] + If text_height > 0, then ON_DimStyle.TextHeight() is set, otherwise current default is used. + When in doubt, pass ON_UNSET_VALUE. + valign - [in] + halign - [in] + valign and halign control placement of text in text objects and leaders. + The value of the annotation_type parameter determines which objects use the + valign and halign settings. + text_orientation - [in] + dim_text_location - [in] + Controls placement of text in linear, angular, radial and ordinate dimensions. + When in doubt, pass parent_dim_style.DimTextLocation(). + Returns: + A dimstyle with the specified text properties. + Remarks: + This is a useful tool for creating the dimension style parameters to + CRhinoDoc.AddTextObject() and CRhinoDoc.AddLeaderObject(). + */ + static const ON_DimStyle CreateFromProperties( + const ON_DimStyle& parent_dim_style, + ON::AnnotationType annotation_type, + const ON_Font* font, + double model_space_text_scale, + double text_height, + ON::LengthUnitSystem text_height_unit_system, + ON::TextVerticalAlignment valign, + ON::TextHorizontalAlignment halign + ); + + static const ON_DimStyle CreateFromProperties( + const ON_DimStyle& parent_dim_style, + ON::AnnotationType annotation_type, + const ON_Font* font, + double model_space_text_scale, + double text_height, + ON::LengthUnitSystem text_height_unit_system, + ON::TextVerticalAlignment valign, + ON::TextHorizontalAlignment halign, + ON::TextOrientation orientation, + ON_DimStyle::TextLocation dim_text_location + ); + + static const ON_DimStyle CreateFromProperties( + const ON_DimStyle& parent_dim_style, + ON::AnnotationType annotation_type, + const ON_Font* font, + double model_space_text_scale, + double text_height, + ON::LengthUnitSystem text_height_unit_system + ); + +private: + static void Internal_CreateFromProperties( + const ON_DimStyle& parent_dim_style, + ON::AnnotationType annotation_type, + const ON_Font* font, + double model_space_text_scale, + double text_height, + ON::LengthUnitSystem text_height_unit_system, + bool bSetAlignment, + ON::TextVerticalAlignment valign, + ON::TextHorizontalAlignment halign, + bool bSetOrientation, + ON::TextOrientation orientation, + bool bSetLocation, + ON_DimStyle::TextLocation dim_text_location, + ON_DimStyle& destination + ); +public: + + /* + + */ + bool IsOverrideDimStyleCandidate( + ON_UUID parent_id, + bool bRequireSetOverrides, + ON_wString* error_description = nullptr + ) const; + + + /* + Description: + For every dimension style property identified by a field_id ON_DimStyle::field enum, + except Name and Index, do the following: + + if ( source.IsFieldOverride(field_id) ) + copy corresponding value from source to this + else + copy corresponding value from parent to this + + Set this->ParentId() = parent.Id(). + Parameters: + src - [in] + It is permitted for src to be this. + parent - [in] + It is permitted for parent to be this. + */ + void OverrideFields( + const ON_DimStyle& source, + const ON_DimStyle& parent + ); + + /* + Description: + For every dimension style property identified by a field_id ON_DimStyle::field enum, + except Name and Index, if source and parent have different values, then + set the field overide for that property to true. + Parameters: + src - [in] + It is permitted for src to be this. + parent - [in] + It is permitted for parent to be this. + */ + void OverrideFieldsWithDifferentValues( + const ON_DimStyle& source, + const ON_DimStyle& parent + ); + + /* + Descripton: + Set the parent dimension style id to parent.Id() and copies + all inherited appearance properties from parent. + Parameters: + parent - [in] + If this->IsFieldOverride(field_id) is false, then the dimension style + property value corresponding to field_id is copied from parent to "this". + Remarks: + Identical to calling this->OverrideFields(*this,parent). + */ + void InheritFields(const ON_DimStyle& parent); + + // Test if this dimstyle is the child of any other dimstyle + bool IsChildDimstyle() const; + + /* + Returns: + True if parent_id is not nil and parent_id == this->ParentId(). + */ + bool IsChildOf(const ON_UUID& parent_id) const; + + tolerance_format ToleranceFormat() const; + int ToleranceResolution() const; + double ToleranceUpperValue() const; + double ToleranceLowerValue() const; + double ToleranceHeightScale() const; + + void SetToleranceFormat(ON_DimStyle::tolerance_format format); + void SetToleranceResolution(int resolution); + void SetToleranceUpperValue(double upper_value); + void SetToleranceLowerValue(double lower_value); + void SetToleranceHeightScale(double scale); + + double BaselineSpacing() const; + void SetBaselineSpacing(double spacing); + + // Determines whether or not to draw a Text Mask + bool DrawTextMask() const; + void SetDrawTextMask(bool bDraw); + + // Determines where to get the color to draw a Text Mask + ON_TextMask::MaskType MaskFillType() const; + void SetMaskFillType(ON_TextMask::MaskType source); + + // Determines whether to draw a frame around a Text Mask + ON_TextMask::MaskFrame MaskFrameType() const; + void SetMaskFrameType(ON_TextMask::MaskFrame source); + + ON_Color MaskColor() const; // Only works right if MaskColorSource returns 1. + // Does not return viewport background color + void SetMaskColor(ON_Color color); + + // Offset for the border around text to the rectangle used to draw the mask + // This number is the offset on each side of the tight rectangle around the + // text characters to the mask rectangle. + double MaskBorder() const; + void SetMaskBorder(double offset); + + // The ON_TextMask class contains the property values for + // DrawTextMask() + // MaskColor() + // MaskFillType() + // MaskBorder() + // Use the + // SetDrawTextMask() + // SetMaskColor() + // SetMaskFillType() + // SetMaskBorder() + // functions to modify text mask properties. + const ON_TextMask& TextMask() const; + void SetTextMask(const ON_TextMask& text_mask); + +private: + void Internal_SetTextMask( + const ON_TextMask& text_mask + ); +public: + + void Scale(double scale); + + // UUID of the dimstyle this was originally copied from + // so Restore Defaults has some place to look + void SetSourceDimstyle(ON_UUID source_uuid); + ON_UUID SourceDimstyle() const; + + void SetExtensionLineColorSource(const ON::object_color_source src); + ON::object_color_source ExtensionLineColorSource() const; + void SetDimensionLineColorSource(const ON::object_color_source src); + ON::object_color_source DimensionLineColorSource() const; + void SetArrowColorSource(const ON::object_color_source src); + ON::object_color_source ArrowColorSource() const; + void SetTextColorSource(const ON::object_color_source src); + ON::object_color_source TextColorSource() const; + void SetExtensionLineColor(ON_Color c); + ON_Color ExtensionLineColor() const; + void SetDimensionLineColor(ON_Color c); + ON_Color DimensionLineColor() const; + void SetArrowColor(ON_Color c); + ON_Color ArrowColor() const; + void SetTextColor(ON_Color c); + ON_Color TextColor() const; + + void SetExtensionLinePlotColorSource(const ON::plot_color_source src); + ON::plot_color_source ExtensionLinePlotColorSource() const; + void SetDimensionLinePlotColorSource(const ON::plot_color_source src); + ON::plot_color_source DimensionLinePlotColorSource() const; + void SetArrowPlotColorSource(const ON::plot_color_source src); + ON::plot_color_source ArrowPlotColorSource() const; + void SetTextPlotColorSource(const ON::object_color_source src); + ON::object_color_source TextPlotColorSource() const; + void SetExtensionLinePlotColor(ON_Color c); + ON_Color ExtensionLinePlotColor() const; + void SetDimensionLinePlotColor(ON_Color c); + ON_Color DimensionLinePlotColor() const; + void SetArrowPlotColor(ON_Color c); + ON_Color ArrowPlotColor() const; + void SetTextPlotColor(ON_Color c); + ON_Color TextPlotColor() const; + + void SetExtensionLinePlotWeightSource(const ON::plot_weight_source src); + ON::plot_weight_source ExtensionLinePlotWeightSource() const; + void SetDimensionLinePlotWeightSource(const ON::plot_weight_source src); + ON::plot_weight_source DimensionLinePlotWeightSource() const; + void SetExtensionLinePlotWeight(double w); + double ExtensionLinePlotWeight() const; + void SetDimensionLinePlotWeight(double w); + double DimensionLinePlotWeight() const; + + void SetFixedExtensionLen(double l); + double FixedExtensionLen() const; + void SetFixedExtensionLenOn(bool on); + bool FixedExtensionLenOn() const; + + void SetTextRotation(double r); + double TextRotation() const; + + void SetAlternateToleranceResolution(int r); + int AlternateToleranceResolution() const; + + void SetSuppressArrow1(bool s); + bool SuppressArrow1() const; + void SetSuppressArrow2(bool s); + bool SuppressArrow2() const; + void SetTextMoveLeader(int m); + + int TextMoveLeader() const; + void SetArcLengthSymbol(int m); + int ArcLengthSymbol() const; + + void SetStackFractionFormat(ON_DimStyle::stack_format f); + ON_DimStyle::stack_format StackFractionFormat() const; + void SetStackHeightScale(double f); + double StackHeightScale() const; + + void SetRoundOff(double r); + double RoundOff() const; + void SetAlternateRoundOff(double r); + double AlternateRoundOff() const; + void SetAngleRoundOff(double r); + double AngleRoundOff() const; + void SetZeroSuppress(ON_DimStyle::suppress_zero s); + ON_DimStyle::suppress_zero ZeroSuppress() const; + void SetAlternateZeroSuppress(ON_DimStyle::suppress_zero s); + ON_DimStyle::suppress_zero AlternateZeroSuppress() const; + + // OBSOLETE - The ZeroSuppress() or AlternateZeroSuppress() property + // is used to format tolerance display. ToleranceZeroSuppress() is ignored. + void SetToleranceZeroSuppress(ON_DimStyle::suppress_zero s); + + // OBSOLETE - The ZeroSuppress() or AlternateZeroSuppress() property + // is used to format tolerance display. ToleranceZeroSuppress() is ignored. + ON_DimStyle::suppress_zero ToleranceZeroSuppress() const; + + void SetAngleZeroSuppress(ON_DimStyle::suppress_zero s); + ON_DimStyle::suppress_zero AngleZeroSuppress() const; + void SetAlternateBelow(bool below); + + /* + Description: + The valid choices for ON_DimStyle::suppress_zero depend on + the dimension length display. + Parameters: + zero_suppress - [in] + length_display - [in] + Returns: + True if zero_suppression is a valid setting when + DimensionLengthDiplay = dimension_length_display + Remarks: + LengthDisplay: Inch fractional – No zero suppression matches + LengthDisplay : FeetAndInches – Zero suppress can be + None, + Suppress zero feet, + Suppress zero inches or + Suppress zero feet and zero inches. + LengthDisplay : ModelUnits or any Decimal mode – Zero suppress can be + None, + Suppress leading, + Suppress trailing or + Suppress leading and trailing. + */ + static bool ZeroSuppressMatchesLengthDisplay( + ON_DimStyle::suppress_zero zero_suppress, + ON_DimStyle::LengthDisplay length_display); + + bool AlternateBelow() const; + + ON_Arrowhead::arrow_type ArrowType1() const; + void SetArrowType1(ON_Arrowhead::arrow_type); + ON_Arrowhead::arrow_type ArrowType2() const; + void SetArrowType2(ON_Arrowhead::arrow_type); + void SetArrowType1And2(ON_Arrowhead::arrow_type); + ON_Arrowhead::arrow_type LeaderArrowType() const; + void SetLeaderArrowType(ON_Arrowhead::arrow_type); + + void SetArrowBlockId1(ON_UUID id); + ON_UUID ArrowBlockId1() const; + void SetArrowBlockId2(ON_UUID id); + ON_UUID ArrowBlockId2() const; + void SetLeaderArrowBlockId(ON_UUID id); + ON_UUID LeaderArrowBlockId() const; + + ON::TextVerticalAlignment TextVerticalAlignment() const; + void SetTextVerticalAlignment(ON::TextVerticalAlignment style); + ON::TextVerticalAlignment LeaderTextVerticalAlignment() const; // was attachstyle + void SetLeaderTextVerticalAlignment(ON::TextVerticalAlignment style); + ON_DimStyle::ContentAngleStyle LeaderContentAngleStyle() const; // was contentalignment + void SetLeaderContentAngleStyle(ON_DimStyle::ContentAngleStyle style); + ON_DimStyle::leader_curve_type LeaderCurveType() const; + void SetLeaderCurveType(ON_DimStyle::leader_curve_type type); + bool LeaderHasLanding() const; + void SetLeaderHasLanding(bool landing); + double LeaderLandingLength() const; + void SetLeaderLandingLength(double length); + double LeaderContentAngleRadians() const; + void SetLeaderContentAngleRadians(double angle_radians); + double LeaderContentAngleDegrees() const; + void SetLeaderContentAngleDegrees(double angle_degrees); + ON::TextHorizontalAlignment TextHorizontalAlignment() const; + void SetTextHorizontalAlignment(ON::TextHorizontalAlignment halign); + ON::TextHorizontalAlignment LeaderTextHorizontalAlignment() const; + void SetLeaderTextHorizontalAlignment(ON::TextHorizontalAlignment halign); + bool DrawForward() const; + void SetDrawForward(bool drawforward); + bool SignedOrdinate() const; + void SetSignedOrdinate(bool allowsigned); + + /// + /// NOTE WELL: A dimstyle unit system was added in V6, but has never been fully used. + /// The idea was this would make it easier to figure out what text height/ arrow size, + /// ... actually meant. Especially in situations where model space and page space have + /// different unit systems, and in more complex cases like text in instance definitions + /// and inserting annotation from models with mismatched unit systems. + /// It is used internally to get some scales properly set and use in limited + /// merging contexts. + /// + /// From a user's perspective, in Rhino 6 and Rhino 7 ON_DimStyle lengths like TextHeight(), ArrowSize(), ... + /// are with respect to the context the annotation resides in. For example, if TextHeight() = 3.5, + /// model units = meters, page units = millimters, and DimScale() = 1, then + /// text created in model space will be 3.5 meters high and + /// text created in page space will be 3.5 millimeters high. + /// + /// Ideally, ON_DimStyle::UnitSystem() would specify the text height units + /// and ON_DimStyle::DimScale() cound be adjusted as model space extents require. + /// Text in instance definitions would have a well defined height and references + /// to those instance defintions would display predictably in both model space and page space. + /// + ON::LengthUnitSystem UnitSystem() const; + + /// + /// NOTE WELL: A dimstyle unit system was added in V6, but has never been fully used. + /// The idea was this would make it easier to figure out what text height/ arrow size, + /// ... actually meant. Especially in situations where model space and page space have + /// different unit systems, and in more complex cases like text in instance definitions + /// and inserting annotation from models with mismatched unit systems. + /// It is used internally to get some scales properly set and use in limited + /// merging contexts. + /// + /// From a user's perspective, in Rhino 6 and Rhino 7 ON_DimStyle lengths like TextHeight(), ArrowSize(), ... + /// are with respect to the context the annotation resides in. For example, if TextHeight() = 3.5, + /// model units = meters, page units = millimters, and DimScale() = 1, then + /// text created in model space will be 3.5 meters high and + /// text created in page space will be 3.5 millimeters high. + /// + /// Ideally, ON_DimStyle::UnitSystem() would specify the text height units + /// and ON_DimStyle::DimScale() cound be adjusted as model space extents require. + /// Text in instance definitions would have a well defined height and references + /// to those instance defintions would display predictably in both model space and page space. + /// + void SetUnitSystem(ON::LengthUnitSystem us); + + /* + Description: + When a dimension style unit system is not set, + this function examines the context the dimension style is + being used in and sets the unit system. + Ideally, both source_unit_system and destination_unit_system are page space units. + Less ideally, both source_unit_system and destination_unit_system are model space units. + Parameters: + bUseName - [in] + Consider the name when assinging a unit system. + For example, a dimension style name "Millimters Small" would + be assinged a unit system of millimeters. + source_unit_system - [in] + unit system in the context where the dimension style originated. + destination_unit_system - [in] + unit system in the context where the dimension style will be used. + */ + void SetUnitSystemFromContext( + bool bUseName, + ON::LengthUnitSystem source_unit_system, + ON::LengthUnitSystem destination_unit_system + ); + + /* + /// NOTE WELL: A dimstyle unit system was added in V6, but has never been fully used. + /// The idea was this would make it easier to figure out what text height/ arrow size, + /// ... actually meant. Especially in situations where model space and page space have + /// different unit systems, and in more complex cases like text in instance definitions + /// and inserting annotation from models with mismatched unit systems. + /// It is used internally to get some scales properly set and use in limited + /// merging contexts. + /// + /// From a user's perspective, in Rhino 6 and Rhino 7 ON_DimStyle lengths like TextHeight(), ArrowSize(), ... + /// are with respect to the context the annotation resides in. For example, if TextHeight() = 3.5, + /// model units = meters, page units = millimters, and DimScale() = 1, then + /// text created in model space will be 3.5 meters high and + /// text created in page space will be 3.5 millimeters high. + /// + /// Ideally, ON_DimStyle::UnitSystem() would specify the text height units + /// and ON_DimStyle::DimScale() cound be adjusted as model space extents require. + /// Text in instance definitions would have a well defined height and references + /// to those instance defintions would display predictably in both model space and page space. + Returns: + true if the unit system is set to an explicit valid length unit. + */ + bool UnitSystemIsSet() const; + + const ON_ScaleValue& ScaleValue() const; + void SetDimScale(ON_ScaleValue sv); + void SetDimScale(double left_val, ON::LengthUnitSystem left_us, double right_val, ON::LengthUnitSystem right_us); + + double ScaleLeftLength_mm() const; + double ScaleRightLength_mm() const; + + void SetDimScale(double scale); + double DimScale() const; + + void SetDimScaleSource(int source); + int DimScaleSource() const; // 0: Global DimScale, 1: DimStyle DimScale + + void SetTextOrientation(ON::TextOrientation); + ON::TextOrientation TextOrientation() const; + + void SetLeaderTextOrientation(ON::TextOrientation); + ON::TextOrientation LeaderTextOrientation() const; + + void SetDimTextOrientation(ON::TextOrientation); + ON::TextOrientation DimTextOrientation() const; + + void SetDimRadialTextOrientation(ON::TextOrientation); + ON::TextOrientation DimRadialTextOrientation() const; + + ON_DimStyle::ContentAngleStyle DimTextAngleStyle() const; + void SetDimTextAngleStyle(ON_DimStyle::ContentAngleStyle style); + + ON_DimStyle::ContentAngleStyle DimRadialTextAngleStyle() const; + void SetDimRadialTextAngleStyle(ON_DimStyle::ContentAngleStyle style); + + bool TextUnderlined() const; + void SetTextUnderlined(bool underlined); + + bool ForceDimLine() const; + void SetForceDimLine(bool forcedimline); + + void SetArrowFit(ON_DimStyle::arrow_fit arrowfit); + ON_DimStyle::arrow_fit ArrowFit() const; + + void SetTextFit(ON_DimStyle::text_fit textfit); + ON_DimStyle::text_fit TextFit() const; + + void SetDecimalSeparator(wchar_t separator); + wchar_t DecimalSeparator() const; + + //double ModelSize() const; + //void SetModelSize(double size); + //double PaperSize() const; + //void SetPaperSize(double size); + + // For converting to and from V5 Dimstyles + static int V5ArrowType(ON_Arrowhead::arrow_type v6type); + static int V5LengthFormat(ON_DimStyle::OBSOLETE_length_format v6format); + static int V5AngleFormat(ON_DimStyle::angle_format v6format); + static int V5ToleranceFormat(ON_DimStyle::tolerance_format v6format); + static int V5MaskColorSourceFromV6MaskType(ON_TextMask::MaskType mask_type); + static ON_Arrowhead::arrow_type V6ArrowType(int v5type); + static ON_DimStyle::OBSOLETE_length_format V6LengthFormat(int v5format); + static ON_DimStyle::angle_format V6AngleFormat(int v5format); + static ON_DimStyle::tolerance_format V6ToleranceFormat(int v5format); + static ON_TextMask::MaskType V6MaskTypeFromV5MaskColorSource(int v5_mask_color_source); + +private: + double m_extextension = 0.5; // extension line extension + double m_extoffset = 0.5; // extension line offset + double m_arrowsize = 1.0; // length of an arrow - may mean different things to different arrows + double m_leaderarrowsize = 1.0; // length of an arrow for leader style dimensions + double m_centermark = 0.5; // size of the + at circle centers + ON_DimStyle::centermark_style m_centermark_style = ON_DimStyle::centermark_style::Mark; // Display style for centermarks + double m_textgap = 0.25; // gap around the text for clipping dim line + double m_textheight = 1.0; // model unit height of dimension text before applying dimscale + + //ON::OBSOLETE_V5_TextDisplayMode m_REMOVE_ME_dimstyle_textalign = ON::OBSOLETE_V5_TextDisplayMode::kAboveLine; + ON_DimStyle::TextLocation m_dim_text_location = ON_DimStyle::TextLocation::AboveDimLine; + ON_DimStyle::TextLocation m_dimradial_text_location = ON_DimStyle::TextLocation::InDimLine; + + ON_DimStyle::angle_format m_angleformat = ON_DimStyle::angle_format::DecimalDegrees; + int m_angleresolution = 2; // for decimal degrees, digits past decimal + + /// + /// The DimensionLengthDisplay is property controls the unit system and format + /// of for display of lengths in dimensions. For more information, see the + /// descriptions of the ON_DimStyle::LengthDisplay enum values. + /// + ON_DimStyle::LengthDisplay m_dimension_length_display = ON_DimStyle::LengthDisplay::ModelUnits; + + /// + /// Alternate DimensionLengthDisplay property. + /// See the description of m_dimension_length_display for more information about this property. + /// + ON_DimStyle::LengthDisplay m_alternate_dimension_length_display = ON_DimStyle::LengthDisplay::ModelUnits; + + /// + /// The LengthResolution property controls the precision of dimension length display. + /// + /// DECIMAL LENGHT DISPLAY: + /// If m_dimension_length_display is any of the ON_DimStyle::LengthDisplay decimal formats, + /// then m_lengthresolution is the number of digits after the decimal point. + /// For example, if m_lengthresolution is 2, then dimension length display will be n.ff + /// If m_lengthresolution=7, then dimension length display will be n.fffffff. + /// + /// FRACTONAL LENGHT DISPLAY: + /// If m_dimension_length_display is ON_DimStyle::LengthDisplay::InchesFractional or + /// ON_DimStyle::LengthDisplay::FeetAndInches, then fractional length display is used. + /// In this case any fractional part will be rouded to the closest multiple + /// of 1/(2^m_alternate_lengthresolution). + /// Examples: If fractional length display is used and m_lengthresolution=2, + // then the possible fractions are 1/4, 1/2(=2/4), 3/4. + /// If fractional length display is used and m_lengthresolution=7, + // then any fractional part is rounded to the closest multipl of 1/128 (128=2^7). + /// + int m_lengthresolution = 2; + + /// + /// Alternate LengthResolution property. + /// See the description of m_lengthresolution for more information about this property. + /// + int m_alternate_lengthresolution = 2; + + /// + /// The LengthFactor is property a rarely used. It applies when a model is being + /// drawn to a scale and the dimension length values should be + /// reverse scaled. For example, if a model is drawn at 1/4 scale, + /// a line 5 units long indicates the real world line is 20 units + /// long. In this case setting LengthFactor to 4 would cause + /// a linear dimension applied to that line to display a value of 20. + /// Use the DimensionLengthDisplay property to control length unit system scaling. + /// + double m_lengthfactor = 1.0; // (dimlfac) model units multiplier for length display + + /// + /// Alternate LengthFactor property. + /// See the description of m_lengthfactor for more information about this property. + /// + double m_alternate_lengthfactor = 1.0; // (dimaltf) model units multiplier for alternate length display + + +private: + // A copy of the font_characteristics passed to SetFont. + // This information is saved in 3dm archives. + ON_Font m_font_characteristics = ON_Font::Default; + + // The managed font returned by ON_Font::GetManagedFont(m_font). + // This is the value returned by ON_DimStyle.Font(). + const ON_Font* m_managed_font = &ON_Font::Default; + +private: + // all dim style content + mutable ON_SHA1_Hash m_content_hash = ON_SHA1_Hash::EmptyContentHash; + + // text position properties content + mutable ON_SHA1_Hash m_text_position_properties_hash = ON_SHA1_Hash::EmptyContentHash; + + mutable ON_SHA1_Hash m_reserved_hash2 = ON_SHA1_Hash::EmptyContentHash; + + // parent dim style content + // All code should use ParentContentHash() to inspect this value. + // Is is set by OverrideFields(). It may be cleared by a call to ParentContentHash(). + mutable ON_SHA1_Hash m_parent_dim_style_content_hash = ON_SHA1_Hash::EmptyContentHash; + +private: + + + bool m_bAlternate = false; // (dimalt) display alternate dimension string (or not) + + bool m_bForceDimLine = true; // 4/30/2019 + ON_DimStyle::arrow_fit m_ArrowFit = ON_DimStyle::arrow_fit::Auto; // 4/30/2019 + ON_DimStyle::text_fit m_TextFit = ON_DimStyle::text_fit::Auto; // 4/30/2019 + wchar_t m_decimal_separator = ON_wString::DecimalAsPeriod; + + ON_wString m_prefix; // string preceding dimension value string + ON_wString m_suffix; // string following dimension value string + ON_wString m_alternate_prefix; // string preceding alternate value string (Default = " [") + ON_wString m_alternate_suffix; // string following alternate value string (Default = "]") + + double m_dimextension = 0.0; // (dimdle) dimension line extension past the "tip" location + + bool m_bSuppressExtension1 = false; // flag to not draw extension lines + bool m_bSuppressExtension2 = false; // flag to not draw extension lines + bool m_bReserved1 = false; + bool m_bReserved2 = false; + + // m_field_override_count + // number of ON_DimStyle::field settings that are independent of the parent dimension style. + // (not inherited from) + // A value of 0 indicates every possible setting is inherited from the parent dimension style. + // A value > 0 indicates at least one setting is independent of the parent dimension style. + ON__UINT32 m_field_override_parent_count = 0; + + // m_field_override_bitsN (Up to 128 true/false) values. + // Each ON_DimStyle::field enum value > ON_DimStyle::field::Unset and < ON_DimStyle::field::Count + // has a corresponding bit in on of the m_field_override_bitsN values. + // When the bit is clear (0), the corresponding override parent setting value = false and + // that setting is inheritied from the parent dimension style. 0 is the default setting. + // When the bit is set (1), the corresponding override parent setting value = true and + // that setting is independent of the parent dimension style. + ON__UINT32 m_field_override_parent_bits0 = 0; + ON__UINT32 m_field_override_parent_bits1 = 0; + ON__UINT32 m_field_override_parent_bits2 = 0; + ON__UINT32 m_field_override_parent_bits3 = 0; + // Please do not replace this bitfield with an array of bools. + // Using bools approach will change the size of this class when additional dimension style + // settings are added and makes construction code more complicated. + + + /* + Parameters: + mask - [out] + 0: field_id is not valid + (Unset, Name, Index, >= Count) + Name and Index settings cannot be inherited from the parent dimension style + not 0: + mask identifies the bit in the + mask - [out] + 0: field_id is not valid + (Unset, Name, Index, >= Count) + Name and Index settings cannot be inherited from the parent dimension style + not 0: + mask identifies the bit in the + Returns: + nullptr: + field_id is not valid + (Unset, Name, Index, >= Count) + Name and Index settings cannot be inherited from the parent dimension style. + not nullptr: + Address of the m_field_override_bitsN member that mask applies to. + */ + ON__UINT32* Internal_GetOverrideParentBit(ON_DimStyle::field field_id, ON__UINT32* mask) const; + + ON_DimStyle::tolerance_format m_tolerance_format = ON_DimStyle::tolerance_format::None; + int m_tolerance_resolution = 4; + double m_tolerance_upper_value = 0.0; // or both upper and lower in symmetrical style + double m_tolerance_lower_value = 0.0; + double m_tolerance_height_scale = 0.7; // relative to the main dimension text + + double m_baseline_spacing = 3.0; + + ON_TextMask m_text_mask = ON_TextMask::None; + + // m_dimscale replaced by m_scale_value.RightToLeftScale() + //double m_dimscale = 1.0; + int m_dimscale_source = 0; + + // Uuid of source dimstyle to restore defaults + ON_UUID m_source_dimstyle = ON_nil_uuid; + + // Sub-object draw colors + unsigned char m_ext_line_color_source = 0; + unsigned char m_dim_line_color_source = 0; + unsigned char m_arrow_color_source = 0; + unsigned char m_text_color_source = 0; + ON_Color m_ext_line_color = ON_Color::Black; + ON_Color m_dim_line_color = ON_Color::Black; + ON_Color m_arrow_color = ON_Color::Black; + ON_Color m_text_color = ON_Color::Black; + unsigned char m_ext_line_plot_color_source = 0; + unsigned char m_dim_line_plot_color_source = 0; + unsigned char m_arrow_plot_color_source = 0; + unsigned char m_text_plot_color_source = 0; + ON_Color m_ext_line_plot_color = ON_Color::Black; + ON_Color m_dim_line_plot_color = ON_Color::Black; + ON_Color m_arrow_plot_color = ON_Color::Black; + ON_Color m_text_plot_color = ON_Color::Black; + unsigned char m_ext_line_plot_weight_source = 0; + unsigned char m_dim_line_plot_weight_source = 0; + double m_ext_line_plot_weight_mm = 0.0; + double m_dim_line_plot_weight_mm = 0.0; + + double m_fixed_extension_len = 1.0; // Fixed extension line length if m_fixed_extension_len_on is true + bool m_fixed_extension_len_on = false; // true: use fixed_extension_len, false: don't use m_fixed_extension_len + + unsigned char m_ReservedChar1 = 0; + unsigned short m_ReservedShort1 = 0; + unsigned int m_ReservedInt1 = 0; + + double m_text_rotation = 0.0; // Dimension text rotation around text point (radians) + int m_alternate_tolerance_resolution = 4; // for decimal, digits past the decimal point, fractions: 1/2^n + double m_tol_textheight_fraction = 0.6; // fraction of main text height + + bool m_suppress_arrow1 = false; // false: dont suppress, true: suppress + bool m_suppress_arrow2 = false; // false: dont suppress, true: suppress + + unsigned short m_ReservedShort2 = 0; + + int m_textmove_leader = 0; // 0: move text anywhere, 1: add leader when moving text + int m_arclength_sym = 0; // 0: symbol before dim text, 1: symbol above dim text, no symbol + double m_stack_textheight_fraction = 0.7; // fraction of main text height + ON_DimStyle::stack_format m_stack_format = ON_DimStyle::stack_format::StackHorizontal; + double m_alt_round = 0.0; // rounds to nearest specified value + double m_round = 0.0; + double m_angular_round = 0.0; + + ON_DimStyle::suppress_zero m_zero_suppress = ON_DimStyle::suppress_zero::None; + ON_DimStyle::suppress_zero m_alt_zero_suppress = ON_DimStyle::suppress_zero::None; + + ON_DimStyle::suppress_zero m_ang_zero_suppress = ON_DimStyle::suppress_zero::None; + + bool m_alt_below = false; // true: display alternate text below main text + + // false: display alternate text after main text + ON_Arrowhead::arrow_type m_arrow_type_1 = ON_Arrowhead::arrow_type::SolidTriangle; // Arrow types for ON_Dimension derived dimensions + ON_Arrowhead::arrow_type m_arrow_type_2 = ON_Arrowhead::arrow_type::SolidTriangle; + ON_Arrowhead::arrow_type m_leader_arrow_type = ON_Arrowhead::arrow_type::SolidTriangle; + ON_UUID m_arrow_block_id_1 = ON_nil_uuid; + ON_UUID m_arrow_block_id_2 = ON_nil_uuid; + ON_UUID m_leader_arrow_block_id = ON_nil_uuid; + + // Text + ON::TextVerticalAlignment m_text_vertical_alignment = ON::TextVerticalAlignment::Top; + ON::TextHorizontalAlignment m_text_horizontal_alignment = ON::TextHorizontalAlignment::Left; + + // Leader + ON::TextVerticalAlignment m_leader_text_vertical_alignment = ON::TextVerticalAlignment::Middle; + ON::TextHorizontalAlignment m_leader_text_horizontal_alignment = ON::TextHorizontalAlignment::Left; + + ON_DimStyle::ContentAngleStyle m_leader_content_angle_style = ON_DimStyle::ContentAngleStyle::Horizontal; + ON_DimStyle::leader_curve_type m_leader_curve_type = ON_DimStyle::leader_curve_type::Polyline; + double m_leader_content_angle = 0.0; + bool m_leader_has_landing = true; + + double m_leader_landing_length = 1.0; + + bool m_draw_forward = true; + bool m_signed_ordinate = true; + + ON_ScaleValue m_scale_value = ON_ScaleValue::OneToOne; + + /// NOTE WELL: A dimstyle unit system was added in V6, but has never been fully used. + /// The idea was this would make it easier to figure out what text height/ arrow size, + /// ... actually meant. Especially in situations where model space and page space have + /// different unit systems, and in more complex cases like text in instance definitions + /// and inserting annotation from models with mismatched unit systems. + /// It is used internally to get some scales properly set and use in limited + /// merging contexts. + /// + /// From a user's perspective, in Rhino 6 and Rhino 7 ON_DimStyle lengths like TextHeight(), ArrowSize(), ... + /// are with respect to the context the annotation resides in. For example, if TextHeight() = 3.5, + /// model units = meters, page units = millimters, and DimScale() = 1, then + /// text created in model space will be 3.5 meters high and + /// text created in page space will be 3.5 millimeters high. + /// + /// Ideally, ON_DimStyle::UnitSystem() would specify the text height units + /// and ON_DimStyle::DimScale() cound be adjusted as model space extents require. + /// Text in instance definitions would have a well defined height and references + /// to those instance defintions would display predictably in both model space and page space. + ON::LengthUnitSystem m_dimstyle_unitsystem = ON::LengthUnitSystem::None; + + ON::TextOrientation m_text_orientation = ON::TextOrientation::InPlane; + ON::TextOrientation m_leader_text_orientation = ON::TextOrientation::InPlane; + ON::TextOrientation m_dim_text_orientation = ON::TextOrientation::InPlane; + ON::TextOrientation m_dimradial_text_orientation = ON::TextOrientation::InPlane; + + ON_DimStyle::ContentAngleStyle m_dim_text_angle_style = ON_DimStyle::ContentAngleStyle::Aligned; + ON_DimStyle::ContentAngleStyle m_dimradial_text_angle_style = ON_DimStyle::ContentAngleStyle::Horizontal; + + bool m_text_underlined = false; // extra/extended line under text block in leaders and radial dimensions + +private: + // The parent dimstyle's managed font. + // Use the ParentDimStyleFont() member function to query this field. + // + const ON_Font* m_parent_dimstyle_managed_font = nullptr; + +private: + void Internal_ContentChange() const; +}; + + +/* +Description: + A general and portable interface to access a model's available dimension styles. +Remarks: + The Rhino C++ SDK function CRhinoDoc.DimStyleContext() will return an ON_DimStyleContext for the Rhino model. + The ONX_Model function ONX_Model.DimStyleContext() will return an ON_DimStyleContext for ONX_Model model. +*/ +class ON_CLASS ON_DimStyleContext +{ +public: + ON_DimStyleContext() = default; + virtual ~ON_DimStyleContext(); + ON_DimStyleContext(const ON_DimStyleContext&) = default; + ON_DimStyleContext& operator=(const ON_DimStyleContext&) = default; + +public: + virtual const ON_DimStyle& CurrentDimStyle() const; + + virtual const ON_DimStyle* DimStyleFromId( + ON_UUID id, + const ON_DimStyle* not_found_result = nullptr + ) const; + + virtual const ON_DimStyle* DimStyleFromName( + const ON_NameHash& name_hash, + const ON_DimStyle* not_found_result = nullptr + ) const; + + virtual const ON_DimStyle* DimStyleFromContentHash( + const ON_SHA1_Hash& content_hash, + const ON_DimStyle* not_found_result = nullptr + ) const; + + virtual const ON_DimStyle* DimStyleFromFont( + const ON_Font& font, + double model_space_text_scale, + double text_height, + ON::LengthUnitSystem text_height_unit_system, + bool bReturnClosestMatch = true, + const ON_DimStyle* not_found_result = nullptr + ) const; + + virtual bool AddDimStyle( + const ON_DimStyle& dim_style, + bool bResolveNameAndIdConflicts + ); + + virtual bool ModifyDimStyle( + ON_UUID model_dim_style_id, + const ON_DimStyle& dim_style + ); + + virtual const ON_DimStyle* FirstDimStyle( + bool bIncludeSystemDimStyles = false, + bool bIncludeDeletedDimStyles = false + ) const; + + virtual const ON_DimStyle* NextDimStyle( + ON_UUID id, + bool bIncludeSystemDimStyles = false, + bool bIncludeDeletedDimStyles = false + ) const; + + virtual const ON_DimStyle* PrevDimStyle( + ON_UUID id, + bool bIncludeSystemDimStyles = false, + bool bIncludeDeletedDimStyles = false + ) const; + + virtual ON::LengthUnitSystem ModelUnitSystem() const; + + virtual ON__UINT64 ModelSerialNumber() const; + +protected: + mutable ON::LengthUnitSystem m_unit_system = ON::LengthUnitSystem::Millimeters; + mutable ON__UINT64 m_model_serial_number = 0; +}; + + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray; +#endif + +#endif diff --git a/opennurbs/Include/opennurbs_dll_resource.h b/opennurbs/Include/opennurbs_dll_resource.h new file mode 100644 index 0000000..e989e0f --- /dev/null +++ b/opennurbs/Include/opennurbs_dll_resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by opennurbs.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/opennurbs/Include/opennurbs_ellipse.h b/opennurbs/Include/opennurbs_ellipse.h new file mode 100644 index 0000000..da169ab --- /dev/null +++ b/opennurbs/Include/opennurbs_ellipse.h @@ -0,0 +1,135 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_ELLIPSE_INC_) +#define OPENNURBS_ELLIPSE_INC_ + +class ON_Ellipse; +class ON_Plane; + +class ON_CLASS ON_Ellipse +{ +public: + ON_Ellipse(); // zeros all fields - plane is invalid + + ON_Ellipse( + const ON_Plane&, + double, double // radii for x and y vectors + ); + + ON_Ellipse( + const ON_Circle& + ); + + ~ON_Ellipse(); + + ON_Ellipse& operator=(const ON_Circle&); + + bool Create( + const ON_Plane&, // point on the plane + double, double // radii for x and y vectors + ); + + bool Create( + const ON_Circle& + ); + + bool IsValid() const; // returns true if all fields contain reasonable + // information and equation jibes with point and Z. + + bool IsCircle() const; // returns true is ellipse is a circle + + double Radius( + int // 0 = x axis radius, 1 = y axis radius + ) const; + const ON_3dPoint& Center() const; + const ON_3dVector& Normal() const; + const ON_Plane& Plane() const; // plane containing ellipse + + /* + Returns: + Distance from the center to a focus, commonly called "c". + */ + double FocalDistance() const; + + bool GetFoci( ON_3dPoint& F1, ON_3dPoint& F2 ) const; + + // Evaluation uses the trigonometrix parameterization + // t -> plane.origin + cos(t)*radius[0]*plane.xaxis + sin(t)*radius[1]*plane.yaxis + // evaluate parameters and return point + ON_3dPoint PointAt( double ) const; + ON_3dVector DerivativeAt( + int, // desired derivative ( >= 0 ) + double // parameter + ) const; + + ON_3dVector TangentAt( double ) const; // returns unit tangent + ON_3dVector CurvatureAt( double ) const; // returns curvature vector + + // returns parameters of point on ellipse that is closest to given point + bool ClosestPointTo( + const ON_3dPoint&, + double* + ) const; + // returns point on ellipse that is closest to given point + ON_3dPoint ClosestPointTo( + const ON_3dPoint& + ) const; + + // evaluate ellipse's implicit equation in plane + double EquationAt( const ON_2dPoint& ) const; + ON_2dVector GradientAt( const ON_2dPoint& ) const; + + // rotate ellipse about its center + bool Rotate( + double, // sin(angle) + double, // cos(angle) + const ON_3dVector& // axis of rotation + ); + bool Rotate( + double, // angle in radians + const ON_3dVector& // axis of rotation + ); + + // rotate ellipse about a point and axis + bool Rotate( + double, // sin(angle) + double, // cos(angle) + const ON_3dVector&, // axis of rotation + const ON_3dPoint& // center of rotation + ); + bool Rotate( + double, // angle in radians + const ON_3dVector&, // axis of rotation + const ON_3dPoint& // center of rotation + ); + + bool Translate( + const ON_3dVector& + ); + + // parameterization of NURBS curve does not match ellipse's transcendental paramaterization + int GetNurbForm( ON_NurbsCurve& ) const; // returns 0=failure, 2=success + +public: // members left public + // The center of the ellipse is at the plane's origin. The axes of the + // ellipse are the plane's x and y axes. The equation of the ellipse + // with respect to the plane is (x/m_r[0])^2 + (y/m_r[1])^2 = 1; + ON_Plane plane; + double radius[2]; // radii for x and y axes (both must be > 0) +}; + +#endif diff --git a/opennurbs/Include/opennurbs_error.h b/opennurbs/Include/opennurbs_error.h new file mode 100644 index 0000000..0272bba --- /dev/null +++ b/opennurbs/Include/opennurbs_error.h @@ -0,0 +1,272 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_ERROR_INC_) +#define OPENNURBS_ERROR_INC_ + +/* +// Macros used to log errors and warnings. The ON_Warning() and ON_Error() +// functions are defined in opennurbs_error.cpp. +*/ +#define ON_ERROR(msg) ON_ErrorEx(__FILE__,__LINE__,OPENNURBS__FUNCTION__,msg) +#define ON_WARNING(msg) ON_WarningEx(__FILE__,__LINE__,OPENNURBS__FUNCTION__,msg) +#define ON_ASSERT_OR_RETURN(cond,returncode) do{if (!(cond)) {ON_ErrorEx(__FILE__,__LINE__,OPENNURBS__FUNCTION__, #cond " is false");return(returncode);}}while(0) +#define ON_ASSERT_OR_RETURNVOID(cond) do{if (!(cond)) {ON_ErrorEx(__FILE__,__LINE__,OPENNURBS__FUNCTION__, #cond " is false");return;}}while(0) + +// Do not use ON_ASSERT. If a condition can be checked by ON_ASSERT, then the +// code must be written detect and respond to that condition. This define will +// be deleted ASAP. It is being used to detect situations where a crash will +// occur and then letting the crash occur. +#define ON_ASSERT(cond) ON_REMOVE_ASAP_AssertEx(cond,__FILE__,__LINE__,OPENNURBS__FUNCTION__, #cond " is false") + + +ON_BEGIN_EXTERNC + +/* +// All error/warning messages are sent to ON_ErrorMessage(). Replace the +// default handler (defined in opennurbs_error_message.cpp) with something +// that is appropriate for debugging your application. +*/ +ON_DECL +void ON_ErrorMessage( + int, /* 0 = warning message, 1 = serious error message, 2 = assert failure */ + const char* + ); + +/* +Returns: + Number of opennurbs errors since program started. +*/ +ON_DECL +int ON_GetErrorCount(void); + +/* +Returns: + Number of opennurbs warnings since program started. +*/ +ON_DECL +int ON_GetWarningCount(void); + +/* +Returns: + Number of math library or floating point errors that have + been handled since program started. +*/ +ON_DECL +int ON_GetMathErrorCount(void); + + +ON_DECL +int ON_GetDebugErrorMessage(void); + +ON_DECL +void ON_EnableDebugErrorMessage( int bEnableDebugErrorMessage ); + +ON_DECL +void ON_VARGS_FUNC_CDECL ON_Error( + const char* file_name, /* __FILE__ will do fine */ + int line_number, /* __LINE__ will do fine */ + const char* format, /* format string */ + ... /* format ags */ + ); + +ON_DECL +void ON_VARGS_FUNC_CDECL ON_ErrorEx( + const char* file_name, /* __FILE__ will do fine */ + int line_number, /* __LINE__ will do fine */ + const char* function_name, /* OPENNURBS__FUNCTION__ will do fine */ + const char* format, /* format string */ + ... /* format ags */ + ); + +ON_DECL +void ON_VARGS_FUNC_CDECL ON_Warning( + const char* file_name, /* __FILE__ will do fine */ + int line_number, /* __LINE__ will do fine */ + const char* format, /* format string */ + ... /* format ags */ + ); + +ON_DECL +void ON_VARGS_FUNC_CDECL ON_WarningEx( + const char* file_name, /* __FILE__ will do fine */ + int line_number, /* __LINE__ will do fine */ + const char* function_name, /*OPENNURBS__FUNCTION__ will do fine */ + const char* format, /* format string */ + ... /* format ags */ + ); + +// Ideally - these "assert" functions will be deleted when the SDK can be changed. +ON_DECL +void ON_VARGS_FUNC_CDECL ON_REMOVE_ASAP_AssertEx( + int, // if false, error is flagged + const char* file_name, /* __FILE__ will do fine */ + int line_number, /* __LINE__ will do fine */ + const char* function_name, /* OPENNURBS__FUNCTION__ will do fine */ + const char* format, /* format string */ + ... /* format ags */ + ); + +ON_DECL +void ON_MathError( + const char*, /* sModuleName */ + const char*, /* sErrorType */ + const char* /* sFunctionName */ + ); + +ON_END_EXTERNC + +#if defined(ON_CPLUSPLUS) + +class ON_CLASS ON_ErrorEvent +{ +public: + enum class Type : unsigned char + { + Unset = 0, + Warning = 1, // call to ON_WARNING / ON_Warning / ON_WarningEx + Error = 2, // call to ON_ERROR / ON_Error / ON_ErrorEx + Assert = 3, // ON_ASSERT (do not use ON_ASSERT - write code that handles errors and calls ON_ERROR) + Custom = 4, + SubDError = 5, // call to ON_SubDIncrementErrorCount() + BrepError = 6, // call to ON_BrepIncrementErrorCount() + NotValid = 7 // call to ON_IsNotValid() + }; + + static const char* TypeToString( + ON_ErrorEvent::Type event_type + ); + + const ON_String ToString() const; + +public: + ON_ErrorEvent() = default; + ~ON_ErrorEvent() = default; + ON_ErrorEvent(const ON_ErrorEvent&); + ON_ErrorEvent& operator=(const ON_ErrorEvent&); + + ON_ErrorEvent( + ON_ErrorEvent::Type event_type, + const char* file_name, + unsigned int line_number, + const char* function_name, + const char* description + ); + + static const ON_ErrorEvent Create( + ON_ErrorEvent::Type event_type, + const char* file_name, + unsigned int line_number, + const char* function_name, + const char* description + ); + + static const ON_ErrorEvent Unset; + + const char* FileName() const; + const char* FunctionName() const; + const char* Description() const; + unsigned int LineNumber() const; + ON_ErrorEvent::Type EventType() const; + + void Dump( + class ON_TextLog& text_log + ) const; + +private: + friend class ON_ErrorLog; + + ON_ErrorEvent::Type m_event_type = ON_ErrorEvent::Type::Unset; + unsigned char m_reserved1 = 0; + unsigned short m_reserved2 = 0; + unsigned int m_line_number = 0; + const char* m_file_name = nullptr; + const char* m_function_name = nullptr; + const char* m_description = nullptr; + char m_buffer[128] = {}; + + void Internal_CopyFrom(const ON_ErrorEvent& src); +}; + + +class ON_CLASS ON_ErrorLog +{ +public: + enum : unsigned int + { + MaximumEventCount = 32 + }; +public: + ON_ErrorLog() = default; + virtual ~ON_ErrorLog(); + ON_ErrorLog(const ON_ErrorLog&) = default; + ON_ErrorLog& operator=(const ON_ErrorLog&) = default; + + /* + Parameters: + error_event - [in] + event to add + Returns: + 0: Event not added because maximum capacity reached. + >0: Number of events after adding error_event. + */ + virtual + unsigned int Append( + const ON_ErrorEvent& error_event + ); + + /* + Returns: + Total number of error events. + */ + unsigned int Count() const; + + /* + Parameters: + i - [in] + zero based event index. + Returns + Event at specified index or ON_ErrorEvent::Unset if the index is out of range. + */ + const ON_ErrorEvent& Event(unsigned int i) const; + + void Clear(); + + /* + Returns: + True if up to ON_ErrorLog::MaximumErrorCount error events will be saved in this to this error log. + False if another error log is active. + */ + bool EnableLogging(); + + /* + Description: + Stop logging errors to this error log. + */ + void DisableLogging(); + + void Dump( + class ON_TextLog& text_log + ) const; + +protected: + unsigned int m_event_count = 0; + ON_ErrorEvent m_events[ON_ErrorLog::MaximumEventCount]; +}; + +#endif + +#endif diff --git a/opennurbs/Include/opennurbs_evaluate_nurbs.h b/opennurbs/Include/opennurbs_evaluate_nurbs.h new file mode 100644 index 0000000..763734c --- /dev/null +++ b/opennurbs/Include/opennurbs_evaluate_nurbs.h @@ -0,0 +1,461 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_EVALUATE_NURBS_INC_) +#define ON_EVALUATE_NURBS_INC_ + +ON_DECL +bool ON_IncreaseBezierDegree( + int, // dimension + bool, // true if Bezier is rational + int, // order (>=2) + int, // cv_stride (>=dim+1) + double* // cv[(order+1)*cv_stride] array + ); + +ON_DECL +bool ON_RemoveBezierSingAt0( // input bezier is rational with 0/0 at start + int, // dimension + int, // order (>=2) + int, // cv_stride (>=dim+1) + double* // cv[order*cv_stride] array + ); + +ON_DECL +bool ON_RemoveBezierSingAt1( // input bezier is rational with 0/0 at end + int, // dimension + int, // order (>=2) + int, // cv_stride (>=dim+1) + double* // cv[order*cv_stride] array + ); + +ON_DECL +double ON_EvaluateBernsteinBasis( // returns (i choose d)*(1-t)^(d-i)*t^i + int, // degree, + int, // 0 <= i <= degree + double // t + ); + +ON_DECL +void ON_EvaluatedeCasteljau( + int, // dim + int, // order + int, // side <= 0 return left side of bezier in cv array + // > 0 return right side of bezier in cv array + int, // cv_stride + double*, // cv + double // t 0 <= t <= 1 + ); + +ON_DECL +bool ON_EvaluateBezier( + int, // dimension + bool, // true if Bezier is rational + int, // order (>=2) + int, // cv_stride >= (is_rat)?dim+1:dim + const double*, // cv[order*cv_stride] array + double, double, // t0,t1 = domain of bezier + int, // number of derivatives to compute (>=0) + double, // evaluation parameter + int, // v_stride (>=dimension) + double* // v[(der_count+1)*v_stride] array + ); + +/* +Description: + Evaluate B-spline basis functions + +Parameters: + order - [in] + order >= 1 + d = degree = order - 1 + knot - [in] + array of length 2*d. + Generally, knot[0] <= ... <= knot[d-1] < knot[d] <= ... <= knot[2*d-1]. + These are the knots that are active for the span being evaluated. + t - [in] + Evaluation parameter. + Typically knot[d-1] <= t <= knot[d]. + In general t may be outside the interval knot[d-1],knot[d]. This can happen + when some type of extrapolation is being used and is almost always a bad + idea in practical situations. + + N - [out] + double array with capacity order*order. + The returned values are: + + If "N" were declared as double N[order][order], then + + k + N[d-k][i] = N (t) = value of i-th degree k basis function at t. + i + where 0 <= k <= d and k <= i <= d. + + In particular, N[0], ..., N[d] - values of degree d basis functions. + The "lower left" triangle is not initialized. + + Actually, the above is true when knot[d-1] <= t < knot[d]. Otherwise, the + value returned is the value of the polynomial that agrees with N_i^k on the + half open domain [ knot[d-1], knot[d] ) + +COMMENTS: + If a degree d NURBS has n control points, then the OpenNURBS knot vector + for the entire NURBS curve has length d+n-1. The knot[] paramter to this + function points to the 2*d knots active for the span being evaluated. + + Most literature, including DeBoor and The NURBS Book, + duplicate the Opennurbs start and end knot values and have knot vectors + of length d+n+1. The extra two knot values are completely superfluous + when degree >= 1. + + Assume C is a B-spline of degree d (order=d+1) with n control vertices + (n>=d+1) and knot[] is its knot vector. Then + + C(t) = Sum( 0 <= i < n, N_{i}(t) * C_{i} ) + + where N_{i} are the degree d b-spline basis functions and C_{i} are the control + vertices. The knot[] array length d+n-1 and satisfies + + knot[0] <= ... <= knot[d-1] < knot[d] + knot[n-2] < knot[n-1] <= ... <= knot[n+d-2] + knot[i] < knot[d+i] for 0 <= i < n-1 + knot[i] <= knot[i+1] for 0 <= i < n+d-2 + + The domain of C is [ knot[d-1], knot[n-1] ]. + + The support of N_{i} is [ knot[i-1], knot[i+d] ). + + If d-1 <= k < n-1 and knot[k] <= t < knot[k+1], then + N_{i}(t) = 0 if i <= k-d + = 0 if i >= k+2 + = B[i-k+d-1] if k-d+1 <= i <= k+1, where B[] is computed by the call + ON_EvaluateNurbsBasis( d+1, knot+k-d+1, t, B ); + + If 0 <= j < n-d, 0 <= m <= d, knot[j+d-1] <= t < knot[j+d], and B[] is + computed by the call + ON_EvaluateNurbsBasis( d+1, knot+j, t, B ), + then + N_{j+m}(t) = B[m]. +*/ +ON_DECL +bool ON_EvaluateNurbsBasis( + int order, + const double* knot, + double t, + double* N + ); + +/* +Description: + Calculate derivatives of B-spline basis functions. +INPUT: + order - [in] + order >= 1 + d = degree = order - 1 + knot - [in] + array of length 2*d. + Generally, knot[0] <= ... <= knot[d-1] < knot[d] <= ... <= knot[2*d-1]. + These are the knots that are active for the span being evaluated. + der_count - [in] + 1 <= der_count < order + Number of derivatives. + Note all B-spline basis derivatives with der_coutn >= order are identically zero. + + N - [in] + The input value of N[] should be the results of the call + ON_EvaluateNurbsBasis( order, knot, t, N ); + + N - [out] + If "N" were declared as double N[order][order], then + + d + N[d-k][i] = k-th derivative of N (t) + i + + where 0 <= k <= d and 0 <= i <= d. + + In particular, + N[0], ..., N[d] - values of degree d basis functions. + N[order], ..., N[order_d] - values of first derivative. +*/ +ON_DECL +bool ON_EvaluateNurbsBasisDerivatives( + int order, + const double* knot, + int der_count, + double* N + ); + +/* +Description: + Evaluate a NURBS curve span. +Parameters: + dim - [in] + dimension (> 0). + is_rat - [in] + true or false. + order - [in] + order=degree+1 (order>=2) + knot - [in] NURBS knot vector. + NURBS knot vector with 2*(order-1) knots, knot[order-2] != knot[order-1] + cv_stride - [in] + cv - [in] + For 0 <= i < order the i-th control vertex is + + cv[n],...,cv[n+(is_rat?dim:dim+1)], + + where n = i*cv_stride. If is_rat is true the cv is + in homogeneous form. + der_count - [in] + number of derivatives to evaluate (>=0) + t - [in] + evaluation parameter + v_stride - [in] + v - [out] + An array of length v_stride*(der_count+1). The evaluation + results are returned in this array. + + P = v[0],...,v[m_dim-1] + Dt = v[v_stride],... + Dtt = v[2*v_stride],... + ... + + In general, Dt^i returned in v[n],...,v[n+m_dim-1], where + + n = v_stride*i. + +Returns: + True if successful. +See Also: + ON_NurbsCurve::Evaluate + ON_EvaluateNurbsSurfaceSpan + ON_EvaluateNurbsCageSpan +*/ +ON_DECL +bool ON_EvaluateNurbsSpan( + int dim, + bool is_rat, + int order, + const double* knot, + int cv_stride, + const double* cv, + int der_count, + double t, + int v_stride, + double* v + ); + +/* +Description: + Evaluate a NURBS surface bispan. +Parameters: + dim - [in] >0 + is_rat - [in] true of false + order0 - [in] >= 2 + order1 - [in] >= 2 + knot0 - [in] + NURBS knot vector with 2*(order0-1) knots, knot0[order0-2] != knot0[order0-1] + knot1 - [in] + NURBS knot vector with 2*(order1-1) knots, knot1[order1-2] != knot1[order1-1] + cv_stride0 - [in] + cv_stride1 - [in] + cv - [in] + For 0 <= i < order0 and 0 <= j < order1, the (i,j) control vertex is + + cv[n],...,cv[n+(is_rat?dim:dim+1)], + + where n = i*cv_stride0 + j*cv_stride1. If is_rat is true the cv is + in homogeneous form. + + der_count - [in] (>=0) + s - [in] + t - [in] (s,t) is the evaluation parameter + v_stride - [in] (>=dim) + v - [out] An array of length v_stride*(der_count+1)*(der_count+2)/2. + The evaluation results are stored in this array. + + P = v[0],...,v[m_dim-1] + Ds = v[v_stride],... + Dt = v[2*v_stride],... + Dss = v[3*v_stride],... + Dst = v[4*v_stride],... + Dtt = v[5*v_stride],... + + In general, Ds^i Dt^j is returned in v[n],...,v[n+m_dim-1], where + + n = v_stride*( (i+j)*(i+j+1)/2 + j). + +Returns: + True if succcessful. +See Also: + ON_NurbsSurface::Evaluate + ON_EvaluateNurbsSpan + ON_EvaluateNurbsCageSpan +*/ +ON_DECL +bool ON_EvaluateNurbsSurfaceSpan( + int dim, + bool is_rat, + int order0, + int order1, + const double* knot0, + const double* knot1, + int cv_stride0, + int cv_stride1, + const double* cv, + int der_count, + double s, + double t, + int v_stride, + double* v + ); + + + +/* +Description: + Evaluate a NURBS cage trispan. +Parameters: + dim - [in] >0 + is_rat - [in] true of false + order0 - [in] >= 2 + order1 - [in] >= 2 + order2 - [in] >= 2 + knot0 - [in] + NURBS knot vector with 2*(order0-1) knots, knot0[order0-2] != knot0[order0-1] + knot1 - [in] + NURBS knot vector with 2*(order1-1) knots, knot1[order1-2] != knot1[order1-1] + knot2 - [in] + NURBS knot vector with 2*(order1-1) knots, knot2[order2-2] != knot2[order2-1] + cv_stride0 - [in] + cv_stride1 - [in] + cv_stride2 - [in] + cv - [in] + For 0 <= i < order0, 0 <= j < order1, and 0 <= k < order2, + the (i,j,k)-th control vertex is + + cv[n],...,cv[n+(is_rat?dim:dim+1)], + + where n = i*cv_stride0 + j*cv_stride1 *k*cv_stride2. + If is_rat is true the cv is in homogeneous form. + + der_count - [in] (>=0) + r - [in] + s - [in] + t - [in] (r,s,t) is the evaluation parameter + v_stride - [in] (>=dim) + v - [out] An array of length v_stride*(der_count+1)*(der_count+2)*(der_count+3)/6. + The evaluation results are stored in this array. + + P = v[0],...,v[m_dim-1] + Dr = v[v_stride],... + Ds = v[2*v_stride],... + Dt = v[3*v_stride],... + Drr = v[4*v_stride],... + Drs = v[5*v_stride],... + Drt = v[6*v_stride],... + Dss = v[7*v_stride],... + Dst = v[8*v_stride],... + Dtt = v[9*v_stride],... + + In general, Dr^i Ds^j Dt^k is returned in v[n],...,v[n+dim-1], where + + d = (i+j+k) + n = v_stride*( d*(d+1)*(d+2)/6 + (j+k)*(j+k+1)/2 + k) + +Returns: + True if succcessful. +See Also: + ON_NurbsCage::Evaluate + ON_EvaluateNurbsSpan + ON_EvaluateNurbsSurfaceSpan +*/ +ON_DECL +bool ON_EvaluateNurbsCageSpan( + int dim, + bool is_rat, + int order0, int order1, int order2, + const double* knot0, + const double* knot1, + const double* knot2, + int cv_stride0, int cv_stride1, int cv_stride2, + const double* cv, + int der_count, + double t0, double t1, double t2, + int v_stride, + double* v + ); + + +ON_DECL +bool ON_EvaluateNurbsDeBoor( // for expert users only - no support available + int, // cv_dim ( dim+1 for rational cvs ) + int, // order (>=2) + int, // cv_stride (>=cv_dim) + double*, // cv array - values changed to result of applying De Boor's algorithm + const double*, // knot array + int, // side, + // -1 return left side of B-spline span in cv array + // +1 return right side of B-spline span in cv array + // -2 return left side of B-spline span in cv array + // Ignore values of knots[0,...,order-3] and assume + // left end of span has a fully multiple knot with + // value "mult_k". + // +2 return right side of B-spline span in cv array + // Ignore values of knots[order,...,2*order-2] and + // assume right end of span has a fully multiple + // knot with value "mult_k". + double, // mult_k - used when side is +2 or -2. See above for usage. + double // t + // If side < 0, then the cv's for the portion of the NURB span to + // the LEFT of t are computed. If side > 0, then the cv's for the + // portion the span to the RIGHT of t are computed. The following + // table summarizes the restrictions on t: + // + // value of side condition t must satisfy + // -2 mult_k < t and mult_k < knots[order-1] + // -1 knots[order-2] < t + // +1 t < knots[order-1] + // +2 t < mult_k and knots[order-2] < mult_k + ); + + +ON_DECL +bool ON_EvaluateNurbsBlossom(int, // cvdim, + int, // order, + int, // cv_stride, + const double*, //CV, size cv_stride*order + const double*, //knot, nondecreasing, size 2*(order-1) + // knot[order-2] != knot[order-1] + const double*, //t, input parameters size order-1 + double* // P + + // DeBoor algorithm with different input at each step. + // returns false for bad input. + ); + + +ON_DECL +void ON_ConvertNurbSpanToBezier( + int, // cvdim (dim+1 for rational curves) + int, // order, + int, // cvstride (>=cvdim) + double*, // cv array - input has NURBS cvs, output has Bezier cvs + const double*, // (2*order-2) knots for the NURBS span + double, // t0, NURBS span parameter of start point + double // t1, NURBS span parameter of end point + ); +#endif diff --git a/opennurbs/Include/opennurbs_extensions.h b/opennurbs/Include/opennurbs_extensions.h new file mode 100644 index 0000000..5543974 --- /dev/null +++ b/opennurbs/Include/opennurbs_extensions.h @@ -0,0 +1,2104 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + + +#if !defined(OPENNURBS_EXTENSIONS_INC_) +#define OPENNURBS_EXTENSIONS_INC_ + +/* +Description: + The ONX_ErrorCounter is useful for counting errors that occur in a section of code. +*/ +class ON_CLASS ONX_ErrorCounter +{ +public: + ONX_ErrorCounter() = default; + ~ONX_ErrorCounter() = default; + ONX_ErrorCounter(const ONX_ErrorCounter&) = default; + ONX_ErrorCounter& operator=(const ONX_ErrorCounter&) = default; + + const ONX_ErrorCounter operator += (const ONX_ErrorCounter& rhs); + const ONX_ErrorCounter operator + (const ONX_ErrorCounter& rhs); + + static const ONX_ErrorCounter Zero; + + /* + Returns: + Number of failures. + */ + unsigned int FailureCount() const; + + /* + Returns: + Number of errors. + */ + unsigned int ErrorCount() const; + + /* + Returns: + Number of warnings. + */ + unsigned int WarningCount() const; + + /* + Returns: + Number of failures, erros, and warnings. + */ + unsigned int TotalCount() const; + + /* + Description: + Adds one to the failure count. + Returns: + Number of failures including this one. + */ + unsigned int IncrementFailureCount(); + + /* + Description: + Adds one to the error count. + Returns: + Number of errors including this one. + */ + unsigned int IncrementErrorCount(); + + /* + Description: + Adds one to the warning count. + Returns: + Number of warnings including this one. + */ + unsigned int IncrementWarningCount(); + + /* + Description: + Saves the current value of ON_GetErrorCount() + so future calls to ON_ERROR can be counted. + */ + void ClearLibraryErrors(); + + /* + Description: + Adds the number of calls to ON_ERROR since the last + call to ClearLibraryErrors(), AddLibraryErrors(), + ClearLibraryErrorsAndWarnings, or AddLibraryErrorsAndWarnings(). + Returns: + The number of errors added. + */ + unsigned int AddLibraryErrors(); + + /* + Description: + Saves the current value of ON_GetWarningCount() + so future calls to ON_WARNING can be counted. + */ + void ClearLibraryWarnings(); + + /* + Description: + Adds the number of calls to ON_WARNING since the last + call to ClearLibraryWarnings(), AddLibraryWarnings(), + ClearLibraryErrorsAndWarnings(), or AddLibraryErrorsAndWarnings(). + Returns: + The number of warnings added. + */ + unsigned int AddLibraryWarnings(); + + /* + Description: + Calls ClearLibraryErrors() and ClearLibraryWarnings(). + */ + void ClearLibraryErrorsAndWarnings(); + + /* + Description: + Calls AddLibraryErrors() and AddLibraryWarnings(). + Returns: + The number of errors and warnings added. + */ + unsigned int AddLibraryErrorsAndWarnings(); + + void Dump(ON_TextLog& text_log) const; + +private: + unsigned int m_failure_count = 0; + unsigned int m_error_count = 0; + unsigned int m_warning_count = 0; + + unsigned int m_state_bit_field = 0; + unsigned int m_opennurbs_library_error_count = 0; + unsigned int m_opennurbs_library_warning_count = 0; +}; + + +/* +Description: + Used to store user data information in an ONX_Model. +*/ +class ON_CLASS ONX_Model_UserData +{ +public: +#if defined(OPENNURBS_EXPORTS) || defined(OPENNURBS_IMPORTS) + // See comments at the top of opennurbs_extensions.cpp for details. + + // new/delete + void* operator new(size_t); + void operator delete(void*); + + // array new/delete + void* operator new[] (size_t); + void operator delete[] (void*); + + // in place new/delete + void* operator new(size_t,void*); + void operator delete(void*,void*); +#endif + + ONX_Model_UserData() = default; + ~ONX_Model_UserData() = default; + ONX_Model_UserData(const ONX_Model_UserData&) = default; + ONX_Model_UserData& operator=(const ONX_Model_UserData&) = default; + + void Dump( ON_TextLog& ) const; + + ON_UUID m_uuid = ON_nil_uuid; + ON_3dmGoo m_goo; + +public: + // 3dm version = 1,2,3,4,5,50,60,... + unsigned int m_usertable_3dm_version = 0; + + // opennurbs_version = old yyyymmddn value or + // a value from ON_VersionNumberConstruct(). + unsigned int m_usertable_opennurbs_version = 0; +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +#endif + +/* +Description: + Pedegodgical example of all the things in an OpenNURBS 3dm archive. + The openNURBS examples use ONX_Model to store the information + read from 3dm archives. Please study example_read.cpp for + details. +*/ +class ON_CLASS ONX_Model +{ +#if defined(OPENNURBS_EXPORTS) || defined(OPENNURBS_IMPORTS) + // See comments at the top of opennurbs_extensions.cpp for details. + +public: + + // new/delete + void* operator new(size_t); + void operator delete(void*); + + // array new/delete + void* operator new[] (size_t); + void operator delete[] (void*); + + // in place new/delete + void* operator new(size_t,void*); + void operator delete(void*,void*); +#endif + +public: + ONX_Model(); + virtual ~ONX_Model(); + + void Reset(); + +private: + // prohibit use of copy construction and operator= + ONX_Model(const ONX_Model&) = delete; + ONX_Model& operator=(const ONX_Model&) = delete; + +public: + /* + Description: + Reads an openNURBS archive and saves the information in this model + Parameters: + archive - [in] + archive to read from + table_filter - [in] + If table_filter is zero, then everything in the archive is read. + Otherwise the bits in table_filter identify what tables should + be read. The bits are defined by the + ON_BInaryArchive::table_type enum. + model_object_type_filter - [in] + If model_object_type_filter is not zero, then it is a bitfield filter + made by bitwise oring ON::object_type values to select which types of + objects will be read from the model object table. + error_log - [out] + any archive reading errors are logged here. + Returns: + true if archive is read with no error. False if errors occur. + Error details are logged in error_log. If crc errors are in + the archive, then ONX_Model::m_crc_error_count is set to the + number of crc errors. + Example: + + // for ASCII file names + const char* sFileName = ....; + FILE* fp = ON::OpenFile( sFileName, "rb"); + + // for UNICODE file names + const wchar_t* wsFileName = ....; + FILE* fp = ON::OpenFile( wsFileName, L"rb"); + + bool bModelRead = false; + bool bModelIsValid = false; + + ON_TextLog error_log; + ONX_Model model; + + if ( 0 != fp ) + { + ON_BinaryFile archive( ON::archive_mode::read3dm, fp ); + bModelRead = model.Read( archive, error_log ); + ON::CloseFile( fp ); + } + + if ( bModelRead ) + { + bModelIsValid = model.Validate(error_log); + } + + See Also: + ONX_Model::IsValid + ONX_Model::Write + ONX_Model::m_crc_error_count + */ + bool Read( + ON_BinaryArchive& archive, + unsigned int table_filter, + unsigned int model_object_type_filter, + ON_TextLog* error_log + ); + + bool Read( + const char* filename, + unsigned int table_filter, + unsigned int model_object_type_filter, + ON_TextLog* error_log + ); + + bool Read( + const wchar_t* filename, + unsigned int table_filter, + unsigned int model_object_type_filter, + ON_TextLog* error_log + ); + + bool Read( + ON_BinaryArchive& archive, + ON_TextLog* error_log = nullptr + ); + + bool Read( + const char* filename, + ON_TextLog* error_log = nullptr + ); + + bool Read( + const wchar_t* filename, + ON_TextLog* error_log = nullptr + ); + + /* + Description: + Reads everything up to the object table. + + Parameters: + archive - [in] + archive to read from + bManageComponents - [in] + true: + The ONX_Model destructor will delete the model components + created by this function. + false: + The caller must delete the ON_ModelComponent components after + the ONX_Model is destroyed. + table_filter - [in] + If table_filter is zero, then everything in the archive before + the model object table is read. Otherwise the bits in + table_filter identify what tables should be read. The bits + are defined by the ON_BInaryArchive::table_type enum. + error_log - [out] any archive reading errors are logged here. + pass nullptr if you don't want to log errors + + Returns: + If the input is valid and everything before the model object + table is successfully read, then true is returned. Otherwise + false is returned. + + Example: + + // for ASCII file names + const char* sFileName = ....; + FILE* fp = ON::OpenFile( sFileName, "rb"); + + // for UNICODE file names + const wchar_t* wsFileName = ....; + FILE* fp = ON::OpenFile( wsFileName, L"rb"); + + bool bModelRead = false; + bool bModelIsValid = false; + + ON_TextLog error_log; + + if ( 0 != fp ) + { + ON_BinaryFile archive( ON::archive_mode::read3dm, fp ); + ONX_Model model; + + // Read settings, layer information, and other tables + // with information that is referenced by model object + // attributes. + bModelRead = model.IncrementalReadBegin( archive, error_log ); + + if ( bModelRead ) + { + object_filter = ON::mesh_object // read meshes + | ON::curve_object // and curves + ; + for(;;) + { + // read the next model object + ON_ModelGeometryComponent* pModelObject = model.IncrementalReadModelObject(object_filter,0); + if ( 0 == pModelObject ) + break; + + ... // work with this model object + + // done with this object. + pModelObject = 0; + model.m_object_table.Remove(); + } + } + ON::CloseFile( fp ); + } + See Also: + ONX_Model::IsValid + ONX_Model::Write + ONX_Model::m_crc_error_count + */ + bool IncrementalReadBegin( + ON_BinaryArchive& archive, + bool bManageComponents, + unsigned int table_filter, + ON_TextLog* error_log + ); + + /* + Description: + Reads the next item in the model geometry table. + + Parameters: + archive - [in] + bManageModelGeometryComponent - [in] + true: + The ONX_Model destructor will delete the ON_ModelGeometryComponent components + created by this function. + false: + The caller must delete the ON_ModelGeometryComponent components after + the ONX_Model is destroyed. + bManageGeometry - [in] + true: + The ON_ModelGeometryComponent destructor will delete the ON_Geometry + classes created by this function. + false: + The caller must delete the ON_Geometry classes after + the ONX_Model and ON_ModelGeometryComponent components are destroyed. + bManageAttributes - [in] + true: + The ON_ModelGeometryComponent destructor will delete the ON_3dmObjectAttributes + classes created by this function. + false: + The caller must delete the ON_3dmObjectAttributes classes after + the ONX_Model and ON_ModelGeometryComponent components are destroyed. + model_object_type_filter - [in] + If model_object_type_filter is not zero, then it is a bitfield filter + made by bitwise oring ON::object_type values to select which types of + objects will be read from the model object table. + model_geometry_reference - [out] + A reference to an ON_ModelGeometryComponent. This referenced ON_ModelGeometryComponent + component is also added to the ONX_Model. + Call ONX_Model.RemoveComponent() if you want to discard it before + continuing. + Returns: + True + Succesful. If model_geometry_reference.IsEmpty() is true, + then no more geometry objects are available and you should call + IncrementalReadFinish(). + False + An error occured and reading should terminate. + Remarks: + You must call IncrementalReadBegin() before making any calls to + IncrementalReadModelObject(). + */ + bool IncrementalReadModelGeometry( + ON_BinaryArchive& archive, + bool bManageModelGeometryComponent, + bool bManageGeometry, + bool bManageAttributes, + unsigned int model_object_type_filter, + ON_ModelComponentReference& model_geometry_reference + ); + + /* + Description: + Reads everything up to the object table. + + Parameters: + archive - [in] + archive to read from + bManageComponents - [in] + true: + The ONX_Model destructor will delete the model components + created by this function. + false: + The caller must delete the ON_ModelComponent components after + the ONX_Model is destroyed. + table_filter - [in] + If table_filter is zero, then everything in the archive before + the model object table is read. Otherwise the bits in + table_filter identify what tables should be read. The bits + are defined by the ON_BInaryArchive::table_type enum. + error_log - [out] any archive reading errors are logged here. + pass nullptr if you don't want to log errors + + Returns: + If the input is valid and everything before the model object + table is successfully read, then true is returned. Otherwise + false is returned. + + See Also: + ONX_Model::IsValid + ONX_Model::Write + ONX_Model::m_crc_error_count + */ + bool IncrementalReadFinish( + ON_BinaryArchive& archive, + bool bManageComponents, + unsigned int table_filter, + ON_TextLog* error_log + ); + + /* + Description: + Writes contents of this model to an openNURBS archive. + + Parameters: + filename - [in] + + version - [in] + Version of the openNURBS archive to write. + 0 default value and suggested. + When 0 is passed in, the value of ON_BinaryArchive::CurrentArchiveVersion() + is used. + 2, 3, 4, 50, 60, ... + If you pass in a value < ON_BinaryArchive::CurrentArchiveVersion(), then some + information in current data structures will not be saved in the 3dm archive. + Rhino 2.x can read version 2 files. + Rhino 3.x can read version 2 and 3 files. + Rhino 4.x can read version 2, 3, and 4 files. + Rhino 5.x can read version 2, 3, 4, 5, and 50 files. + Rhino 6.x can read version 2, 3, 4, 5, 50, and 60 files. + + error_log - [out] + any archive writing errors are logged here. + + Returns: + True if archive is written with no error. + False if errors occur. + Error details are logged in error_log. + */ + bool Write( + const char* filename, + int version = 0, + ON_TextLog* error_log = nullptr + ) const; + + /* + Description: + Writes contents of this model to an openNURBS archive. + + Parameters: + filename - [in] + + version - [in] + Version of the openNURBS archive to write. + 0 default value and suggested. + When 0 is passed in, the value of ON_BinaryArchive::CurrentArchiveVersion() + is used. + 2, 3, 4, 50, 60, ... + If you pass in a value < ON_BinaryArchive::CurrentArchiveVersion(), then some + information in current data structures will not be saved in the 3dm archive. + Rhino 2.x can read version 2 files. + Rhino 3.x can read version 2 and 3 files. + Rhino 4.x can read version 2, 3, and 4 files. + Rhino 5.x can read version 2, 3, 4, 5, and 50 files. + Rhino 6.x can read version 2, 3, 4, 5, 50, and 60 files. + + error_log - [out] + any archive writing errors are logged here. + + Returns: + True if archive is written with no error. + False if errors occur. + Error details are logged in error_log. + */ + bool Write( + const wchar_t* filename, + int version = 0, + ON_TextLog* error_log = nullptr + ) const; + + /* + Description: + Writes contents of this model to an openNURBS archive. + + Parameters: + archive - [in] + archive to write to + You must call archive.SetArchiveFullPath(...) i order for file references to work correctly. + + version - [in] + Version of the openNURBS archive to write. + 0 default value and suggested. + When 0 is passed in, the value of ON_BinaryArchive::CurrentArchiveVersion() + is used. + 2, 3, 4, 50, 60, ... + If you pass in a value < ON_BinaryArchive::CurrentArchiveVersion(), then some + information in current data structures will not be saved in the 3dm archive. + Rhino 2.x can read version 2 files. + Rhino 3.x can read version 2 and 3 files. + Rhino 4.x can read version 2, 3, and 4 files. + Rhino 5.x can read version 2, 3, 4, 5, and 50 files. + Rhino 6.x can read version 2, 3, 4, 5, 50, and 60 files. + + error_log - [out] + any archive writing errors are logged here. + + Returns: + True if archive is written with no error. + False if errors occur. + Error details are logged in error_log. + + Example: + + model = ...; + if ( model.IsValid( error_log ) ) + { + const wchar_t* wsFileName = ....; + FILE* fp = ON::OpenFile( wsFileName, L"wb"); + + bool ok = false; + if ( 0 != fp ) + { + const char* sStartSectionComment = "..."; + int version = 5; // 2, 3, 4 or 5 are valid + ON_BinaryFile archive( ON::archive_mode::write3dm, fp ); + archive.SetArchiveFullPath(wsFileName); + ok = model.write( archive, + version, + sStartSectionComment, + error_log ); + ON::CloseFile( fp ); + } + } + + */ + bool Write( + ON_BinaryArchive& archive, + int version = 0, + ON_TextLog* error_log = nullptr + ) const; + + ///////////////////////////////////////////////////////////////////// + // + // BEGIN model definitions + // + + // 3dm archive start section information + int m_3dm_file_version = 0; + unsigned int m_3dm_opennurbs_version = 0; + ON__UINT64 m_3dm_file_byte_count = 0; + + ON_String m_sStartSectionComments; + + // Properties include revision history, notes, information about + // the applicaton that created the file, and an optional preview image. + ON_3dmProperties m_properties; + + // Settings include tolerance, and unit system, and defaults used + // for creating views and objects. + ON_3dmSettings m_settings; + + /* + Description: + A manifest of every model component in this ONX_Model. + Remarks: + Use the manifest to find model objects from a name, id or index. + + The manifest Id, Name, and Index values are values used in + the model. These are assigned when a component is added to the ONX_Model. + When possible the id and name are not changed. + + The manifest=model and original component values are different when: + - The original component Id or Name was not set and a value was automatically + assigned. + - The original component Id or Name was not unique and was modified when the component + was added to the model. + - Generally the original component index differs from the manifest=model component + index. + + The OriginalToModelMap() can be used to convert original component index + and id to the manifest=model index and id. + + The ModelToOriginalMap() can be used to manifest=model index and id to + the original component index and id. + */ + const ON_ComponentManifest& Manifest() const; + + /* + Returns: + A map from original component index and id to manifest=model index and id. + Remarks: + ON_ManifestMapItem Source = original component index and id. + ON_ManifestMapItem Destination = model-manifest index and id. + */ + const ON_ManifestMap& OriginalToModelMap() const; + + /* + Returns: + A map from manifest=model index and id to original component index and id. + Remarks: + ON_ManifestMapItem Source = model-manifest index and id. + ON_ManifestMapItem Destination = original component index and id. + */ + const ON_ManifestMap& ModelToOriginalMap() const; + + /* + Description: + This number changes every time the content of the ONX_Model is modified. + */ + ON__UINT64 ModelContentVersionNumber() const; + + /* + Description: + Add an copy of a model_compoent to this model. + model_component - [in] + A copy of model_component is added to this model. + The index, id, and name of the copied component are + set the the model values (Manifest() "Manifest" index, name, and id). + + bResolveIdAndNameConflicts - [in] + If bResolveIdAndNameConflicts is false, then model_component.Id() must be non-nil + and not used in this model and model_component.Name() must be correctly set. + If bResolveIdAndNameConflicts is true, then id and name will be modified + as needed in the model and manifest. + + Returns: + A reference to the added model component. + If the reference is empty (ON_ModelComponent::IsEmpty() is true) + then the input was not valid. + */ + ON_ModelComponentReference AddModelComponent( + const class ON_ModelComponent& model_component, + bool bResolveIdAndNameConflicts + ); + + ON_ModelComponentReference AddModelComponent( + const class ON_ModelComponent& model_component + ); + + ON_ModelComponentReference RemoveModelComponent( + ON_ModelComponent::Type component_type, + ON_UUID component_id + ); + + /* + Description: + Easy way to add a layer to the model. + Returns: + If layer_name is valid, the layer's index (>=0) is returned. Otherwise, + ON_UNSET_INT_INDEX is returned. + */ + int AddLayer( + const wchar_t* layer_name, + ON_Color layer_color + ); + + /* + Description: + Easy way to add a default layer to the model. + Properties: + layer_name - [in] + can be nullptr or empty. + layer_color - [in] + can be ON_Color::UnsetColor + Returns: + The default layer's index (>=0) is returned. + */ + int AddDefaultLayer( + const wchar_t* layer_name, + ON_Color layer_color + ); + + /* + Description: + Easy way to add a default dimension style to the model. + Parameters: + dimension_style_name - [in] + can be nullptr or empty + length_unit_system - [in] + If ON::LengthUnitSystem::Unset, then settings length unit system is used. + tolerance - [in] + If not > 0, then settings tolerance is used. + Returns: + The default dimension style's index (>=0) is returned. + */ + int AddDefaultDimensionStyle( + const wchar_t* dimension_style_name, + ON::LengthUnitSystem length_unit_system, + double model_tolerance + ); + + + + /* + Description: + Add a managed model component (ON_Layer, ON_DimStyle, ...) to this model. + + managed_model_component - [in] + managed_model_component must be created by operator new and on the heap. + It will be deleted when the model and last ON_ModelComponentReference are + destroyed. + + bResolveIdAndNameConflicts - [in] + If bResolveIdAndNameConflicts is false, then model_component.Id() must be non-nil + and not used in this model and model_component.Name() must be correctly set. + If bResolveIdAndNameConflicts is true, then id and name will be modified + as needed in managed_model_component, the model, and the manifest. + + Returns: + A reference to the added model component. + If the reference is empty (ON_ModelComponent::IsEmpty() is true) + then the input was not valid. + */ + ON_ModelComponentReference AddManagedModelComponent( + class ON_ModelComponent* managed_model_component, + bool bResolveIdAndNameConflicts + ); + + ON_ModelComponentReference AddManagedModelComponent( + class ON_ModelComponent* managed_model_component + ); + + /* + Description: + Add a model component to this model and control how the model_component instance + is managed. + + model_component - [in] + An ON_ModelComponent created on the heap by calling new X where X is + derived from ON_ModelComponent. + + bManagedComponent - [in] + If bManagedComponent is true, then ~ONX_Model will delete the component. + If bManagedComponent is false, then you are responsible for insuring + the component exists past the desctruction of this ONX_Model. + + bResolveIdAndNameConflicts - [in] + If bResolveIdAndNameConflicts is false, then model_component.Id() must be non-nil + and not used in this model and model_component.Name() must be correctly set. + If bResolveIdAndNameConflicts is true, then id and name will be modified + as needed. + + bUpdateComponentIdentification - [in] + The model_component Index(), Id(), and Name() values are set to match + the ones used in the model (Manifest() "Manifest" values.) + + Returns: + A reference to the added model component. + If the reference is empty (ON_ModelComponentReference::IsEmpty() is true), + then the input was not valid and the model component was not added. + */ + ON_ModelComponentReference AddModelComponentForExperts( + class ON_ModelComponent* model_component, + bool bManagedComponent, + bool bResolveIdAndNameConflicts, + bool bUpdateComponentIdentification + ); + + /* + Description: + Add an copy of the model_geometry and attrbutes to this model. + + Parameters: + geometry_object - [in] + geometry_object must point to a geometric object (curve, surface, brep, mesh, points, ...), + a render light, an annotation object, or a detail object. + A copy of geometry_object is added to and managed by this model. + attributes - [in] + nullptr if not available. + A copy of attributes is added to and managed by this model. + + bResolveIdAndNameConflicts - [in] + If bResolveIdAndNameConflicts is false, then attributes must be nullptr + or attributes->m_uid must be non-nil and not used in this model. + If bResolveIdAndNameConflicts is true, then id will be modified + as needed. + + Returns: + A reference to the added model component. + If the reference is empty (ON_ModelComponent::IsEmpty() is true) + then the input was not valid. + */ + ON_ModelComponentReference AddModelGeometryComponent( + const class ON_Object* geometry_object, + const class ON_3dmObjectAttributes* attributes, + bool bResolveIdAndNameConflicts + ); + + ON_ModelComponentReference AddModelGeometryComponent( + const class ON_Object* geometry_object, + const class ON_3dmObjectAttributes* attributes + ); + + /* + Description: + Add an copy of the model_geometry and attrbutes to this model. + + Parameters: + managed_geometry_object - [in] + managed_geometry_object must point to an instance geometric object (curve, surface, brep, mesh, points, ...), + a render light, an annotation object, or a detail object created by operator new and on the heap. + It will be deleted when the this ONX_Model and the last ON_ModelComponentReference are destroyed. + + managed_attributes - [in] + managed_attributes should be nullptr or point to an instance created by operator new and on the heap. + It will be deleted when the this ONX_Model and the last ON_ModelComponentReference are destroyed. + + bResolveIdAndNameConflicts - [in] + If bResolveIdAndNameConflicts is false, then managed_attributes must be nullptr + or managed_attributes->m_uuid must be non-nil and not used in this model. + If bResolveIdAndNameConflicts is true, then id will be modified + as needed. + + Returns: + A reference to the added model component. + If the reference is empty (ON_ModelComponent::IsEmpty() is true) + then the input was not valid. + */ + ON_ModelComponentReference AddManagedModelGeometryComponent( + class ON_Object* managed_geometry_object, + class ON_3dmObjectAttributes* managed_attributes, + bool bResolveIdAndNameConflicts + ); + + ON_ModelComponentReference AddManagedModelGeometryComponent( + class ON_Object* managed_geometry_object, + class ON_3dmObjectAttributes* managed_attributes + ); + + /* + Description: + Add geometry and attibutes to this model and control how the instances are managed. + + Parameters: + bManageGeometry - [in] + If true, geometry_object should point to an instance created by operator new and on the heap. + It will be deleted when the this ONX_Model and the last ON_ModelComponentReference are destroyed. + If false, the expert caller is carefully managing the instance and memory to insure + model_geometry is a valid instance while this ONX_Model and any ON_ModelComponentReference + are active. + + geometry_object - [in] + geometry_object should point to a geometric object (curve, surface, brep, mesh, points, ...), + a render light, an annotation object, or a detail object. + + bManageAttributes - [in] + If true, attributes should be nullptr or point to an instance created by operator new and on the heap. + It will be deleted when the this ONX_Model and the last ON_ModelComponentReference are destroyed. + If false, the expert caller is carefully managing the instance and memory to insure + attributes is a valid instance while this ONX_Model and and ON_ModelComponentReference + are active. + + attributes - [in] + nullptr if not avaiable. + + bResolveIdAndNameConflicts - [in] + If bResolveIdAndNameConflicts is false, then attributes must be nullptr + or attributes->m_uid must be non-nil and not used in this model. + If bResolveIdAndNameConflicts is true, then id will be modified + as needed. + + Returns: + A reference to the added model component. + If the reference is empty (ON_ModelComponent::IsEmpty() is true) + then the input was not valid. + */ + ON_ModelComponentReference AddModelGeometryComponentForExperts( + bool bManageGeometry, + class ON_Object* geometry_object, + bool bManageAttributes, + class ON_3dmObjectAttributes* attributes, + bool bResolveIdAndNameConflicts + ); + + unsigned int ComponentIndexLimit( + ON_ModelComponent::Type component_type + ) const; + + /* + Returns: + Number of active and deleted components. + Count does not include system components. + */ + unsigned int ActiveAndDeletedComponentCount( + ON_ModelComponent::Type component_type + ) const; + + /* + Returns: + Number of active components. + Count does not include system components. + */ + unsigned int ActiveComponentCount( + ON_ModelComponent::Type component_type + ) const; + + /* + Returns: + Number of deleted components. + */ + unsigned int DeletedComponentCount( + ON_ModelComponent::Type component_type + ) const; + + ON_ModelComponentReference ComponentFromIndex( + ON_ModelComponent::Type component_type, + int component_model_index + ) const; + + ON_ModelComponentReference ComponentFromUnsignedIndex( + ON_ModelComponent::Type component_type, + unsigned int component_model_index + ) const; + + ON_ModelComponentReference ComponentFromId( + ON_ModelComponent::Type component_type, + ON_UUID component_model_id + ) const; + + ON_ModelComponentReference ComponentFromName( + ON_ModelComponent::Type component_type, + ON_UUID component_parent_id, + const wchar_t* component_model_name + ) const; + + ON_ModelComponentReference ComponentFromNameHash( + ON_ModelComponent::Type component_type, + const ON_NameHash& component_model_name_hash + ) const; + + /* + Parameters: + runtime_serial_number - [in] + Value of ON_ModelComponent::RuntimeSerialNumber() to search for. + Returns: + If there is a model component with the specified runtime serial number, + then a reference to that component is returned. + Otherwise, ON_ModelComponentReference::Empty is returned. + Remarks: + ONX_Model::ComponentFromRuntimeSerialNumber() used to get a reference rather than a copy of the model's + primary ON_ModelComponentReference. This is the function that must be used if a caller is going to + use exclusive access funcitons like + + ON_ModelComponent* ON_ModelComponentReference::ExclusiveModelComponent() + ON_3dmObjectAttributes* ON_ModelGeometryComponent::ExclusiveAttributes() + ON_Geometry* ON_ModelGeometryComponent::ExclusiveGeometry() + + to modify content that is in the ONX_Model. The exclusive access functions + will only return non-nullptr values when there are no external references to + the model component. + */ + const ON_ModelComponentReference& ComponentFromRuntimeSerialNumber( + ON__UINT64 runtime_serial_number + ) const; + + /* + Description: + Get an image from its model index. + Parameters: + image_model_index - [in] + Returns: + An ON_ModelComponentReference to the image. + Remarks: + Model index and Manifest() manifest item index are the same. + */ + ON_ModelComponentReference ImageFromIndex( + int image_model_index + ) const; + + ON_ModelComponentReference ImageFromId( + ON_UUID image_id + ) const; + + ON_ModelComponentReference ImageFromFileFullPath( + const wchar_t* image_file_full_path_name + ) const; + + ON_ModelComponentReference ImageFromFileContent( + const ON_ContentHash& image_file_content_hash + ) const; + + ON_ModelComponentReference ImageFromFileReference( + const ON_FileReference& file_reference + ) const; + + /* + Description: + Get a line pattern from its model index. + Parameters: + line_pattern_model_index - [in] + Returns: + An ON_ModelComponentReference to the line pattern. + Remarks: + Model index and Manifest() manifest item index are the same. + */ + ON_ModelComponentReference LinePatternFromIndex( + int line_pattern_model_index + ) const; + + ON_ModelComponentReference LinePatternFromId( + ON_UUID line_pattern_model_id + ) const; + + ON_ModelComponentReference LinePatternFromName( + const wchar_t* line_pattern_name + ) const; + + ON_ModelComponentReference LinePatternFromNameHash( + ON_NameHash line_pattern_model_name_hash + ) const; + + /* + Description: + Get linetype from object attributes. + Parameters: + attributes - [in] object attributes. + line_pattern - [out] linetype + */ + ON_ModelComponentReference LinePatternFromAttributes( + const ON_3dmObjectAttributes& attributes + ) const; + + ON_ModelComponentReference LinePatternFromLayerIndex( + int layer_index + ) const; + + /* + Description: + Get render material from object attributes. + Parameters: + attributes - [in] object attributes. + material - [out] render material + */ + ON_ModelComponentReference RenderMaterialFromLayerIndex( + int layer_index + ) const; + + ON_ModelComponentReference RenderMaterialFromAttributes( + const ON_3dmObjectAttributes& attributes + ) const; + + ON_ModelComponentReference RenderMaterialFromIndex( + int render_material_index + ) const; + + ON_ModelComponentReference RenderMaterialFromId( + ON_UUID render_material_id + ) const; + + /* + Description: + Get a layer from its model index. + Parameters: + layer_model_index - [in] + Returns: + An ON_ModelComponentReference to the layer. + Remarks: + Model index and Manifest() manifest item index are the same. + */ + ON_ModelComponentReference LayerFromIndex( + int layer_model_index + ) const; + + ON_ModelComponentReference LayerFromId( + ON_UUID layer_model_id + ) const; + + ON_ModelComponentReference LayerFromName( + ON_UUID layer_parent_id, + const wchar_t* layer_name + ) const; + + ON_ModelComponentReference LayerFromNameHash( + const ON_NameHash& layer_model_name_hash + ) const; + + ON_ModelComponentReference LayerFromAttributes( + const ON_3dmObjectAttributes& attributes + ) const; + + /* + Description: + Get a dimension style from its model index. + Parameters: + dimension_style_model_index - [in] + Returns: + An ON_ModelComponentReference to the dimension style. + Remarks: + Model index and Manifest() manifest item index are the same. + */ + ON_ModelComponentReference DimensionStyleFromIndex( + int dimension_style_index + ) const; + ON_ModelComponentReference DimensionStyleFromId( + ON_UUID dimension_styleid + ) const; + ON_ModelComponentReference DimensionStyleFromName( + const wchar_t* dimension_style_name + ) const; + ON_ModelComponentReference DimensionStyleFromNameHash( + ON_NameHash dimension_style_name_hash + ) const; + + /* + Returns: + Id of the current dimension style or nil if the current style is + not set or not in this model. + */ + ON_UUID CurrentDimensionStyleId() const; + + /* + Parameters: + dimension_style_id - [in] + Id of a dimension style in this model, a system dimension style, or ON_nil_uuid. + Returns: + true if dimension_style_id is valid and is set. + */ + bool SetCurrentDimensionStyleId( + ON_UUID dimension_style_id + ); + + /* + Returns: + Current dimension style + = DimensionStyleFromId(CurrentDimensionStyleId()) + */ + ON_ModelComponentReference CurrentDimensionStyle() const; + + + /* + Returns: + A system dimension style that is the default for this model + and is used when a referenced dimension style is missing from + this model. + */ + ON_ModelComponentReference DefaultDimensionStyle() const; + + /* + Parameters: + font - [in] + model_space_text_scale - [in] + If model_space_text_scale > 0, then the DimScale() must be equal to model_space_text_scale. + bIgnoreSystemDimStyles - [in] + Returns: + The first dimension style with the specified font. + Remarks: + dimension styles with a non-nil parent id are ignored. + */ + ON_ModelComponentReference FirstDimensionStyleFromFont( + const ON_Font* font, + double model_space_text_scale, + bool bIgnoreSystemDimStyles + ) const; + + /* + Parameters: + managed_font_serial_number - [in] + model_space_text_scale - [in] + If model_space_text_scale > 0, then the DimScale() must be equal to model_space_text_scale. + bIgnoreSystemDimStyles - [in] + Returns: + The first dimension style with the specified font. + Remarks: + dimension styles with a non-nil parent id are ignored. + */ + ON_ModelComponentReference FirstDimensionStyleFromManagedFontSerialNumber( + unsigned int managed_font_serial_number, + double model_space_text_scale, + bool bIgnoreSystemDimStyles + ) const; + + /* + Description: + Find or create a dimension style with the specified font characteristics. + */ + ON_ModelComponentReference DimensionStyleWithFontCharacteristics( + const ON_Font& font_characteristics, + double model_space_text_scale + ); + + /* + Description: + Find a model geometry component from Id + Parameters: + model_geometry_component_id - [in] + Returns: + If there is a model geometry component with the id, it is returned. + Otherwise, ON_ModelComponentReference::Empty is returned. + */ + ON_ModelComponentReference ModelGeometryFromId( + ON_UUID model_geometry_component_id + ) const; + + /* + Description: + Find a model geometry component from Id + Parameters: + model_geometry_component_id - [in] + Returns: + If there is a model geometry component with the id, it is returned. + Otherwise, ON_ModelGeometryComponent::Unset is returned. + */ + const ON_ModelGeometryComponent& ModelGeometryComponentFromId( + ON_UUID model_geometry_component_id + ) const; + +public: + ON_SimpleArray m_userdata_table; + +private: + ON_ModelComponentReference m_default_render_material = ON_ModelComponentReference::CreateConstantSystemComponentReference(ON_Material::Default); + ON_ModelComponentReference m_default_line_pattern = ON_ModelComponentReference::CreateConstantSystemComponentReference(ON_Linetype::Continuous); + ON_ModelComponentReference m_default_layer = ON_ModelComponentReference::CreateConstantSystemComponentReference(ON_Layer::Default); + ON_ModelComponentReference m_default_text_style = ON_ModelComponentReference::CreateConstantSystemComponentReference(ON_TextStyle::Default); + ON_ModelComponentReference m_default_dimension_style = ON_ModelComponentReference::CreateConstantSystemComponentReference(ON_DimStyle::Default); + +private: + ON_ModelComponentReference Internal_AddModelComponent( + ON_ModelComponent* model_component, + ON_UUID id, + ON_UUID name_parent_id, + const ON_wString& name, + bool bManagedComponent, + bool bUpdateComponentIdentification + ); + +private: + // Content version is incremented every time the + // contents of the ONX_Model are modified. + ON__UINT64 m_model_content_version_number = 0; + +private: + void Internal_IncrementModelContentVersionNumber(); + + +private: + // A manifest of everything in the model. Use the manifest to find + // objects from a name, id or index. + ON_ComponentManifest m_manifest; + ON_ManifestMap m_original_to_manifest_map; + ON_ManifestMap m_manifest_to_original_map; + +private: + friend class ONX_ModelComponentIterator; + class ONX_ModelComponentReferenceLink* Internal_ModelComponentLinkFromSerialNumber( + ON__UINT64 model_component_runtime_serial_number + ) const; + class ONX_ModelComponentReferenceLink* Internal_AddModelComponentReference( + ON_ModelComponentReference mcr + ); + void Internal_RemoveModelComponentReferenceLink( + class ONX_ModelComponentReferenceLink* mcr_link + ); + // A map used to lookup by serial number. + ON_SerialNumberMap m_mcr_sn_map; + ON_FixedSizePool m_mcr_link_fsp; +#pragma ON_PRAGMA_WARNING_PUSH +#pragma ON_PRAGMA_WARNING_DISABLE_MSC( 4251 ) + // C4251: ... needs to have dll-interface to be used by clients of class ... + // This warning is not correct. + // m_mcr_lists is private and all code that manages m_mcr_lists is explicitly implemented in the DLL. + class ONX_ModelComponentList + { + public: + ON_ModelComponent::Type m_component_type = ON_ModelComponent::Type::Unset; + unsigned int m_count = 0; + class ONX_ModelComponentReferenceLink* m_first_mcr_link = nullptr; + class ONX_ModelComponentReferenceLink* m_last_mcr_link = nullptr; + }; + enum : unsigned int + { + ONX_MCR_LIST_COUNT = 16 + }; + ONX_ModelComponentList m_mcr_lists[ONX_MCR_LIST_COUNT]; + const ONX_ModelComponentList& Internal_ComponentListConst(ON_ModelComponent::Type component_type) const; + ONX_ModelComponentList& Internal_ComponentList(ON_ModelComponent::Type component_type); +#pragma ON_PRAGMA_WARNING_POP + +public: + bool ValdateComponentIdAndName( + ON_ModelComponent::Type component_type, + const ON_UUID& candidate_id, + const ON_UUID& component_parent_id, + const wchar_t* candidate_name, + bool bResolveIdConflict, + bool bResolveNameConflict, + ON_UUID& model_id, + ON_wString& model_name + ) const; + + // + // END model definitions + // + ///////////////////////////////////////////////////////////////////// + +public: + /* + Returns: + Bounding box of every object in m_object_table[]. + */ + ON_BoundingBox ModelGeometryBoundingBox() const; + + /* + Returns: + Bounding box of every render light in m_light_table[]. + */ + ON_BoundingBox RenderLightBoundingBox() const; + +private: + void Internal_ComponentTypeBoundingBox( + const ON_ModelComponent::Type component_type, + ON_BoundingBox& bbox + ) const; + +public: + + + /* + Description: + Get wireframe drawing color from object attributes. + Parameters: + attributes - [in] object attributes. + Returns: + Wireframe drawing color. + */ + ON_Color WireframeColorFromAttributes( + const ON_3dmObjectAttributes& attributes + ) const; + + /* + Description: + See if the instance reference iref refers to an instance + definition. + Parameters: + iref - [in] + idef_uuid - [in] id of idef we are looking for + Returns: + @untitled table + 0 iref does not use idef + 1 iref directly references idef + >1 iref has a nested reference to idef (nesting depth returned) + -1 iref.m_instance_definition_uuid is not valid + -2 invalid idef found + */ + int UsesIDef( + const ON_InstanceRef& iref, + ON_UUID idef_uuid + ) const; + + ///////////////////////////////////////////////////////////////////// + // + // BEGIN model document level user string tools + // + + /* + Description: + Attach a user string to the document. + Parameters: + key - [in] id used to retrieve this string. + string_value - [in] + If nullptr, the string with this id will be removed. + Returns: + True if successful. + */ + bool SetDocumentUserString( + const wchar_t* key, + const wchar_t* string_value + ); + + /* + Description: + Get user string from the document. + Parameters: + key - [in] id used to retrieve the string. + string_value - [out] + Returns: + True if a string with id was found. + */ + bool GetDocumentUserString( + const wchar_t* key, + ON_wString& string_value + ) const; + + /* + Description: + Get a list of all user strings in the document. + Parameters: + user_strings - [out] + user strings are appended to this list. + Returns: + Number of elements appended to the user_strings list. + */ + int GetDocumentUserStrings( ON_ClassArray& user_strings ) const; + + // + // END model document level user string tools + // + ///////////////////////////////////////////////////////////////////// + + + ///////////////////////////////////////////////////////////////////// + // + // BEGIN model text dump tools + // + + // text dump of entire model + void Dump( ON_TextLog& ) const; + + // text dump of model properties and settings + void DumpSummary( ON_TextLog& ) const; + + // text dump of user data table + void DumpUserDataTable( ON_TextLog& ) const; + + void DumpComponentList( + ON_ModelComponent::Type component_type, + ON_TextLog& text_log + ) const; + + /* + Returns: + A text dump of all component lists. + */ + void DumpComponentLists( + ON_TextLog& text_log + ) const; + + /* + Returns: + A SHA-1 hash of the model's content. If two models have identical content, + then the have equal ContentHash() values. + */ + ON_SHA1_Hash ContentHash() const; + +public: + + +private: + void Internal_DumpSummary( + ON_TextLog& dump, + bool bInvariantContentOnly + ) const; + +public: + + // + // END model text dump tools + // + ///////////////////////////////////////////////////////////////////// + + + ///////////////////////////////////////////////////////////////////// + // + // BEGIN Render Development Toolkit (RDK) information + // + // The following functions allow the developer access to the information saved per document or per-object in the 3dm file by the + // RDK plug-in, built into Rhino. There are two parts to this information - the XML data that constitutes the information + // about materials, textures and environments in addition to some of the document settings such as sun data, skylighting + // ground plane and so on - and the embedded support files which are saved as byte-per-byte copies of the actual file data + // for the original files. Typically, these embedded files will be textured used by materials, environments or decals. + + // Call this function to determine if RDK document information has been saved in this model and can be read using the GetRDKDocumentInfomation function. + // Returns true if RDK document information is available. + static bool IsRDKDocumentInformation(const ONX_Model_UserData& docud); + + // This function returns the entire XML associated with the RDK document data for this file. The XML will include details about + // materials, textures and environments as well as sun, skylighting, ground plane and so on. + // Returns true if RDK document information is available. + static bool GetRDKDocumentInformation(const ONX_Model_UserData& docud,ON_wString& rdk_xml_document_data); + + // This function returns the embedded support files written with this document. The returned arrays will be empty if no support filers were saved. + // Typically, these files will be used by materials and environments. Rhino unpacks these files into a folder with the suffix "embedded_files" next to the + // 3dm file on disk. + // This is only supported for Version 6 files onwards. + // Returns true if embedded files were found. + ON_DEPRECATED_MSG("This function is deprecated as it did not return the buffer sizes, making it useless") + static bool GetRDKEmbeddedFiles(const ONX_Model_UserData& docud, ON_ClassArray& paths, ON_SimpleArray& embedded_files_as_buffers); + + // This function returns the embedded support files written with this document. The returned arrays will be empty if no support filers were saved. + // Typically, these files will be used by materials and environments. Rhino unpacks these files into a folder with the suffix "embedded_files" next to the + // 3dm file on disk. + // This is only supported for Version 6 files onwards. + // Returns true if embedded files were found. + static bool GetRDKEmbeddedFiles(const ONX_Model_UserData& docud, ON_ClassArray& paths, ON_SimpleArray& embedded_files_as_buffers, ON_SimpleArray& buffer_sizes); + + // This function returns the paths of the embedded support files written with this document. The returned arrays will be empty if no support filers were saved. + // This function is similar to GetRDKEmbeddedFiles, but is faster and uses less memory to return only the paths. Use the paths (exactly the strings returned from this function) to + // extract the embedded files using GetRDKEmbeddedFile + static bool GetRDKEmbeddedFilePaths(const ONX_Model_UserData& docud, ON_ClassArray& paths); + + // This function extracts one embedded file from the support files written with this document. Use the exact path as returned from GetRDKEmbeddedFilePaths + static bool GetRDKEmbeddedFile(const ONX_Model_UserData& docud, const wchar_t* path, ON_SimpleArray& bytes); + + // Call this function to determine if RDK object information has saved in this model and can be read using the GetRDKObjectInformation function. + // Returns true if RDK object information is available. + static bool IsRDKObjectInformation(const ON_UserData& objectud); + + // This function returns the entire XML associated with the RDK object. The XML includes details about decals. + // Returns true if RDK object information is available. + static bool GetRDKObjectInformation(const ON_Object& object,ON_wString& rdk_xml_object_data); + // + // END Render Development Toolkit (RDK) information + // + ///////////////////////////////////////////////////////////////////// + +private: + mutable ON_BoundingBox m_model_geometry_bbox = ON_BoundingBox::UnsetBoundingBox; + mutable ON_BoundingBox m_render_light_bbox = ON_BoundingBox::UnsetBoundingBox; + class ON_DocumentUserStringList* m_model_user_string_list = nullptr; +}; + +class ON_CLASS ONX_ModelComponentIterator +{ +public: + ONX_ModelComponentIterator() = default; + ~ONX_ModelComponentIterator() = default; + ONX_ModelComponentIterator(const ONX_ModelComponentIterator&) = default; + ONX_ModelComponentIterator& operator=(const ONX_ModelComponentIterator&) = default; + + ONX_ModelComponentIterator( + const ONX_Model& model, + ON_ModelComponent::Type component_type + ); + + const ONX_Model* Model() const; + + ON_ModelComponentReference FirstComponentReference(); + ON_ModelComponentReference LastComponentReference(); + ON_ModelComponentReference CurrentComponentReference() const; + ON_ModelComponentReference NextComponentReference(); + ON_ModelComponentReference PreviousComponentReference(); + + ON_ModelComponentWeakReference FirstComponentWeakReference(); + ON_ModelComponentWeakReference LastComponentWeakReference(); + ON_ModelComponentWeakReference NextComponentWeakReference(); + ON_ModelComponentWeakReference PreviousComponentWeakReference(); + ON_ModelComponentWeakReference CurrentComponentWeakReference() const; + + // Use these with caution unless it is clear you are the only thread + // with references to the model and the iterator. + const ON_ModelComponent* FirstComponent(); + const ON_ModelComponent* LastComponent(); + const ON_ModelComponent* CurrentComponent() const; + const ON_ModelComponent* NextComponent(); + const ON_ModelComponent* PreviousComponent(); + + /* + Returns: + Number of active components in the current model. + Remarks: + If the model is modified during iteration, this value will changes. + */ + unsigned int ActiveComponentCount() const; + +private: + const class ONX_Model::ONX_ModelComponentList* Internal_List() const; + void Internal_SetLink(const class ONX_ModelComponentReferenceLink* link) const; + void Internal_SetLink(ON__UINT64 model_component_sn) const; + + ON_ModelComponent::Type m_component_type = ON_ModelComponent::Type::Unset; + const class ONX_Model* m_model = nullptr; + mutable ON__UINT64 m_model_content_version = 0; + mutable const class ONX_Model::ONX_ModelComponentList* m_list = nullptr; + mutable const class ONX_ModelComponentReferenceLink* m_link = nullptr; + mutable ON__UINT64 m_current_component_sn = 0; + mutable ON__UINT64 m_next_component_sn = 0; + mutable ON__UINT64 m_prev_component_sn = 0; + + // The current component is a weak ref so that a stand alone iterator cannot + // keep the current element alive since iterations often involve deletion. + // The iterators next/prev will still work as expected when the current element + // is deleted. In particular, an iterator can be used to efficiently delete + // portions of a model and have the deletion occur when many people + // expect it to occur and not at a later time. This makes debugging + // invalid deletions much easier. + mutable ON_ModelComponentWeakReference m_current_component_weak_ref; +}; + +class ON_CLASS ONX_ModelTest +{ +public: + ONX_ModelTest() = default; + ~ONX_ModelTest() = default; + ONX_ModelTest(const ONX_ModelTest&) = default; + ONX_ModelTest& operator=(const ONX_ModelTest&) = default; + + static const ONX_ModelTest Unset; + +public: + +#pragma region // XXRH_C_SHARED_ENUM // [ONX_ModelTest::Type] [Rhino.Geometry.Something.Type] [nested:byte] + /// + /// ONX_ModelTest::Type identifies the type of file reading test to perform. + /// + enum class Type : unsigned char + { + Unset = 0, + + /// + /// Read the source 3dm file. + /// + Read = 1, + + /// + /// Read the source 3dm file and write one or two temporary 3dm files. The original + /// source file is not modified. If the 3dm version of the source file + /// is < ON_BinaryArchive::CurrentArchiveVersion(), then two temporary 3dm + /// files are written, the first with 3dm version = ON_BinaryArchive::CurrentArchiveVersion()-10 + /// and the second with 3dm version = ON_BinaryArchive::CurrentArchiveVersion(). + /// For example, if Rhino 6 is the current version of Rhino and a file written + /// by Rhino 5 is read, then both a temporary Rhino 5 and a temporary Rhino 6 3dm + /// file are written. + /// + ReadWrite = 2, + + /// + /// Perform the ReadWrite test and read the temporary files. + /// + ReadWriteRead = 3, + + /// + /// Perform the ReadWriteRead test. If one of the temporary files has the same 3dm version + /// as the original source file, verify that the ONX_Models created by reading the original + /// 3dm file and the temporary 3dm file with the same version have identical values + /// of ONX_Model::ContentHash(). + /// + ReadWriteReadCompare = 4 + }; +#pragma endregion + + static const char* TestTypeToString(ONX_ModelTest::Type test_type); + static const wchar_t* TestTypeToWideString(ONX_ModelTest::Type test_type); + +#pragma region // XXRH_C_SHARED_ENUM // [ONX_ModelTest::Result] [Rhino.Geometry.Something.Result] [nested:byte] + /// + /// ONX_ModelTest::Result reports the result of a test. + /// + enum class Result : unsigned char + { + /// + /// Test result is not set. + /// + Unset = 0, + + /// + /// Test failed to complete. + /// + Fail = 1, + + /// + /// Test was performed and completed, but at least one ON_ERROR occured. + /// + Errors = 2, + + /// + /// Test was performed and completed, but at least one ON_WARNING occured. + /// + Warnings = 3, + + + /// + /// Test was performed and passed. + /// + Pass = 4, + + /// + /// Test was not perfomed because the input did not satisfy prerequisites or an + /// earlier test failed. + /// For example, if a ONX_ModelReadTest::TestType::ReadWriteReadCompare + /// test is requested and the source file is a Rhino 1 file, the compare + /// test is skipped. + /// For example, if a ONX_ModelReadTest::TestType::ReadWriteRead + /// test is requested and the Write test failes, the second Read test is skipped. + /// + Skip = 5, + }; +#pragma endregion + + static const char* ResultToString(ONX_ModelTest::Result result); + static const wchar_t* ResultToWideString(ONX_ModelTest::Result result); + + static ONX_ModelTest::Result WorstResult( + ONX_ModelTest::Result a, + ONX_ModelTest::Result b + ); + + /* + Parameters: + error_count - [in] + no_errors_result - [in] + result to return when 0 = error_count.TotalCount(). + */ + static ONX_ModelTest::Result ResultFromErrorCounter( + ONX_ErrorCounter error_count, + ONX_ModelTest::Result no_errors_result + ); + + /* + Description: + Test ONX_Model::Read() and ONX_Model::Write(). + Parameters: + file_path - [in] + file path + test_type - [in] + test to perform. + bKeepModels - [in] + If true, then the ONX_Models created by reading 3dm archives are saved + so the can be examined after the tests complete. + text_log_file_path - [in] + If not empty, the string to use for file_path in the output text_log. + This is used to create logs on different computers that can be compared. + text_log - [in] + If text_log is not nullptr, then a summary of the test is sent to text_log. + Returns: + True if every test passed with no warnings or errors. + False if a test failed or warnings or errors occured. + */ + bool ReadTest( + const char* file_path, + ONX_ModelTest::Type test_type, + bool bKeepModels, + const char* text_log_file_path, + ON_TextLog* text_log + ); + + /* + Description: + ONX_Model::ReadTest() can be used to test reading a specific file. + Parameters: + file_path - [in] + file path + test_type - [in] + test to perform. + bKeepModels - [in] + If true, then the ONX_Models created by reading 3dm archives are saved + so the can be examined after the tests complete. + text_log_file_path - [in] + If not empty, the string to use for file_path in the output text_log. + This is used to create logs on different computers that can be compared. + text_log - [in] + If text_log is not nullptr, then a summary of the test is sent to text_log. + Returns: + True if every test passed with no warnings or errors. + False if a test failed or warnings or errors occured. + */ + bool ReadTest( + const wchar_t* file_path, + ONX_ModelTest::Type test_type, + bool bKeepModels, + const wchar_t* text_log_file_path, + ON_TextLog* text_log + ); + + /* + Description: + ONX_Model::ReadTest() can be used to test reading a specific file. + Parameters: + fp - [in] + fp pointer to a file opened with ON_FileStream::Opent(...,"rb"); + test_type - [in] + test to perform. + bKeepModels - [in] + If true, then the ONX_Models created by reading 3dm archives are saved + so the can be examined after the tests complete. + text_log_file_path - [in] + If not empty, the string to use for file_path in the output text_log. + This is used to create logs on different computers that can be compared. + text_log - [in] + If text_log is not nullptr, then a summary of the test is sent to text_log. + Returns: + True if every test passed with no warnings or errors. + False if a test failed or warnings or errors occured. + */ + bool ReadTest( + FILE* fp, + ONX_ModelTest::Type test_type, + bool bKeepModels, + const wchar_t* text_log_file_path, + ON_TextLog* text_log + ); + + + /* + Description: + ONX_Model::Test() can be used to test reading a specific file. + Parameters: + archive - [in] + test_type - [in] + test to perform. + bKeepModels - [in] + If true, then the ONX_Models created by reading 3dm archives are saved + so the can be examined after the tests complete. + text_log_file_path - [in] + If not empty, the string to use for file_path in the output text_log. + This is used to create logs on different computers that can be compared. + text_log - [in] + If text_log is not nullptr, then a summary of the test is sent to text_log. + Returns: + True if every test passed with no warnings or errors. + False if a test failed or warnings or errors occured. + */ + bool ReadTest( + ON_BinaryArchive& archive, + ONX_ModelTest::Type test_type, + bool bKeepModels, + const wchar_t* text_log_file_path, + ON_TextLog* text_log + ); + + /* + Description: + Prints test results. + */ + void Dump(ON_TextLog& text_log) const; + + + /* + Description: + Prints the model context to text_log. + */ + static bool DumpModel(const ONX_Model* model, ON_TextLog& text_log); + + /* + Description: + Prints the source model context to text file next to the source file + with the file _ONX_ModelText_original_.txt appended to the + source file name. + Remark: + Call after test is completed. + */ + bool DumpSourceModel() const; + + /* + Description: + Prints the source model context to text_log. + Remark: + Call after test is completed. + */ + bool DumpSourceModel(const wchar_t* text_file_full_path) const; + + /* + Description: + Prints the source model context to text_log. + Remark: + Call after test is completed. + */ + bool DumpSourceModel(ON_TextLog& text_log) const; + + /* + Description: + Prints the model obtained from the last read in the read-write-read test to + with the file _ONX_ModelText_copy_.txt appended to the + original source file name. + Remark: + Call after test is completed. + */ + bool DumpReadWriteReadModel() const; + + /* + Description: + Prints the model obtained from the last read in the read-write-read test to + with the file _ONX_ModelText_copy_.txt appended to a text file + with the specified name. + Remark: + Call after test is completed. + */ + bool DumpReadWriteReadModel(const wchar_t* text_file_full_path) const; + + /* + Description: + Prints the model obtained from the last read in the read-write-read test to + with the file _ONX_ModelText_copy_.txt appended to the text_log. + Remark: + Call after test is completed. + */ + bool DumpReadWriteReadModel(ON_TextLog& text_log) const; + +private: + void Internal_BeginTest(); + + void Internal_EndCurrentTest(); + + void Internal_BeginNextTest( + ONX_ModelTest::Type test_type + ); + + + void Internal_ReadTest( + ON_BinaryArchive& archive, + ONX_ModelTest::Type test_type, + bool bKeepModels, + const wchar_t* text_log_file_path, + ON_TextLog* text_log + ); + + bool Internal_TallyTestResults(); + +public: + + // Test that was performed. + ONX_ModelTest::Type TestType() const; + + /* + Returns: + The name of the source 3dm file. + */ + const ON_wString Source3dmFilePath() const; + + /* + Returns: + The string used in the output log to identify the source 3dm file. + */ + const ON_wString TextLogSource3dmFilePath() const; + + /* + Returns: + Version of the 3dm fie, 1,2,3,4,5,50,60,... + */ + unsigned int Source3dmFileVersion() const; + + /* + Returns: + Worst result for any test that was attempted. + */ + ONX_ModelTest::Result TestResult() const; + + /* + Parameters: + test_type - [in] + Returns: + Result of the test identified by the test_type parameter. + */ + ONX_ModelTest::Result TestResult( + ONX_ModelTest::Type test_type + ); + + static bool SkipCompare( + unsigned int source_3dm_file_version + ); + + /* + Returns: + Total number of failures, errors, and warnings for all tests that + were performed. + */ + ONX_ErrorCounter ErrorCounter() const; + + /* + Returns: + Total number of failures, errors, and warnings for all tests that + were performed. + */ + ONX_ErrorCounter ErrorCounter( + ONX_ModelTest::Type test_type + ) const; + + const ON_SHA1_Hash SourceModelHash(); + const ON_SHA1_Hash ReadWriteReadModelHash(); + + /* + Returns: + nullptr if the test was run with bKeepModels=false or the + source archive could not be read. + Otherwise, a pointer to the source model. + */ + std::shared_ptr SourceModel() const; + + /* + Returns: + nullptr if the read write read test was not performed or was run with bKeepModels=false. + Otherwise, a pointer to the result of the read write read test. + */ + std::shared_ptr ReadWriteReadModel() const; + + + private: + ONX_ModelTest::Type m_test_type = ONX_ModelTest::Type::Unset; + + ON_wString m_source_3dm_file_path; + + // if set, used when printing the name of m_source_3dm_file_path in the text + // log so results from different computers can be compared. + ON_wString m_text_log_3dm_file_path; + + unsigned int m_model_3dm_file_version[3]; + + unsigned int m_current_test_index = 0; + + ONX_ModelTest::Result m_test_result = ONX_ModelTest::Result::Unset; + ONX_ModelTest::Result m_test_results[7] = {}; + + ONX_ErrorCounter m_error_count; + ONX_ErrorCounter m_error_counts[7]; + +#pragma ON_PRAGMA_WARNING_PUSH +#pragma ON_PRAGMA_WARNING_DISABLE_MSC( 4251 ) + // C4251: ... : class 'std::shared_ptr' + // needs to have dll-interface to be used by clients ... + // m_model[] is private and all code that manages m_sp is explicitly implemented in the DLL. + + // m_model[0] = model from source file + // m_model[1] = model[0] -> write to current 3dm version -> read into model[1] + // m_model[2] = model[0] -> write to prev 3dm version -> read into model[2] + std::shared_ptr m_model[3]; +#pragma ON_PRAGMA_WARNING_POP + + // m_model_hash[i] = m_model[0].Hash() + ON_SHA1_Hash m_model_hash[3]; +}; + + +#endif diff --git a/opennurbs/Include/opennurbs_file_utilities.h b/opennurbs/Include/opennurbs_file_utilities.h new file mode 100644 index 0000000..5f65478 --- /dev/null +++ b/opennurbs/Include/opennurbs_file_utilities.h @@ -0,0 +1,1794 @@ +/* +// +// Copyright (c) 1993-2015 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_FILE_UTILITIES_INC_) +#define OPENNURBS_FILE_UTILITIES_INC_ + +class ON_CLASS ON_FileSystem +{ +private: + ON_FileSystem() = delete; + ~ON_FileSystem() = delete; + ON_FileSystem(const ON_FileSystem&) = delete; + ON_FileSystem& operator=(const ON_FileSystem&) = delete; + +public: + static bool PathExists( + const char* path + ); + + static bool PathExists( + const wchar_t* path + ); + + /* + Returns: + True if path is a directory. + False otherwise. + */ + static bool IsDirectory( + const char* path + ); + + /* + Returns: + True if path is a directory. + False otherwise. + */ + static bool IsDirectory( + const wchar_t* path + ); + + /* + Returns: + True if path is a directory where files can be written. + False otherwise. + */ + static bool IsDirectoryWithWriteAccess( + const char* path + ); + + /* + Returns: + True if path is a directory where files can be written. + False otherwise. + */ + static bool IsDirectoryWithWriteAccess( + const wchar_t* path + ); + + /* + Returns: + True if path is a file. + False otherwise. + */ + static bool IsFile( + const char* path + ); + + /* + Returns: + True if path is a file. + False otherwise. + */ + static bool IsFile( + const wchar_t* path + ); + + /* + Description + Remove a file + Parameters: + file_path - [in] + name of file to delete + Returns: + True if the fuke existed and was removed. + */ + static bool RemoveFile( + const char* file_path + ); + + /* + Description + Remove a file + Parameters: + file_path - [in] + name of file to delete + Returns: + True if the fuke existed and was removed. + */ + static bool RemoveFile( + const wchar_t* file_path + ); +}; + +class ON_CLASS ON_FileSystemPath +{ +private: + ON_FileSystemPath() = delete; + ~ON_FileSystemPath() = delete; + ON_FileSystemPath(const ON_FileSystemPath&) = delete; + ON_FileSystemPath& operator=(const ON_FileSystemPath&) = delete; + +public: + /* + Platform dependent character used to separate directory names. + On Windows platforms: + ON_FileSystemPath::DirectorySeparator = ON_wString::Backslash. + On UNIX (including modern Apple) platforms: + ON_FileSystemPath::DirectorySeparator = ON_wString::Slash. + */ + static const char DirectorySeparatorAsChar; + static const wchar_t DirectorySeparator; + + static const char AlternateDirectorySeparatorAsChar; + static const wchar_t AlternateDirectorySeparator; + + static bool IsDirectorySeparator( + char c, + bool bAllowAlternate + ); + + static bool IsDirectorySeparator( + wchar_t c, + bool bAllowAlternate + ); + + /* + Description: + Find the locations in a path the specify the drive, directory, + file name and file extension. + Parameters: + path - [in] + path to split + volume - [out] (pass null if you don't need the volume) + If volume is not null and the path parameter begins with a + Windows volume specification, *volume will either be + the Windows volume letter followed by the trailing colon + or a Windows UNC \\. Otherwise volume will + be the empty string. + dir - [out] (pass null if you don't need the directory) + If dir is not null and the path parameter contains a + directory specification, then the returned value of *dir + will be the directory specification including the trailing + slash. + file_name_stem - [out] (pass null if you don't need the file name stem) + If file_name_stem is not null and the path parameter contains a + file name specification, then the returned value of *file_name_stem + will be the file name stem. + file_name_ext - [out] (pass null if you don't need the extension) + If file_name_ext is not null and the path parameter contains a + file name extension specification, then the returned value of + *file_name_ext will be the file name extension including the initial + '.' character. + Remarks: + This function will treat a front slash ( / ) and a back slash + ( \ ) as directory separators. Because this function parses + file names store in .3dm files and the .3dm file may have been + written on a Windows computer and then read on a another + computer, it looks for a volume specification even when the + operating system is not Windows. + This function will not return an directory that does not + end with a trailing slash. + This function will not return an empty filename and a non-empty + extension. + This function parses the path string according to these rules. + It does not check the actual file system to see if the answer + is correct. + See Also: + on_splitpath + */ + static void SplitPath( + const char* path, + ON_String* volume, + ON_String* dir, + ON_String* file_name_stem, + ON_String* file_name_ext + ); + + static void SplitPath( + const char* path, + ON_wString* volume, + ON_wString* dir, + ON_wString* file_name_stem, + ON_wString* file_name_ext + ); + + static void SplitPath( + const wchar_t* path, + ON_wString* volume, + ON_wString* dir, + ON_wString* file_name_stem, + ON_wString* file_name_ext + ); + + static void SplitPath( + const wchar_t* path, + ON_wString* volume, + ON_wString* dir, + ON_wString* file_name_stem_and_extension + ); + + static bool FilePathHas3dmExtension( + const wchar_t* file_path, + bool bAllow3dmbakExtension + ); + + static bool FilePathHas3dmExtension( + const char* file_path, + bool bAllow3dmbakExtension + ); + + /* + Description: + Determine if the file_name string is a permitted file name. + Valid file names must be non empty, cannot have two periods in a row, + and cannot contain directory separators, tildes, and other + platform specific values. + Parameters: + file_name - [in] + string to test. + bAllPlatforms - [in] + If true, test name for all supported platforms. + Returns: + True if the string can be a file name. + */ + static bool IsValidFileName( + const char* file_name, + bool bAllPlatforms + ); + + /* + Description: + Determine if the file_name string is a permitted file name. + Valid file names must be non empty, cannot have two periods in a row, + and cannot contain directory separators, tildes, and other + platform specific values. + Parameters: + file_name - [in] + string to test. + bAllPlatforms - [in] + If true, test name for all supported platforms. + Returns: + True if the string can be a file name. + */ + static bool IsValidFileName( + const wchar_t* file_name, + bool bAllPlatforms + ); + + /* + Parameters: + path - [in] + path to split + Returns: + The volume portion of the path. + */ + static const ON_wString VolumeFromPath( + const wchar_t* path + ); + + /* + Parameters: + path - [in] + path to split + Returns: + The directory portion of the path. + */ + static const ON_wString DirectoryFromPath( + const wchar_t* path + ); + + /* + Parameters: + path - [in] + path to split + Returns: + The volume and directory portion of the path. + */ + static const ON_wString VolumeAndDirectoryFromPath( + const wchar_t* path + ); + + /* + Parameters: + path - [in] + path to split + bIncludeExtension - [in] + Returns: + The file name portion of the path. + */ + static const ON_wString FileNameFromPath( + const wchar_t* path, + bool bIncludeExtension + ); + + /* + Parameters: + path - [in] + path to split + Returns: + The file name extension portion of the path, inlcuding the leading period or "dot". + */ + static const ON_wString FileNameExtensionFromPath( + const wchar_t* path + ); + + /* + Description: + Condenses // to / + Condenses /./ to / + Condenses /sfsdf/../ to / + Sets all directory separators to directory_separator. + Parameters: + bAllowWindowsUNCHostNameOrDiskLetter - [in] + If bAllowWindowsUNCHostNameOrDiskLetter and the path begins with \\HostName followed by + a directory separator, then the initial \\ is not condensed. + If the path begins with X: followed by a directory separator, where "X" is a single + letter in the range A to Z or a to z, then the path is considered valid. + bDeleteWindowsUNCHostNameOrDiskLetter - [in] + If bAllowWindowsUNCHostNameOrDiskLetter is true and the path begins with a UNC + host name or disk letter followed by a directory separator, then host name or disk letter + is deleted. This is useful when using paths from a Windows platform on a + non-Windows platform. + bExpandUser - [in] + If the path begins with ~ and ON_FileSystemPath::PlatformPath( ON_FileSystemPath::PathId::UserHomeDirectory ) + is not empty, then the ~ is replaced with absolute path of user's home directory. + directory_separator - [in] + If 0 == directory_separator, then the first directory separator + is kept when condensing occurs. + ON_wString::FileSystemPathSeparator is a good choice if you want + to use the current runtime's separator. + dirty_path - [in] + path to clean. + Return: + Cleaned path. + */ + static const ON_wString CleanPath( + bool bTrimLeft, + bool bTrimRight, + bool bAllowWindowsUNCHostNameOrDiskLetter, + bool bDeleteWindowsUNCHostNameOrDiskLetter, + bool bExpandUser, + const wchar_t directory_separator, + const wchar_t* dirty_path + ); + + static const ON_wString CleanPath( + bool bTrimLeft, + bool bTrimRight, + bool bAllowWindowsUNCHostNameOrDiskLetter, + bool bDeleteWindowsUNCHostNameOrDiskLetter, + const wchar_t directory_separator, + const wchar_t* dirty_path + ); + + /* + Description: + If the path begins with ~ and ON_FileSystemPath::PlatformPath( ON_FileSystemPath::PathId::UserHomeDirectory ) + is not empty, then the ~ is replaced with absolute path of user's home directory. + */ + static const ON_wString ExpandUser( + const char* dirty_path + ); + static const ON_wString ExpandUser( + const wchar_t* dirty_path + ); + + /* + Parameters: + path - [in] + path to test + directory_separator - [in] + If 0 == directory_separator, then either ON_wString::FileSystemPathSeparator + or ON_wString::AlternateFileSystemPathSeparator is permitted as a directory + separator. + ON_wString::FileSystemPathSeparator is a good choice if you want + to use the current runtime's separator. + Returns: + True if path begins with ../ or ./ + */ + static bool IsRelativePath( + const wchar_t* path, + const wchar_t directory_separator + ); + + + /* + Parameters: + path - [in] + path to test + Returns: + True if path begins with ../ or ..\ or ./ or .\ + */ + static bool IsRelativePath( + const wchar_t* path + ); + /* + Description: + Condenses // to / + Condenses /./ to / + Condenses /sfsdf/../ to / + Trims left and right white space. + Sets all directory separators to ON_FileSystemPath::DirectorySeparator. + If the Platform is not windows, the UNC host names and volume letters are deleted. + */ + static const ON_wString CleanPath( + const wchar_t* dirty_path + ); + + /* + Description: + Get a the relative path from base_path to full_path. + Parameters: + full_path - [in] + base_path - [in] + + Example + full_path = L"c:/a/b/c/d/somefile.txt"; + base_path = L"C:/A/B/X/Y/Z/model.3dm"; + ON_wString::GetRelativePath(full_path,base_path) returns + L"../../../c/d/somefile.txt" + + Example + full_path = L"c:/a/b/somefile.txt"; + base_path = L"C:/A/B/model.3dm"; + ON_wString::GetRelativePath(full_path,base_path) returns + L"./somefile.txt" + + Remarks: + Path separators on the input can be mixed. + Path separators on the returned relative path are ON_wString::FileSystemPathSeparator + */ + static const ON_wString RelativePath( + const wchar_t* full_path, + bool bFullPathIncludesFileName, + const wchar_t* base_path, + bool bBasePathIncludesFileName + ); + + static const ON_wString FullPathFromRelativePath( + const wchar_t* base_path, + bool bBasePathIncludesFileName, + const wchar_t* relative_path + ); + + /* + Returns: + true if the platform file system ignores case. + Remarks: + Windows and default installations of OS X 10.10.3, and default installations of the UNIX + terminal interface in OS X 10.10.3 and later ignore case. + In the case of OX X, a user can override the default setting. + */ + static bool PlatformPathIgnoreCase(); + + /* + Parameters: + bWithTrailingDirectorySeparator - [in] + true - returned path will have a trailing directory separator. + false - returned path will not have a trailing directory separator. + Returns: + The platform current working directory which should be the directory + where ON::OpenFile("fname","r") would look for a file named "fname". + */ + static const ON_wString CurrentDirectory( + bool bWithTrailingDirectorySeparator + ); + + /* + Description: + Removes file name from path. + Parameters: + path - [in] + file system path with a file name. + file_name - [out] + If file_name is not nullptr, the removed portion of path + is returned here. + Returns: + path with any file name removed. + Remarks: + This function uses on_wsplitpath() to decide if the path ends with characters that + could be a file name. It does not inspect the file system to see if the file exists. + */ + static const ON_wString RemoveFileName( + const wchar_t* path, + ON_wString* file_name + ); + + /* + Description: + Removes Windows volume name from path. + Parameters: + path - [in] + file system path + volume_name - [out] + If volume_name is not nullptr, the removed portion of path + is returned here. + Returns: + path with any volume name removed. + Remarks: + This function uses on_wsplitpath() to decide if the path begins with characters that + could be a volume name. It does not inspect the file system to see if the volume exists. + */ + static const ON_wString RemoveVolumeName( + const wchar_t* path, + ON_wString* volume_name + ); + + /* + Description: + Combine paths into a single valid path name. Remove internal .. and . + directory references. If necessary remove file names. + Parameters: + left_side - [in] + bLeftSideContainsFileName - [in] + true if left_side path ends in a file name and that + file name is removed and discarded. + right_side - [in] + bRightSideContainsFileName - [in] + true if right_side path ends in a file name. + If bAppendTrailingDirectorySeparator is true, that file name is removed + and discarded. If bAppendTrailingDirectorySeparator is false, the + returned path ends in that file name. + bAppendTrailingDirectorySeparator - [in] + If true, any file names are removed and a directory separator + is appended to the returned string. + Returns: + a path made left_side + right_side + Remarks: + This function manipulates string information. + This function does not look at storage media + to see if the paths currently exist. + */ + static const ON_wString CombinePaths( + const wchar_t* left_side, + bool bLeftSideContainsFileName, + const wchar_t* right_side, + bool bRightSideContainsFileName, + bool bAppendTrailingDirectorySeparator + ); + + /// + /// ON_FileSystemPath::PathId identifies a collection of commonly used directories. + /// Use ON_FileSystemPath::PlatformPath() to get the name of the directory. + /// + enum class PathId : unsigned int + { + /// + /// The current user's home directory. + /// + Unset = 0, + + /// + /// The current user's desktop directory. + /// + DesktopDirectory = 1, + + /// + /// The current user's documents directory. + /// + DocumentsDirectory = 2, + + /// + /// The current user's downloads directory. + /// + DownloadsDirectory = 3, + + /// + /// The current user's home directory. + /// + HomeDirectory = 4 + }; + + /* + Parameters: + path_id - [in] + Specifies path to get. + Returns: + Requested path. If the path does not exist in the current context, + the empty string is returned. + */ + static const ON_wString PlatformPath( + ON_FileSystemPath::PathId path_id + ); + + + ON_DEPRECATED_MSG("Use ON_FileSystem::PathExists") + static bool PathExists( + const char* path + ); + + ON_DEPRECATED_MSG("Use ON_FileSystem::PathExists") + static bool PathExists( + const wchar_t* path + ); + + ON_DEPRECATED_MSG("Use ON_FileSystem::IsDirectory") + static bool IsDirectory( + const char* path + ); + + ON_DEPRECATED_MSG("Use ON_FileSystem::IsDirectory") + static bool IsDirectory( + const wchar_t* path + ); + + ON_DEPRECATED_MSG("Use ON_FileSystem::IsFile") + static bool IsFile( + const char* path + ); + + ON_DEPRECATED_MSG("Use ON_FileSystem::IsFile") + static bool IsFile( + const wchar_t* path + ); +}; + +class ON_CLASS ON_FileStream +{ +public: + /* + Description: + Portable wrapper for C runtime fopen(). + Parameters: + filename - [in] + mode - [in] + Remarks: + Use the ON_FileStream static functions for reading, writing, + seeking, position finding with the FILE pointer returned + by this function. + */ + static FILE* Open( const wchar_t* filename, const wchar_t* mode ); + + /* + Description: + Portable wrapper for C runtime fopen(). + Parameters: + filename - [in] + mode - [in] + Remarks: + Use the ON_FileStream static functions for reading, writing, + seeking, position finding with the FILE pointer returned + by this function. + */ + static FILE* Open( const char* filename, const char* mode ); + + /* + Description: + Portable wrapper for C runtime fclose(). + Parameters: + fp - [in] + FILE pointer returned by ON_FileStream::Open(). + Returns: + 0: successful + -1: null fp parameter + != 0: fclose() failure code + */ + static int Close( FILE* fp ); + + /* + Returns: + True if the file is a 3dm archive. + */ + static bool Is3dmFile( + const wchar_t* file_path, + bool bAllow3dmbakExtension + ); + + /* + Returns: + True if the file is a 3dm archive. + */ + static bool Is3dmFile( + const char* file_path, + bool bAllow3dmbakExtension + ); + + /* + Description: + Open the file and seek to the location where the 3dm archive information begins. + Returns: + A file stream with the current position at the beginning of the 3dm archive. + nullptr if the file is not a 3dm archive. + */ + static FILE* Open3dmToRead( + const wchar_t* file_path + ); + + /* + Description: + Open the file and seek to the location where the 3dm archive information begins. + Returns: + A file stream with the current position at the beginning of the 3dm archive. + nullptr if the file is not a 3dm archive. + */ + static FILE* Open3dmToRead( + const char* file_path + ); + + /* + Description: + Portable wrapper for C runtime ftell(). + Parameters: + fp - [in] + FILE pointer returned by ON_FileStream::Open(). + Returns: + >= 0: current file position + -1: an error occured + */ + static ON__INT64 CurrentPosition( FILE* fp ); + + /* + Description: + Portable wrapper for C runtime fseek(fp,offset,SEEK_CUR). + Parameters: + fp - [in] + FILE pointer returned by ON_FileStream::Open(). + offset - [in] + */ + static bool SeekFromCurrentPosition( FILE* fp, ON__INT64 offset ); + + /* + Description: + Portable wrapper for C runtime fseek(fp,offset,SEEK_SET). + Parameters: + fp - [in] + FILE pointer returned by ON_FileStream::Open(). + offset - [in] + */ + static bool SeekFromStart( FILE* fp, ON__INT64 offset ); + + /* + Description: + Portable wrapper for C runtime fseek(fp,offset,SEEK_END). + Parameters: + fp - [in] + FILE pointer returned by ON_FileStream::Open(). + offset - [in] + */ + static bool SeekFromEnd( FILE* fp, ON__INT64 offset ); + + /* + Description: + Portable wrapper for C runtime fseek(fp,offset,origin). + Parameters: + fp - [in] + FILE pointer returned by ON_FileStream::Open(). + offset - [in] + origin - [in] + SEEK_SET (0): seek from beginning of file. + SEEK_CUR (1): seek from current position of file pointer. + SEEK_END (2): seek from end of file. + */ + static bool Seek( FILE* fp, ON__INT64 offset, int orgin ); + + /* + Description: + Portable wrapper for C runtime fread(buffer,1,count,fp). + Parameters: + fp - [in] + FILE pointer returned by ON_FileStream::Open() + count - [in] + number of bytes to read. + buffer - [out] + read bytes are stored in this buffer + Returns: + number of bytes read + */ + static ON__UINT64 Read( FILE* fp, ON__UINT64 count, void* buffer ); + + /* + Description: + Portable wrapper for C runtime fwrite(buffer,1,count,fp). + Parameters: + fp - [in] + FILE pointer returned by ON_FileStream::Open() + count - [in] + number of bytes to write + buffer - [in] + data to be written + Returns: + number of bytes written. + */ + static ON__UINT64 Write( FILE* fp, ON__UINT64 count, const void* buffer ); + + /* + Description: + Portable wrapper for C runtime fflush(fp). + Parameters: + fp - [in] + FILE pointer returned by ON_FileStream::Open(). + Returns: + true if flush was successful. False if an error occured. + */ + static bool Flush( FILE* fp ); + + /* + Description: + Portable wrapper for C runtime fstat(). + Parameters: + fp - [in] + FILE pointer returned by ON_FileStream::Open(). + file_size - [out] + If file_size is not null, the the size of the file + in bytes returned here + file_metadata_last_modified_time - [out] + If file_metadata_last_modified_time is not null, then the time the + file's metadata (owner, permissions, ...) were last modified is returned + here as the number of seconds since midnight January 1, 1970. + file_contents_last_modified_time - [out] + If file_contents_last_modified_time is not null, then the time the + file's contents were last modified is returned here as the number of + seconds since midnight January 1, 1970. + Returns: + true if the query was successful. False if an error occured. + */ + static bool GetFileInformation( + FILE* fp, + ON__UINT64* file_size, + ON__UINT64* file_metadata_last_modified_time, + ON__UINT64* file_contents_last_modified_time + ); + static bool GetFileInformation( + const wchar_t* file_name, + ON__UINT64* file_size, + ON__UINT64* file_metadata_last_modified_time, + ON__UINT64* file_contents_last_modified_time + ); + static bool GetFileInformation( + const char* file_name, + ON__UINT64* file_size, + ON__UINT64* file_metadata_last_modified_time, + ON__UINT64* file_contents_last_modified_time + ); +}; + +class ON_CLASS ON_ContentHash +{ +public: + static const ON_ContentHash Unset; + +public: + ON_ContentHash() = default; + ~ON_ContentHash() = default; + ON_ContentHash(const ON_ContentHash&) = default; + ON_ContentHash& operator=(const ON_ContentHash&) = default; + + /* + Descripton: + Create an ON_ContentHash class with the specified size, hash and times. + Parameters: + sha1_name_hash - [in] + The SHA-1 hash of the name (typically a full path file name). + When the content is identified by a file name in a file system, + use ON_SHA1_Hash::FileSystemPathHash() to calculate this value. + byte_count - [in] + number of bytes in the content. + sha1_content_hash - [in] + The SHA-1 hash of the content (typically a buffer or file). + You may use ON_SHA1_Has::FileContentHash() or ON_SHA1_Hash::BufferContentHash() + to calculate this value. + hash_time - [in] + The time the sha1_hash was calculated in seconds since January 1, 1970 UCT. + If 0 is passed in, the current time is used. + content_last_modified_time - [in] + Pass 0 if not known. + The time the hashed information that was last modifed in seconds since January 1, 1970 UCT. + If content_last_modified_time > hash_time, then 0 is used. + Returns: + An ON_ContentHash with size and SHA-1 hash and times set from the parameters, + */ + static ON_ContentHash Create( + ON_SHA1_Hash sha1_name_hash, + ON__UINT64 byte_count, + ON_SHA1_Hash sha1_content_hash, + ON__UINT64 hash_time, + ON__UINT64 content_last_modified_time + ); + + /* + Descripton: + Create an ON_ContentHash from a memory buffer. + Parameters: + sha1_name_hash - [in] + A SHA-1 hash of the name associated with this content. + If the buffer has no name, pass ON_SHA1_Hash::ZeroDigest. + If the buffer has an empty name, pass ON_SHA1_Hash::EmptyContentHash. + buffer - [in] + byte_count - [in] + number of bytes in buffer[] + Returns: + An ON_ContentHash with size and SHA-1 hash calculated from the parameters, + hash time = now, and content last modified time = 0. + */ + static ON_ContentHash CreateFromBuffer( + ON_SHA1_Hash sha1_name_hash, + const void* buffer, + size_t byte_count + ); + + /* + Descripton: + Create an ON_ContentHash from a file stream. + Parameters: + sha1_file_name_hash - [in] + A SHA-1 hash of the file name associated with fp. + Use ON_SHA1_Has::FileSystemPathHash() to create the value. + If the name is not known, pass ON_SHA1_Hash::ZeroDigest. + fp - [in] pointer to a file opened with ON:FileOpen(...,"rb") + Returns: + An ON_ContentHash with size and SHA-1 hash and times set from the file, + hash time = now, and content last modifed time set from the file system + information returned by ON_FileStream::GetFileInformation(). + */ + static ON_ContentHash CreateFromFile( + ON_SHA1_Hash sha1_file_name_hash, + FILE* fp + ); + + /* + Descripton: + Create an ON_ContentHash from a file stream. + Parameters: + filename - [in] name of file. + Returns: + An ON_ContentHash with size and SHA-1 hash and times set from the file, + hash time = now, and content last modifed time set from the file system + information returned by ON_FileStream::GetFileInformation(). + */ + static ON_ContentHash CreateFromFile( + const wchar_t* filename + ); + + static ON_ContentHash CreateFromFile( + const char* filename + ); + + /* + Returns: + True if the SHA-1 hash has been set. + */ + bool IsSet() const; + + /* + Returns: + True if the SHA-1 hash is not set. + */ + bool IsNotSet() const; + + /* + Returns: + Number of bytes in the content (typically a file or buffer). + */ + ON__UINT64 ByteCount() const; + + /* + Returns: + Time the hash SHA-1 hash was cacluated in seconds since January 1, 1970 UCT. + */ + ON__UINT64 HashCalculationTime() const; + + /* + Returns: + Time the hashed content was last modifed in seconds since January 1, 1970 UCT. + 0 is returned if this time is not known. + + This time should be used for important decisions as a last resort. + + When hash values differ, this time may be considered to + which content is newer (or most recently copied). + + Unfortunately, in many cases this time is often unknown and incorrectly set. + For example, some file systems set the last modified time of a copy of + an "old" file to the time the copy was created. Thus a copy of "old" content + may appear to be newer than "new" content that has not been copied. + */ + ON__UINT64 ContentLastModifiedTime() const; + + /* + Returns: + SHA-1 hash of the name (typically a full path file name). + */ + ON_SHA1_Hash NameHash() const; + + /* + Returns: + SHA-1 hash of the content (typically a buffer or file). + */ + ON_SHA1_Hash ContentHash() const; + + /* + Description: + Test a buffer to see if it has a matching size and SHA-1 hash. + Parameters: + buffer - [in] + byte_count - [in] + number of bytes in buffer[] + Returns: + True if the buffer has a matching byte_count and SHA-1 hash. + */ + bool IsSameBufferContent( + const void* buffer, + size_t byte_count + ) const; + + /* + Description: + Test a file to see if it has a matching size and SHA-1 hash. + Paramters: + fp - [in] pointer to file opened with ON::OpenFile(...,"rb") + bSkipTimeCheck - [in] if true, the time of last + modification is not checked. + Returns: + True if the file existes, can be read, and has a matching byte_count + and SHA-1 hash. + */ + bool IsSameFileContent( + FILE* fp + ) const; + + /* + Description: + Test a file to see if it has a matching size and SHA-1 content hash. + Paramters: + filename - [in] + Returns: + True if the file exists, can be read, and has a matching byte_count + and SHA-1 content hash. + */ + bool IsSameFileContent( + const wchar_t* filename + ) const; + + bool IsSameFileContent( + const char* filename + ) const; + + /// + /// ON_ContentHash::Compare are the possible results of calling ON_ContentHash::CompareFile(). + /// + enum class CompareResult : unsigned char + { + /// + /// Not set. This value is never returned by ON_ContentHash::CheckFile(). + /// + Unset = 0, + + /// + /// File exists and its size and content matches the information + /// used to set the content hash. + /// + EqualContent = 1, + + /// + /// File exists and its size or content differs from the information + /// used to set the content hash. Unable to reliably determine which + /// is newer. + /// + DifferentContent = 2, + + /// + /// File exists and its size or content differs from the information + /// used to set the content hash. The file's laste modified time + /// is older than ContentLastModifiedTime(). + /// + DifferentContentFileIsOlder = 3, + + /// + /// File exists and its size or content differs from the information + /// used to set the content hash. The file's last modified time + /// is newer than ContentLastModifiedTime(). + /// + ContentDifferentFileIsNewer = 4, + + /// + /// File does not exist. + /// + FileDoesNotExist = 5, + + /// + /// File cannot be opened, read, or some other file system issue prevents checking. + /// + FileSystemFailure = 6 + }; + + static ON_ContentHash::CompareResult CompareResultFromUnsigned( + unsigned int compare_result_as_unsigned + ); + + /* + Description: + Compare the information used to set this content hash with + the contents of the file. + Parameters: + file_path - [in] + bFastCompare - [in] + If bFastCompare is true and the file_path, create time, last modified time, and size + exactly match the values in ON_ContentHash, then + ON_ContentHash::CompareResult::EqualContent is returned + without performing the expensive SHA1 test on the file's content. + If bFastCompare is false, the SHA-1 hash of the file's content will be + calculated and compared before ON_ContentHash::CompareResult::EqualContent + is returned. + Returns: + Result of compare test as a ON_ContentHash::CompareResult enum. + ON_ContentHash::CompareResult::DifferentContentFileIsOlder means file_path content is different and older than "this". + ON_ContentHash::CompareResult::DifferentContentFileIsNewer means file_path content is different and newer than "this". + */ + ON_ContentHash::CompareResult Compare( + const wchar_t* file_path, + bool bFastTest + ) const; + + /* + Description: + Compare the byte count and SHA-1 content hash. + Parameters: + file_content_hash - [in] + ON_ContentHash to compare against this one. + Returns: + Result of compare test as a ON_ContentHash::CompareResult enum. + ON_ContentHash::CompareResult::DifferentContentFileIsOlder means file_content_hash is different and older than "this". + ON_ContentHash::CompareResult::DifferentContentFileIsNewer means file_content_hash is different and newer than "this". + */ + ON_ContentHash::CompareResult Compare( + ON_ContentHash file_content_hash + ) const; + + /* + Returns: + true if a and b have identical ByteCount() and SHA-1 content hash values. + */ + static bool EqualContent( + const ON_ContentHash& a, + const ON_ContentHash& b + ); + + /* + Returns: + true if a and b have differnt ByteCount() or SHA-1 content hash values. + */ + static bool DifferentContent( + const ON_ContentHash& a, + const ON_ContentHash& b + ); + + + /* + Description: + Compares content byte count and content SHA-1 + */ + static int CompareContent( + const ON_ContentHash& a, + const ON_ContentHash& b + ); + + /* + Description: + Compares all fields + */ + static int Compare( + const ON_ContentHash& a, + const ON_ContentHash& b + ); + + /* + Parameters: + filename - [in] + Returns: + True if the file exists, has size > 0, has the same name, same size, and same last modified time + than this content hash. + False otherwise. + Remarks: + Faster than the ON_ContentHash::EqualContent() and reliable if this content + hash was set on the same file system. + Unreliable if the file system does not correctly set last modified times + or the file was modified less than 2 seconds before the call. + */ + bool EqualFileNameSizeAndTime( + const wchar_t* filename + ) const; + + bool Write( + class ON_BinaryArchive& archive + ) const; + + bool Read( + class ON_BinaryArchive& archive + ); + + void Dump( + class ON_TextLog& text_log + ) const; + +private: + // Number of bytes in the buffer or file + ON__UINT64 m_byte_count = 0; + + // Time this hash was set (always > 0 if this ON_ContentHash is set). + ON__UINT64 m_hash_time = 0; // number of seconds since Jan 1, 1970, UCT + + // Time the content was last modifed. + // This time is often unknown, or set incorrectly. + ON__UINT64 m_content_time = 0; // number of seconds since Jan 1, 1970, UCT + + // SHA-1 hash of the content name (file name or other assigned name) + ON_SHA1_Hash m_sha1_name_hash = ON_SHA1_Hash::ZeroDigest; + + // SHA-1 hash of the content (buffer or file). + ON_SHA1_Hash m_sha1_content_hash = ON_SHA1_Hash::ZeroDigest; +}; + +class ON_CLASS ON_FileReference +{ +public: + static const ON_FileReference Unset; + +#pragma region RH_C_SHARED_ENUM [ON_FileReference::Status] [Rhino.FileIO.FileReferenceStatus] [int] + ///Enumerates a list of file statuses. + enum class Status : unsigned int + { + /// + /// Status of a the full path is not known. + /// + Unknown = 0, + + /// + /// Full path is valid. + /// + FullPathValid = 1, + + /// + /// Unable to locate file. + /// + FileNotFound = 2 + }; +#pragma endregion + + static int Compare( + const ON_FileReference& a, + const ON_FileReference& b + ); + + static ON_FileReference::Status StatusFromUnsigned( + unsigned int full_path_status_as_unsigned + ); + + ON_FileReference() = default; + ~ON_FileReference() = default; + ON_FileReference(const ON_FileReference&) = default; + ON_FileReference& operator=(const ON_FileReference&) = default; + + ON_FileReference( + const wchar_t* full_path, + const wchar_t* relative_path, + ON_ContentHash content_hash, + ON_FileReference::Status full_path_status + ); + + static ON_FileReference CreateFromFullPath( + const wchar_t* full_path, + bool bSetContentHash, + bool bSetFullPathStatus + ); + +#pragma region RH_C_SHARED_ENUM [ON_FileReference::FindFilePreference] [Rhino.FileIO.FileFindPreference] [int] + ///Defines options for file search. + enum class FindFilePreference : unsigned char + { + ///The choice is not defined. + None = 0, + + ///File name exists in FullPath(). + FullPath = 1, + + ///File name exists in base path + RelativePath(). + RelativePath = 2, + + ///File name exists in base path directory. + BasePath = 3, + + ///File with mathing content exists. + ContentMatch = 4, + + ///Most recently modifed file. + MostRecent = 5 + }; +#pragma endregion + + /* + Description: + Uses the full path, relative path and parameter information to find a + full path to a file that exists. + Parameters: + base_path - [in] + If base_path and RelativePath() are not empty, then path base_path+RelativePath(). + If base_path is not empty, then base_path + filename is considered. + bBasePathIncludesFileName - [in] + True if base_path contains a file name that must be removed to get a directory path. + first_choice - [in] + When multiple files are found in different locations, the first_choice, second_choice, + third_choice, forth_choice, and fifth_choice parameters are used to select which file + is returned. + second_choice - [in] + When multiple files are found in different locations, the first_choice, second_choice, + third_choice, forth_choice, and fifth_choice parameters are used to select which file + is returned. + third_choice - [in] + When multiple files are found in different locations, the first_choice, second_choice, + third_choice, forth_choice, and fifth_choice parameters are used to select which file + is returned. + forth_choice - [in] + When multiple files are found in different locations, the first_choice, second_choice, + third_choice, forth_choice, and fifth_choice parameters are used to select which file + is returned. + fifth_choice - [in] + When multiple files are found in different locations, the first_choice, second_choice, + third_choice, forth_choice, and fifth_choice parameters are used to select which file + is returned. + full_path - [out] + A full path to a file that exists. + If FullPath() and base_path+RelativePath() resolve to different files, + the content hash information is used to select the file. + Returns: + If the file is found, then the returned ON_FileReference::FindFilePreference enum value + indicates why it was selected. + If the file is not found, then ON_FileReference::FindFilePreference::None is returned + and full_path is empty. + Remarks: + The locations FullPath(), base_path+RelativePath(), and base_path+FileName() are tested. + If multiple files are found, first_choice, second_choice, third_choice, forth_choice, + and fifth_choice are used to select which file is returned. + */ + ON_FileReference::FindFilePreference FindFile( + const wchar_t* base_path, + bool bBasePathIncludesFileName, + ON_FileReference::FindFilePreference first_choice, + ON_FileReference::FindFilePreference second_choice, + ON_FileReference::FindFilePreference third_choice, + ON_FileReference::FindFilePreference forth_choice, + ON_FileReference::FindFilePreference fifth_choice, + ON_wString& found_file_full_path + ) const; + + /* + Description: + Uses the full path, relative path and parameter information to find a + full path to a file that exists. + Parameters: + base_path - [in] + If base_path and RelativePath() are not empty, then path base_path+RelativePath(). + If base_path is not empty, then base_path + filename is considered. + bBasePathIncludesFileName - [in] + True if base_path contains a file name that must be removed to get a directory path. + Returns: + If the file is found, then the returned ON_FileReference::FindFilePreference enum value + indicates why it was selected. + If the file is not found, then ON_FileReference::FindFilePreference::None is returned + and full_path is empty. + Remarks: + The locations FullPath(), base_path+RelativePath(), and base_path+FileName() are tested. + If multiple files are found, the returned file is selected in the order + relative path, full path, content match, base path and most recently modified. + If you prefer a different order, use the version of ON_FileReference::FindFile + with 5 ON_FileReference::FindFilePreference parameters. + */ + ON_FileReference::FindFilePreference FindFile( + const wchar_t* base_path, + bool bBasePathIncludesFileName, + ON_wString& found_file_full_path + ) const; + + /* + Description: + The search for the file is identical to the one performed by find file. + If a file is found, the full path setting in this reference is updated. + */ + ON_FileReference::FindFilePreference FindFileAndUpdateReference( + const wchar_t* base_path, + bool bBasePathIncludesFileName, + ON_FileReference::FindFilePreference first_choice, + ON_FileReference::FindFilePreference second_choice, + ON_FileReference::FindFilePreference third_choice, + ON_FileReference::FindFilePreference forth_choice, + ON_FileReference::FindFilePreference fifth_choice, + bool bUpdateContentHash, + ON_wString& found_file_full_path + ); + + /* + Description: + The search for the file is identical to the one performed by find file. + If a file is found, the full path setting in this reference is updated. + */ + ON_FileReference::FindFilePreference FindFileAndUpdateReference( + const wchar_t* base_path, + bool bBasePathIncludesFileName, + bool bUpdateContentHash, + ON_wString& found_file_full_path + ); + + ON_FileReference::FindFilePreference FindFileAndUpdateReference( + const wchar_t* base_path, + bool bBasePathIncludesFileName, + bool bUpdateContentHash + ); + + /* + Returns: + True if FullPath() is not empty. + */ + bool IsSet() const; + + /* + Returns: + True if FullPath() is empty. + */ + bool IsNotSet() const; + + /* + Parameters: + bUseArchiveBasePath - [in] + If bUseArchiveBasePath is true and a file is being written, then the + base path of the file being written use used as the base path to + calculate the relative path. + If bUseArchiveBasePath is false, then the current value of RelativePath() + is saved in the archive. + */ + bool Write( + bool bUseArchiveDirectoryAsBasePath, + ON_BinaryArchive& archive + ) const; + + /* + Parameters: + base_path - [in] + If base_path is not empty, then the relative path saved + in the archive will be calculated from FullPath() and base_path. + If base_path is nullptr or empty, then RelativePath() is saved in + the archive. + */ + bool Write( + const wchar_t* base_path, + bool bBasePathIncludesFileName, + ON_BinaryArchive& archive + ) const; + + /* + Remarks: + Calling Read() sets m_full_path_status = ON_FileReference::Status::Unknown, + even if that was not the status when Write() was called. + */ + bool Read( + ON_BinaryArchive& archive + ); + + void Dump( + class ON_TextLog& text_log + ) const; + + unsigned int SizeOf() const; + + const ON_wString& FullPath() const; + const wchar_t* FullPathAsPointer() const; + void SetFullPath( + const wchar_t* full_path, + bool bSetContentHash + ); + void SetFullPath( + const char* full_path, + bool bSetContentHash + ); + void ClearFullPath(); + + const ON_wString& RelativePath() const; + const wchar_t* RelativePathAsPointer() const; + void SetRelativePath( + const wchar_t* relative_path + ); + void SetRelativePath( + const char* relative_path + ); + void SetRelativePathFromBasePath( + const wchar_t* base_path, + bool bBasePathContainsFileName + ); + void SetRelativePathFromBasePath( + const char* base_path, + bool bBasePathContainsFileName + ); + void ClearRelativePath(); + + /* + Returns: + File content hash. This value is persistent, saved in 3dm archive, + and could have been calculated a long time ago on a different computer. + */ + const ON_ContentHash& ContentHash() const; + void SetContentHash( + ON_ContentHash content_hash + ); + void ClearContentHash(); + + bool UpdateContentHash(); + + /* + Returns: + Parameters: + recent_time - [in] + The time, in number of seconds since January 1, 1970 UTC, to use + when deciding what content hashes can be considered recent. + If recent_time is 0 or in the future, then the current value of + ON_SecondsSinceJanOne1970UTC() is used. + Typically this parameter is the value of ON_SecondsSinceJanOne1970UTC() + at the beginning of a calculation durint which any referenced files will + not be changed. + Returns: + A file content hash value calculated on or after a specified time in the current + instance of the application. This value is used to detect changed files + in the current instance of the application. It is cached for performance reasons. + This value is never saved in 3dm files. + */ + const ON_ContentHash& RecentContentHash( + ON__UINT64 recent_time + ) const; + + /* + Returns: + ON_SHA1_Hash::FileSystemPathHash(FullPath()); + Remarks: + The value of the hash is saved in a runtime cache so + using this function when comparing paths is efficient + when multple compares are required. + See Also: + ON_NameHash::CreateFilePathHash( ON_FileReference& file_reference ); + */ + const ON_SHA1_Hash& FullPathHash() const; + + ON_FileReference::Status FullPathStatus() const; + void SetFullPathStatus( + ON_FileReference::Status full_path_status + ); + + ON_UUID EmbeddedFileId() const; + void SetEmbeddedFileId( + ON_UUID embedded_file_id + ); + +private: + ON_wString m_full_path; + ON_wString m_relative_path; + + // If the referenced file is saved in the model as an embedded file, + // the ON_BinaryArchive read code sets m_embedded_file_id + // at read time. + mutable ON_UUID m_embedded_file_id = ON_nil_uuid; + + // file content hash. Can be calculated long ago, on a different computer, + // and is saved in 3dm archived. + ON_ContentHash m_content_hash; // File content hash. + + mutable ON_ContentHash m_recent_content_hash; + + // m_full_path_hash is chached runtime information. The value is not saved + // in .3dm archives. It is calculated on demand. + mutable ON_SHA1_Hash m_full_path_hash = ON_SHA1_Hash::EmptyContentHash; // File path hash. + + ON_FileReference::Status m_full_path_status = ON_FileReference::Status::Unknown; + +private: + ON_FileReference::FindFilePreference Internal_FindFile( + const wchar_t* base_path, + bool bBasePathIncludesFileName, + const ON_FileReference::FindFilePreference* file_preference, + unsigned int file_preference_count, + ON_wString& found_file_full_path, + ON_ContentHash* found_file_content_hash + ) const; +}; + +/* +Description: + Iterates through every item in a file system directory. +*/ +class ON_CLASS ON_FileIterator +{ +public: + ON_FileIterator() = default; + ~ON_FileIterator(); + +private: + ON_FileIterator(const ON_FileIterator&) = delete; + ON_FileIterator& operator=(const ON_FileIterator&) = delete; + +public: + + ////////////////////////////////////////////////////////////////////////////////// + // + // Iteratation initialization tools + // + /* + Description: + Initialize where the search should occur. + Parameters: + directory_name - [in] + The directory to look in. + item_name_filter - [in] + If this paramter is null, then the iteration + includes all names in the directory. + The item name to search for. This parameter can + include wildcard characters, such as an + asterisk (*) or a question mark (?). For example, + "\rootdir\subdir\*.*" will iterate all files in + the \rootdir\subdir\ directory. + + Returns: + true: + The iterator is set to the first item. + false: + There are no matching items. + + Remarks: + Calling FirstItem() is eqivalent to calling Initialize() and then calling NextItem(). + */ + bool Initialize( + const wchar_t* directory_name + ); + bool Initialize( + const wchar_t* directory_name, + const wchar_t* item_name_filter + ); + bool Initialize( + const char* directory_name + ); + bool Initialize( + const char* directory_name, + const char* item_name_filter + ); + + ////////////////////////////////////////////////////////////////////////////////// + // + // Iteratation iteration tools + // + + /* + Description: + Find the first matching item in the directory. + Example: + // Iterate through the files in a directory named "\rootdir\subdir" + ON_FileIterator fit; + fit.Initialize("\\rootdir\\subdir"); + for ( bool bHaveItem = fit.FirstItem(); bHaveItem; bHaveItem = fit.NextItem() ) + { + if ( fit.CurrentFileIsDirectory() ) + continue; + ON_String fullpath = fit.CurrentItemFullPathName(); + FILE* fp = ON_FileStream::Open(fullpath,"rb"); + if ( 0 == fp ) + { + continue; + } + ... + ON_FileStream::Close(fp); + fp = 0; + } + } + + Returns: + true: + The iterator is set to the first item. + false: + There are no matching items. + */ + bool FirstItem(); + + /* + Description: + Find the next matching item in the directory. + Returns: + true: + The iterator was advanced to the next item. + false: + There are no more matching items. + */ + bool NextItem(); + + /* + Description: + Reset this ON_FileIterator so it can be used again. + */ + void Reset(); + + ////////////////////////////////////////////////////////////////////////////////// + // + // Current item query + // + + /* + Returns: + Current file or directory name in the directory being iterated. + Use CurrentFullPathItemName() to get the full path name. + */ + const ON_wString CurrentItemName() const; + + /* + Returns: + The name of the directory being iterated. + */ + const ON_wString DirectoryName() const; + + /* + Returns: + If the current item is a file, then the size of the file in bytes is returned. + If the current item is a directory, then 0 is returned. + */ + ON__UINT64 CurrentItemSize() const; + + /* + Returns + true if the current item is a directory. + */ + bool CurrentItemIsDirectory() const; + + /* + Returns + true if the current item is a file. + */ + bool CurrentItemIsFile() const; + + /* + Returns + true if the current file or directory is hidden. + This means its name begins with a '.' or it's + Windows hidden attribute is true. + */ + bool CurrentItemIsHidden() const; + + const ON_wString CurrentItemFullPathName() const; + + /* + Returns: + File last modified time in seconds since January 1, 1970 + Remarks: + The times returned by ON_FileIterator can differ from the time + returned by ON_FileStream::GetFileInformation(). + */ + ON__UINT64 CurrentItemLastModifiedTime() const; + + /* + Returns: + Number of matching items iterated through. + */ + ON__UINT64 CurrentItemCount() const; + +private: + ON__UINT32 m_state = 0; // 0 unset, 1=initialized, 2 = itereation in progress. 3 = iteration finished. + ON__UINT32 m_reserved = 0; + + ON_wString m_directory; // directory passed to Initialize() or FirstItem + ON_wString m_item_name_filter; // item_name_filter passed to Initialize() or FirstItem + ON_wString m_item_name; // Current item name. + + // cached full path name + // m_directory + directory separator + m_item_name + // (length = 0 if it is not set) + mutable ON_wString m_full_path_name; + + ON__UINT64 m_count = 0; // number of items iterated through so far + class ON_DirectoryIteratorImpl* m_impl = nullptr; +}; + +#endif diff --git a/opennurbs/Include/opennurbs_font.h b/opennurbs/Include/opennurbs_font.h new file mode 100644 index 0000000..2c32077 --- /dev/null +++ b/opennurbs/Include/opennurbs_font.h @@ -0,0 +1,6674 @@ +// +// Copyright (c) 1993-2015 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// + + +#if !defined(OPENNURBS_FONT_INC_) +#define OPENNURBS_FONT_INC_ + + +/// +/// https://monotype.github.io/panose/pan1.htm +/// +class ON_CLASS ON_PANOSE1 +{ +public: + ON_PANOSE1() = default; + ~ON_PANOSE1() = default; + ON_PANOSE1(const ON_PANOSE1&) = default; + ON_PANOSE1& operator=(const ON_PANOSE1&) = default; + + /// + /// PANOSE 1.0 font family kind + /// + /// The overall genre of the alphabet or script that is being described + /// is signified by the Family Kind digit. This digit consists of two parts: + /// the script kind identifier and the genre kind identifier. + /// In this case, the script identifier is Latin, and the genre type is described as Text, + /// Hand Written, Decorative or Symbol. + + /// The Family Kind digit is not controlled by specific measurements, + /// and there has been no attempt to mathematically determine the + /// appropriate category for a given font design. Visual and aesthetic + /// classification of Latin faces that are obviously script, decorative, + /// or symbol fonts is required. + /// + enum class FamilyKind : ON__UINT8 + { + /// "Any" means match that digit with any available digit, which allows the mapper to handle distortable typefaces. + Any = 0, + + /// "No Fit" means that the item being classified does not fit within the PANOSE 1.0 classification system. + NoFit = 1, + + /// + /// To decide whether a font belongs to the Latin Text group follow the two step process below. + /// + /// A. Answer the following three questions. If they are all yes, then it belongs in this group. + /// If the answer is still ambiguous, go to step B. + /// + /// Does the font belong to a family that includes italic versions? + /// Most fonts in this group have a variety of weights and most include italic versions. + /// + /// Are the characters in the font made up of standard topologies constructed of standard parts? + /// + /// Is some portion of the font suitable for composing a paragraph of text? + /// + /// B. As a final tie breaker, look at the second digit of the Decorative (Section 4) + // and Handwritten (Section 3) families and see if there is something in them that + /// fits the font in question better. + /// https://monotype.github.io/panose/pan2.htm + /// + LatinText = 2, + + /// + /// Many fonts are clearly scripts and unrelated to any book face. On occasion, + /// though, the distinction gets rather vague. A good rule of thumb is that if + /// the cursive font is part a family that includes a book face, then it should + /// be classified in the Latin Text group. If it is freestanding with no obvious + /// related book face, then it falls into the Latin Hand Written group. This can + /// be a bit difficult to determine, since a font house may only choose to provide + /// the cursive from a larger family, so the classifier needs to think about the + /// face being processed and not do it purely by rote. + /// https://monotype.github.io/panose/pan3.htm + /// + LatinScript = 3, + + /// + /// Latin Decorative faces are those that are designed more for impact than readability. + /// Usually Decoratives are used singly or in small groups, for special purposes. + /// Small cap fonts are also included in this group because they have become unusual + /// enough to be considered special purpose fonts. + /// https://monotype.github.io/panose/pan4.htm + /// + LatinDecorative = 4, + + /// + /// Latin Symbol is where all the nonalphabetic fonts reside. These are fonts that can be loaded + /// like normal text fonts, but do not contain readable characters. Dingbats and specialized + /// symbol fonts are two examples. + /// https://monotype.github.io/panose/pan5.htm + /// + LatinSymbol = 5 + }; + + /* +Special values "Any" (0) and "No Fit" (1) exist for every category, which have specific meanings to the mapper. +*/ + + /* + Description: + In the rare cases when an ON_PANOSE1::Classification value must be passed + as an unsigned int, use ON_PANOSE1::ClassificationFromUnsigned() to + convert the unsigned value to an ON_PANOSE1::Classification value. + Parameters: + unsigned_panose_family_kind - [in] + */ + static ON_PANOSE1::FamilyKind FamilyKindFromUnsigned( + unsigned int unsigned_panose_family_kind + ); + + static const wchar_t* FamilyKindToWideString( + ON_PANOSE1::FamilyKind family_kind + ); + + static const ON_PANOSE1 Zero; // All PANOSE 1.0 values are zero, which means (Any,Any,...,Any) + + /* + Returns: + True if every PANOSE 1.0 value is zero which means there is no useful + font classification information in the instance. + */ + bool IsZero() const; + + /* + Returns: + True if every PANOSE 1.0 value is zero or one which means there is no useful + font classification information in the instance. + */ + bool IsZeroOrOne() const; + + /* + Returns: + True if some PANOSE 1.0 value is not zero and not one. This means this + PANOSE 1.0 information may be useful in searching for similar fonts. + */ + bool IsSet() const; + + ON_PANOSE1::FamilyKind PANOSE1FamilyKind() const; + + /* + Returns: + A pointer to an array of 10 bytes of PANOSE 1 classification properties. + The initial byte is the PANOSE 1 Classification and is identical + to the value returned by FontClassification(). + The interpretation of the following 9 bytes depends on the + value of the first byte. If the initial byte is + 0 = ON_FontPANOSE1::Classification::Any (0) + or 1 = ON_FontPANOSE1::Classification::NoFit, + then these 9 bytes have no meaning. + */ + const ON__UINT8* TenBytes() const; + + /* + Parameters: + classification - [in] + PANOSE 1.0 font classification + panose1_properties_bytes - [in] + Array of 9 bytes of PANOSE1 properties + */ + void SetTenBytes(const ON__UINT8* panose1_ten_bytes); + + /* + Parameters: + family_kind - [in] + PANOSE 1.0 font Family kind classification + panose1_properties_bytes - [in] + Array of 9 bytes of PANOSE1 properties + */ + void SetNineBytes( + ON_PANOSE1::FamilyKind family_kind, + const ON__UINT8* panose1_properties_bytes + ); + + void Dump( + class ON_TextLog& text_log + ) const; + + bool Write( + class ON_BinaryArchive& archive + ) const; + + bool Read( + class ON_BinaryArchive& archive + ); + +private: + // PANOSE 1.0 properties (10 bytes) + // // text / script / decrorative / symbol + ON_PANOSE1::FamilyKind m_family_kind = ON_PANOSE1::FamilyKind::Any; + + // The interpretation of the m_prop* values depends on the value of m_family_kind. + // + // For every classification property, + // 0 = "Any" and means match that digit with any available digit, which allows the mapper to handle distortable typefaces. + // 1 = "No Fit" means that the item being classified does not fit within the PANOSE 1.0 classification system. + // Additional values need to be + + // Classification // Latin text / Latin script / Latin decrorative / Latin symbol + ON__UINT8 m_prop1 = 0; // serif style / tool kind / decorative class / symbol kind + ON__UINT8 m_prop2 = 0; // weight / weight / weight / weight + ON__UINT8 m_prop3 = 0; // proportion / spacing / aspect / spacing + ON__UINT8 m_prop4 = 0; // contrast / aspect ratio / contrast / aspect ration and contrast + ON__UINT8 m_prop5 = 0; // stroke variation / contrast / serif variant / aspect ratio 94 + ON__UINT8 m_prop6 = 0; // arm style / script topology / fill / aspect ratio 119 + ON__UINT8 m_prop7 = 0; // letter form / script form / lining / aspect ratio 157 + ON__UINT8 m_prop8 = 0; // midline / finials / decorative topology / aspect ratio 163 + ON__UINT8 m_prop9 = 0; // x-height / x-ascent / character range / aspect ratio 211 +}; + +class ON_CLASS ON_FontMetrics +{ +public: + ON_FontMetrics() = default; + ~ON_FontMetrics() = default; + ON_FontMetrics(const ON_FontMetrics&) = default; + ON_FontMetrics& operator=(const ON_FontMetrics&) = default; + + +public: + // All properties are zero. + static const ON_FontMetrics Unset; + + + // Used when it is impossible to find normalized font metrics (missing font for example) + // and something valid is required for a computation. + static const ON_FontMetrics LastResortNormalizedMetrics; + + // Used when it is impossible to find font metrics (missing font for example) + // and something valid is required for a computation. + // Currently LastResortMetrics.UPM() is 2048 and this value is chosen because + // it is the largest common UPM found in real fonts encountered in March 2018. + static const ON_FontMetrics LastResortMetrics; + + + /* + ON_FontMetric::DefaultLineFeedRatio*ON_FontMetrics().AscentOfCapital() + can be used to cook up a line space value when using the + ON_FontMetrics.LineSpace() value defined by the font is + not desired. + */ + static const double DefaultLineFeedRatio; // 1.6 + + // UNICODE code point of the glyph used to determine HeightOfCapital() + // when no reaonable value is available from the font definition. + // Currently this is the 'I' glyph. Opennurbs has used 'I' since 2005. + // It is possible 'H' would work as well. All other glyphs, in + // particular 'M' and 'W', do not work. + static const ON__UINT32 HeightOfCapitalCodePoint; // 'I' + +public: + /* + Returns: + Signed distance from the baseline to highest point on a glyph outline. + + Remarks: + If every glyph outline in the font has (0,0) on the basline, then Ascent() + is the maximum glyph bounding box Y. + + Ascent typically includes internal leading, the space used for + diacritcial marks above capital latin letters. For this reason, + Ascent is typically greater than AscentOfCapital. + + Windows: = DWRITE_FONT_METRICS.ascent + */ + int Ascent() const; + + /* + Returns: + Signed distance from the English baseline to lowest point on a glyph outline. + + Remarks: + This value is typically negative because glyphs for letters like 'g' and 'j' + typically have a portion of their outline below the baseline. However, + some fonts have positive descent. + If every glyph outline in the font has (0,0) on the basline, then Descent() + is the minimum glyph bounding box Y. + + Windows: = -DWRITE_FONT_METRICS.descent + */ + int Descent() const; + + /* + Returns: + The postive distance to move the base line when moving to a new line of text. + + Remarks: + For almost every font used to render English text, LineSpace() > (Ascent() - Descent()). + + This metric is sometimes called "height", but that term is often confused + with (Ascent() - Descent()). + + For fonts designed to render horizontal lines of text, LineSpace() is a + vertical distance. For fonts desingned to render vertical lines of text, + LineSpace() is a horizontal distance. Depending on the context, the + direction to move can be up, down, left or right. + + Windows: = DWRITE_FONT_METRICS.ascent + + DWRITE_FONT_METRICS.descent + + DWRITE_FONT_METRICS.lineGap; + */ + int LineSpace() const; + + /* + Returns: + The "units per EM". This is the height and width of the square grid + where the font glyphs are designed. + Remarks: + The width of the 'M' glyph in a font can be different from UPM. + The height of the 'M' glyph in a font is typically less than UPM. + In TrueType fonts, UPM is often a power of two and generally 1024 or 2048. + In OpenType fonts, UPM is often 1000. + In PostScript fonts, UPM is often 1000. + + Windows: = DWRITE_FONT_METRICS.designUnitsPerEm + */ + int UPM() const; + + /* + Returns: + AscentOfCapital() + */ + int AscentOfI() const; + + /* + Returns: + The font's typographic capital height. + + Remarks: + The primary uses of AscentOfCapital() are: + 1) + Calculate a scale factor to produce text with a user specified "text height". + 2) + To calculate insertion location for ON::TextVerticalAlignment::Middle + and ON::TextVerticalAlignment::Top. + + From 2005-2018 opennurbs used the ascent of a capital I. + Beginning in 2018 this value is taken from the system font metrics + so that fonts designed to render Asian language text, symbols, + and emojis will display as expected and lines of text containing + mulitiple fonts will render more clearly. + + The value (user specified text height)/AscentOfCapital() is used + as the scale factor to render glyphs when user interface has provided + a "text height" value. + + If the capial height property of a font is not + available, the ascent of I or H can be used instead. (There are + commonly used fonts where using other glpyhs gives undesirable results.)OfI. + + Windows: = DWRITE_FONT_METRICS.capHeight + Apple: = CTFontGetAscent(...) + */ + int AscentOfCapital() const; + + + /* + Returns: + The font's typographic x-height. + + Remarks: + The x-height is used to help select a substitute font to use for missing glpyhs. + */ + int AscentOfx() const; + + + /* + Description: + Parameters: + height_of_capital - [in] + The desired height of typical capital latin letter glyphs. + For fonts like Arial, Helvetica, and Times Roman the + heights of the H and I glyphs = font's height of capital. + Returns: + text_height / AscentOfCapital(). + */ + double GlyphScale(double text_height) const; + + /* + Returns: + Thickness of strikeout. + Remarks: + The signed distance from the baseline to the bottom of the strikeout + is StrikeoutPosition() - StrikeoutThickness()/2. + */ + int StrikeoutThickness() const; + + /* + Returns: + Signed distance from baseline to center of strikeout. + A positive value indicates the strikeout is above the baseline (common). + Remarks: + The signed distance from the baseline to the bottom of the strikeout + is StrikeoutPosition() - StrikeoutThickness()/2. + */ + int StrikeoutPosition() const; + + + /* + Returns: + Thickness of underscore + Remarks: + The signed distance from the baseline to the bottom of the underscore + is UnderscorePosition() - UnderscoreThickness()/2. + */ + int UnderscoreThickness() const; + + /* + Returns: + Signed distance from baseline to center of underscore. + A negative value indicates the underscore is below the baseline (common). + Remarks: + The signed distance from the baseline to the bottom of the underscore + is UnderscorePosition() - UnderscoreThickness()/2. + */ + int UnderscorePosition() const; + + static const ON_FontMetrics Scale( + const ON_FontMetrics& font_metrics, + double scale + ); + + static const ON_FontMetrics Normalize( + const ON_FontMetrics& font_metrics + ); + + void SetHeights( + int ascent, + int descent, + int UPM, + int line_space + ); + + void SetAscentOfI( + int ascent_of_capital + ); + + void SetAscentOfCapital( + int ascent_of_capital + ); + + void SetAscentOfx( + int ascent_of_x + ); + + void SetStrikeout( + int strikeout_position, + int strikeout_thickness + ); + + void SetUnderscore( + int underscore_position, + int underscore_thickness + ); + + void SetHeights( + double ascent, + double descent, + double UPM, + double line_space + ); + + void SetAscentOfCapital( + double ascent_of_capital + ); + + void SetAscentOfx( + double ascent_of_x + ); + + void SetStrikeout( + double strikeout_position, + double strikeout_thickness + ); + + void SetUnderscore( + double underscore_position, + double underscore_thickness + ); + + /* + Returns: + True if all of the following are true. + UPM() > 0 + At least one of Ascent() or Descent() is not zero. + Ascent() > Descent() + None of UPM(), Ascent(), or Descent() is ON_UNSET_INT_INDEX or -ON_UNSET_INT_INDEX. + */ + bool AscentDescentAndUPMAreValid() const; + + /* + Returns: + True if all of the following are true. + AscentDescentAndUPMAreValid() is true + LineSpace() >= Ascent() - Descent() + AscentOfCapital() <= Ascent() + AscentOfx() <= Ascent() + */ + bool HeightsAreValid() const; + + /* + Returns: + True if all of the following are true. + HeightsAreValid() is true. + AscentOfCapital() > 0 + */ + bool IsSetAndValid() const; + + /* + Returns true if at least one metric is not zero. + */ + bool IsSet() const; + + /* + Returns true if all metrics are zero + */ + bool IsUnset() const; + + void Dump(class ON_TextLog& text_log) const; + +#if defined(ON_OS_WINDOWS_GDI) + static const ON_FontMetrics CreateFromDWriteFontMetrics(const struct DWRITE_FONT_METRICS* dwrite_font_metrics); + static const ON_FontMetrics CreateFromDWriteFont(struct IDWriteFont* dwrite_font); +#endif + +private: + int m_UPM = 0; // units per EM + int m_ascent = 0; // max over all glyphs in font of (highest outline point - baseline point).y + int m_descent = 0; // min over all glyphs in font of (lowest outline point - baseline point).y + int m_line_space = 0; // distance between baselines + ON__UINT16 m_ascent_of_capital = 0; + ON__UINT16 m_ascent_of_x = 0; // same units as m_ascent_of_capital + + int m_strikeout_thickness = 0; // + int m_strikeout_position = 0; // + + int m_underscore_thickness = 0; // + int m_underscore_position = 0; // + +private: + int m_reserved1 = 0; + double m_reserved2 = 0.0; + double m_reserved3 = 0.0; + ON__UINT_PTR m_reserved_ptr = 0; +}; + +class ON_CLASS ON_TextBox +{ +public: + ON_TextBox() = default; + ~ON_TextBox() = default; + ON_TextBox(const ON_TextBox&) = default; + ON_TextBox& operator=(const ON_TextBox&) = default; + + ON_TextBox( + ON_2dPoint bbmin, + ON_2dPoint bbmax + ); + +#if defined(ON_OS_WINDOWS_GDI) + static const ON_TextBox CreateFromDWriteGlyphMetrics(const struct DWRITE_GLYPH_METRICS* dwrite_glyph_metrics); +#endif + + /* + Returns: + true if bounding box is set. + */ + bool IsSet() const; + + static const ON_TextBox Scale( + const ON_TextBox& text_box, + double scale + ); + + /* + Returns: + A text box with m_bbmin, m_bbmax, m_max_basepoint are translated by delta. + m_advance is not changed. + */ + static const ON_TextBox Translate( + const ON_TextBox& text_box, + const ON_2dVector& delta + ); + + static const ON_TextBox Translate( + const ON_TextBox& text_box, + const ON_2dex& delta + ); + + /* + Parameters: + lhs - [in] + lhs.m_advance is ignored + rhs - [in] + rhs.m_advance is ignored + Returns: + Returned m_bbmin, m_bbmax, m_max_basepoint are the union of the lhs and rhs bounding box. + Returned m_advance = (0,0) + */ + static const ON_TextBox Union( + const ON_TextBox& lhs, + const ON_TextBox& rhs + ); + + void Dump(class ON_TextLog& text_log) const; + +public: + static const ON_TextBox Unset; + +public: + // The use context determines the length units. Common units include font glyph design units, + // normalizied font design units, various display units. Typically x increases to the right, + // y increases upwards. For glyph and text run boxes, (0,0) is the horizontal base + // + ON_2dex m_bbmin = ON_2dex::Unset; + ON_2dex m_bbmax = ON_2dex::Unset; + + // m_max_basepoint.i = maximum horizontal delta in any line. Increases to the right, decreases to the left. + // m_max_basepoint.i = vertical delta to basline of bottom line. Increases upward, decreases downward. + ON_2dex m_max_basepoint = ON_2dex::Zero; + + // m_advance is a vector that specifies where the basepoint should be moved + // to after the text is rendered. m_advance.i and m_advance.j are always >= 0. + // When glyphs are rendered right to left (Arabic and Hebrew being examples) + // or bottom to top, the rendering code must apply the correct sign. Some + // reasons for using positive advance values for every glyph is that left to right + // and right to left languages can be appear on a single line and the sign of y + // associated with "up" is sometimes positive and sometimes negative. + // ON_TextBox::Translate does not modify the vector m_advance. + // ON_TextBox::Union ignored input advance values and returns a box with advance = (0,0). + // 0 <= m_advance.i will be <= m_max_basepoint.i. + ON_2dex m_advance = ON_2dex::Zero; + + + // NOTE: + // When the SDK can be broken, this class needs another int = verticalOriginY. + // verticalOriginY is required when placing glyphs vertically. +}; + +class ON_CLASS ON_OutlineFigurePoint +{ +public: + ON_OutlineFigurePoint() = default; + ~ON_OutlineFigurePoint() = default; + ON_OutlineFigurePoint(const ON_OutlineFigurePoint&) = default; + ON_OutlineFigurePoint& operator= (const ON_OutlineFigurePoint&) = default; + +public: + enum class Type : ON__UINT8 + { + Unset = 0, + + ////////////////////////////////////////////////////////////////// + // + // Beginning of a figure + // + // The open/closed state is unknown. + BeginFigureUnknown = 1, + + // Marks the beginning of an open figure. (single stroke font, ...) + BeginFigureOpen = 2, + + // Marks the beginning of a closed figure. + BeginFigureClosed = 3, + + + ////////////////////////////////////////////////////////////////// + // + // Interior of a figure + // + + // interior line segment point + LineTo = 6, + + // interior quadratic bezier (degree=2, order=3) control point. + QuadraticBezierPoint = 7, + + // interior cubic bezier (degree=3, order=4) control point. + CubicBezierPoint = 8, + + ////////////////////////////////////////////////////////////////// + // + // End of a figure + // + + // End of an open figure (single stroke font, ...) + EndFigureOpen = 11, + + // End of a closed figure. + EndFigureClosed = 12, + + + ////////////////////////////////////////////////////////////////// + // + + // Error of some sort. + Error = 15 + }; + + enum class Proximity : ON__UINT8 + { + Unset = 0, + + // The point is the beginning or end of a line or bezier segment in the figure + OnFigure = 1, + + // The point is a bezier control point that may be off the figure + OffFigure = 2, + + Error = 15 + }; + + /* + Returns: + true if point_type is one of the following: + ON_OutlineFigurePoint::Type::BeginFigureUnknown + ON_OutlineFigurePoint::Type::BeginFigureFilled + ON_OutlineFigurePoint::Type::BeginFigureHollow + ON_OutlineFigurePoint::Type::BeginFigureOpen + */ + static bool IsBeginFigurePointType( + ON_OutlineFigurePoint::Type point_type + ); + + /* + Returns: + true if point_type is one of the following: + ON_OutlineFigurePoint::Type::MoveTo + ON_OutlineFigurePoint::Type::LineTo + ON_OutlineFigurePoint::Type::QuadraticBezierPoint + ON_OutlineFigurePoint::Type::CubicBezierPoint + */ + static bool IsInteriorFigurePointType( + ON_OutlineFigurePoint::Type point_type + ); + + /* + Returns: + true if point_type is one of the following: + ON_OutlineFigurePoint::Type::LineToCloseContour + ON_OutlineFigurePoint::Type::EndFigureUnknown + ON_OutlineFigurePoint::Type::EndFigureClosed + ON_OutlineFigurePoint::Type::EndFigureOpen + */ + static bool IsEndFigurePointType( + ON_OutlineFigurePoint::Type point_type + ); + + static ON_OutlineFigurePoint::Type ContourPointTypeFromUnsigned(unsigned contour_point_type_as_unsigned); + + static const ON_OutlineFigurePoint Unset; + static const ON_OutlineFigurePoint Error; + + + /* + Returns: + true if point_type is one of the following: + ON_OutlineFigurePoint::Type::BeginFigureUnknown + ON_OutlineFigurePoint::Type::BeginFigureFilled + ON_OutlineFigurePoint::Type::BeginFigureHollow + ON_OutlineFigurePoint::Type::BeginFigureOpen + */ + bool IsBeginFigurePoint() const; + + /* + Returns: + true if point_type is one of the following: + ON_OutlineFigurePoint::Type::MoveTo + ON_OutlineFigurePoint::Type::LineTo + ON_OutlineFigurePoint::Type::QuadraticBezierPoint + ON_OutlineFigurePoint::Type::CubicBezierPoint + */ + bool IsInteriorFigurePoint() const; + + /* + Returns: + true if point_type is one of the following: + ON_OutlineFigurePoint::Type::LineToCloseContour + ON_OutlineFigurePoint::Type::EndFigureUnknown + ON_OutlineFigurePoint::Type::EndFigureClosed + ON_OutlineFigurePoint::Type::EndFigureOpen + */ + bool IsEndFigurePoint() const; + + + ON_OutlineFigurePoint::Type PointType() const; + + ON_OutlineFigurePoint::Proximity PointProximity() const; + + /* + Returns: + True if the point is on at the start or end of a line or bezier segment. + False otherwise (the point is in iterior control point in bezier segment or unset). + */ + bool IsOnFigure() const; + + /* + Returns: + True if the point is in iterior control point in bezier segment. + False otherwise (the point is on at the start or end of a line or bezier segment or unset). + */ + bool IsOffFigure() const; + + ON__UINT16 FigureIndex() const; + + const ON_2fPoint Point() const; + const ON_2dPoint Point2d() const; + + /* + Returns: + Point rounded to nearest integer coordinates. + */ + const ON_2iPoint Point2i() const; + + /* + Returns: + Point rounded up (ceil) to integer coordinates. + */ + const ON_2iPoint Point2iCeil() const; + + /* + Returns: + Point rounded down (floor) to integer coordinates. + */ + const ON_2iPoint Point2iFloor() const; + +public: + ON_OutlineFigurePoint::Type m_point_type = ON_OutlineFigurePoint::Type::Unset; + + ON_OutlineFigurePoint::Proximity m_point_proximity = ON_OutlineFigurePoint::Proximity::Unset; + + // 0 = unset. The first figure in an outline has m_figure_index = 1. + ON__UINT16 m_figure_index = 0; + + // point location + ON_2fPoint m_point = ON_2fPoint::NanPoint; +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +#endif + +class ON_CLASS ON_OutlineFigure +{ +public: + ON_OutlineFigure() = default; + ~ON_OutlineFigure() = default; + ON_OutlineFigure(const ON_OutlineFigure&) = default; + ON_OutlineFigure& operator=(const ON_OutlineFigure&) = default; + +public: + static const ON_OutlineFigure Unset; + +public: + + enum class Orientation : ON__UINT8 + { + Unset = 0, + + CounterClockwise = 1, + + Clockwise = 2, + + NotOriented = 3, + + // An error occured in orientation calculations + Error = 15 + }; + + static const wchar_t* OrientationToWideString( + ON_OutlineFigure::Orientation orientation + ); + + /// + /// ON_OutlineFigure::Type identifies the structure of the figure. + /// + enum class Type : ON__UINT8 + { + /// + /// This value should be used for parameters where the type is has not + /// been explicity to determined. + /// + Unset = 0, + + /// + /// Unknown indicates an attempt was made to determine the type, + /// that attempt failed, and further attempts will just waste time. + /// It is best to pass Unset when calling functions and you have + /// not calculated the type. + /// + Unknown = 1, + + /// + /// Single stroke figures can be open or closed and are not designed to be filled. + /// Single stroke fonts like RhSS and MecSoft have these types of figures. + /// + SingleStroke = 2, + + /// + /// Double stroke figures are closed and contain no area. + /// They consist of a single stroke path follow by the reverse of the single stroke path. + /// The CamBam Stick fonts have these types of figures. A double stroke figure can + /// be converted to a single stroke figure by removing the reversed overlapping portion. + /// + DoubleStroke = 3, + + /// + /// The outline figures are perimeters around non-empty areas that are typically + /// filled or hollow depending on their orientation. + /// The majority of TrueType, OpenType, and PostScript fonts have these types of figures. + /// + Perimeter = 4, + + /// + /// The outline figure is not a perimeter around a non-empty area. + /// + NotPerimeter = 5, + + /// + /// Used in a context where there are multiple figures with different types. + /// + Mixed = 7, + }; + + /* + Returns: + If the figure type is known for certain, that type is returned. + Otherwise ON_OutlineFigure::Type::Unknown is returned. + */ + static ON_OutlineFigure::Type FigureTypeFromFontName( + const wchar_t* font_name + ); + + /* + Description: + Opennurbs searches the description saved in field 10 of the name table + for the strings "Engraving - single stroke" / "Engraving - double stroke" / "Engraving" + to identify fonts that are desgned for engraving (and which tend to render poorly when + used to dispaly text devices like screens, monitors, and printers). + The SLF (single line fonts) are examples of fonts that have Engraving in field 10. + Parameters: + field_10_description - [in] + Field 10 string from the font name table. + Returns: + If the description contains "single stroke", returns ON_OutlineFigure::Type::SingleStroke. + If the description contains "double stroke", returns ON_OutlineFigure::Type::DoubleStroke. + Otherwise returns ON_OutlineFigure::Type::Unset; + */ + static ON_OutlineFigure::Type FigureTypeFromField10Description( + const ON_wString field_10_description + ); + + + /* + Returns: + Figure orientation. + */ + ON_OutlineFigure::Orientation FigureOrientation() const; + + /* + Returns: + Figure type. + */ + ON_OutlineFigure::Type FigureType() const; + + /* + Returns: + Signed area estimate. For simple closed curves, a positive area indicates a counter-clockwise orientation. + */ + double AreaEstimate() const; + + + /* + Returns: + Bounding box area >= 0 + */ + double BoxArea() const; + + /* + Description: + Determines if this ON_OutlineFigure is inside of outer_figure. + Parameters: + outer_figure - [in] + When bPerformExtraChecking is false, outer_figure->FigureOrientation() should + be set to what you plan on using when rendering the glyph. + The orientation of outer_figur can be either clockwise or counterclockwise + and, in the context of the entire glyph, outer_figure can be an inner or outer boundary. + For example, the registered trademark glpyh (UNICODE U+00AE) is an example where + four nested figures with alternating orientations are common. + bPerformExtraChecking - [in] + In general, when sorting glyph outlines as they come froma font file, set + outer_figure->FigureOrientation() to what will be used to render the glyph + and pass false for bPerformExtraChecking. + Details: In the case when bounding boxes and estimated areas and spot checks of winding numbers + all indicate that this is inside of other_f, an additional time consuming intersection + check is performed when this->FigureOrientation() == other_f->FigureOrientation(). + When this->FigureOrientation() and other_f->FigureOrientation() are opposited, + the additional intersection check is skipped unless bPerformExtraChecking is true. + Returns: + True if it is very likely that this is not empty and is inside of other_f. + False otherwise + Remarks: + */ + bool IsInsideOf( + const ON_OutlineFigure* outer_figure, + bool bPerformExtraChecking + ) const; + + /* + Description: + Get up to four distinct points on the figure. + These are useful for winding number tests when sorting figures. + Parameters: + p - [out] + the returned points will be on the figure (not bezier interior control points). + Returns: + Number of points. + */ + unsigned GetUpToFourPointsOnFigure( + ON_2fPoint p[4] + ) const; + + ON__UINT32 UnitsPerEM() const; + + ON__UINT16 FigureIndex() const; + + unsigned int GetFigureCurves( + double scale, + bool b3d, + ON_SimpleArray< ON_Curve* >& figure_curves + ) const; + + unsigned int GetFigureCurves( + double scale, + bool b3d, + ON_SimpleArray< ON_NurbsCurve* >& figure_curves + ) const; + + bool IsValidFigure( + bool bLogErrors + ) const; + + const ON_BoundingBox BoundingBox() const; + + bool ReverseFigure(); + + bool NegateY(); + + /* + Description: + Get a polyline approximation of the figure. + + Parameters: + tolerance - [in] + If tolerance > 0, that value is used. + Otherwise UnitsPerEM() / 256.0 is used, which gives course but + recognizable decent results for glyph outlines. + + PointCallbackFunc - [in] + called once for each point in the polyline + context - [in] + third parameter to PointCallbackFunc() + Returns: + Number of points passed to PointCallbackFunc() + */ + unsigned int GetPolyline( + double tolerance, + void(*PointCallbackFunc)(float x, float y, void*), + void* context + ) const; + + double DefaultPolylineTolerance() const; + + static double DefaultPolylineTolerance( + double units_per_em + ); + + int WindingNumber( + ON_2fPoint winding_point + ) const; + + /* + Description: + Get a polyline approximation of the figure. + Parameters: + tolerance - [in] + If tolerance > 0, that value is used. + Otherwise UnitsPerEM() / 256.0 is used, which gives course but + recognizable decent results for glyph outlines. + points - [out] + polyline points are appended to this array. + Returns: + Number of points appended to oiunts[] + */ + unsigned int GetPolyline( + double tolerance, + ON_SimpleArray& points + ) const; + + /* + Description: + Get a polyline approximation of the figure. + Parameters: + tolerance - [in] + If tolerance > 0, that value is used. + Otherwise UnitsPerEM() / 256.0 is used, which gives course but + recognizable decent results for glyph outlines. + points - [out] + polyline points are appended to this array. + Returns: + Number of points appended to oiunts[] + */ + unsigned int GetPolyline( + double tolerance, + ON_SimpleArray& points + ) const; + + /* + Description: + Get a polyline approximation of the figure. + Parameters: + tolerance - [in] + If tolerance > 0, that value is used. + Otherwise UnitsPerEM() / 256.0 is used, which gives course but + recognizable decent results for glyph outlines. + points - [out] + polyline points are appended to this array. + Returns: + Number of points appended to oiunts[] + */ + unsigned int GetPolyline( + double tolerance, + ON_SimpleArray& points + ) const; + + /* + Description: + Get a polyline approximation of the figure. + Parameters: + tolerance - [in] + If tolerance > 0, that value is used. + Otherwise UnitsPerEM() / 256.0 is used, which gives course but + recognizable decent results for glyph outlines. + points - [out] + polyline points are appended to this array. + Returns: + Number of points appended to oiunts[] + */ + unsigned int GetPolyline( + double tolerance, + ON_SimpleArray& points + ) const; + +private: + friend class ON_Outline; + +private: + ON__UINT32 m_units_per_em = 0; + +private: + mutable ON_OutlineFigure::Orientation m_orientation = ON_OutlineFigure::Orientation::Unset; + mutable ON_OutlineFigure::Type m_figure_type = ON_OutlineFigure::Type::Unset; + +private: + mutable ON__UINT8 m_bbox_status = 0; // 0 = unset, 1 = set, 7 = error + mutable ON__UINT8 m_area_status = 0; // 0 = unset, 1 = set, 7 = error + + +public: + ON__UINT16 m_figure_index = 0; + +private: + mutable ON_2fPoint m_bbox_min = ON_2fPoint::NanPoint; + mutable ON_2fPoint m_bbox_max = ON_2fPoint::NanPoint; + + double m_short_tolerance = 0.0; + mutable double m_area_estimate = ON_DBL_QNAN; + +public: + ON_SimpleArray m_points; + +private: + ON__UINT32 Internal_FigureEndDex( bool bLogErrors ) const; + + bool Internal_HasValidEnds( bool bLogErrors ) const; + ON__UINT32 Internal_EstimateFigureSegmentCount() const; + + static bool Internal_NegateY(ON_2fPoint&); + + + unsigned int Internal_SegmentDegree( + ON__UINT32 segment_start_dex + ) const; + + /* + Parameters: + figure_end_dex - [in] + index of the last point in the figure. + b3dCurve - [in] + If true the result is 3d, otherwise it is 2d. + curve - [in] + If not nullptr, result is stored here + Returns: + nurbs curve + */ + class ON_NurbsCurve* Internal_GetFigureCurve( + ON__UINT32 figure_end_dex, + ON__UINT32 segment_start_dex, + ON__UINT32* segment_end_dex, + bool b3d, + class ON_NurbsCurve* destination_curve + ) const; +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; +#endif + +class ON_CLASS ON_Outline +{ +public: + ON_Outline() = default; + ~ON_Outline() = default; + ON_Outline(const ON_Outline&) = default; + ON_Outline& operator=(const ON_Outline&) = default; + +public: + static const ON_Outline Unset; + + /* + Default value for outer orientation when it is not explicitly specified. + */ + static const ON_OutlineFigure::Orientation DefaultOuterOrientation; + + + + ON__UINT32 UnitsPerEM() const; + + void SetUnitsPerEM( + ON__UINT32 units_per_em + ); + + /* + Returns: + Number of figures in the outline. + */ + unsigned int FigureCount() const; + + /* + Parameters: + i - [in] + 0 <= i < count + */ + const ON_OutlineFigure& Figure( + int i + ) const; + + const ON_ClassArray< ON_OutlineFigure >& Figures() const; + + /* + Returns: + Number of points in all figures in the outline. + */ + unsigned int OutlinePointCount() const; + + /* + Parameters: + bLogErrors - [in] + + Returns: + True if the outline and all figures are valid. + */ + bool IsValidOutline( + bool bLogErrors + ) const; + + /* + Description: + The outline consists of one or more figures. + There can be zero or more closed outer figures + (single stroke fonts have zero, Arial I has one, Arial i has two). + There can be zero or more inner figures + (Arial I has zero, O has one, 8 has two). + Parameters: + scale - [in] + If scale > 0.0, then all curves are scaled this factor with (0,0) + as the fixed point. Otherwise all curves are returned in font design units. + ON_Font::ScaleFromTextHeight() is a good tool to get this value. + b3d - [in] + If true, then 3d curves in the world xy plane are returned. + Otherwise 2d curves are returned. + figure_curves - [in] + Results are appended to this array. + Returns: + Number of figures appended to outline_curves[] + */ + unsigned int GetOutlineCurves( + double scale, + bool b3d, + ON_ClassArray< ON_SimpleArray< ON_Curve* > >& outline_curves + ) const; + + + /* + Returns: + The bounding box of the outline curves. + + Remarks: + The glyph metrics bounding box of the metrics can be different from the + figure outline bounding box. + For example, the glyph metrics box for 1 (numeral one) often contains space beyond the + glyph outline because 1 visually occupies the same space as a 2. The choice is up to the + font designer and takes into account the desired font asthetics of columns of numbers. + */ + const ON_BoundingBox OutlineBoundingBox() const; + + /* + Returns: + Glyph metrics. + Remarks: + The glyph metrics bounding box of the metrics can be different from the + figure outline bounding box. + For example, the glyph metrics box for 1 (numeral one) often contains space beyond the + glyph outline because 1 visually occupies the same space as a 2. The choice is up to the + font designer and takes into account the desired font asthetics of columns of numbers. + */ + const ON_TextBox GlyphMetrics() const; + + /* + Description: + The signed area estimate calculated as the sum of each figure's area estimate. + */ + double AreaEstimate() const; + + /* + Description: + Reverse every figure. + */ + void Reverse(); + + /* + Description: + Sort figures so that each outer loop is followed by it's inner loops. + */ + void SortFigures( + ON_OutlineFigure::Orientation outer_loop_orientation + ); + + /* + Returns: + ON_OutlineFigure::Orientation::Unset + Figures are not sorted. + ON_OutlineFigure::Orientation::CounterClockwise + Figures are sorted and outer figures are CCW. + ON_OutlineFigure::Orientation::Clockwise + Figures are sorted and outer figures are CW. + ON_OutlineFigure::Orientation::Error + Figure sorting failed. + */ + ON_OutlineFigure::Orientation SortedFigureOuterOrientation() const; + + /* + Returns: + ON_OutlineFigure::Orientation::Unset + Figures are not sorted. + ON_OutlineFigure::Orientation::CounterClockwise + Figures are sorted and inner figures are CCW. + ON_OutlineFigure::Orientation::Clockwise + Figures are sorted and inner figures are CW. + ON_OutlineFigure::Orientation::Error + Figure sorting failed. + */ + ON_OutlineFigure::Orientation SortedFigureInnerOrientation() const; + + /* + Returns: + Type of figures in the outline. + */ + ON_OutlineFigure::Type FigureType() const; + +public: + ON__UINT16 AppendFigure( + const ON_SimpleArray& points + ); + + ON__UINT16 AppendFigure( + size_t point_count, + const ON_OutlineFigurePoint* points + ); + + void SetGlyphMetrics( + ON_TextBox glyph_metrics + ); + +private: + friend class ON_OutlineAccumulator; + ON__UINT32 m_units_per_em = 0; + ON_OutlineFigure::Type m_figure_type = ON_OutlineFigure::Type::Unset; + mutable ON__UINT8 m_bbox_status = 0; // 0 = unset, 1 = set, 7 = error + + // Unset = unsorted + // CounterClockwise: outer figures are CCW + // Clockwise: outer fitures are CW + // Error: error occured during sorting + mutable ON_OutlineFigure::Orientation m_sorted_figure_outer_orientation = ON_OutlineFigure::Orientation::Unset; + + ON__UINT8 m_reserved1 = 0; + + double m_short_tolerance = 0.0; + + mutable ON_BoundingBox m_bbox = ON_BoundingBox::NanBoundingBox; + ON_TextBox m_glyph_metrics = ON_TextBox::Unset; + + // unsets the bounding box, m_bSingleStroke settings, ... + void Internal_ClearCachedValues() const; + + ON__UINT16 Internal_AppendFigure( + size_t point_count, + const ON_OutlineFigurePoint* points, + double short_tolerance, + bool bSkipPointFigures + ); + + ON_ClassArray< ON_OutlineFigure > m_figures; +}; + +class ON_CLASS ON_OutlineAccumulator +{ +public: + ON_OutlineAccumulator() = default; + ~ON_OutlineAccumulator() = default; + +private: + ON_OutlineAccumulator(const ON_OutlineAccumulator&) = delete; + ON_OutlineAccumulator& operator=(const ON_OutlineAccumulator&) = delete; + +public: + + /* + Parameters: + font_units_per_em - [in] + This is the height and width of the square font design grid. + In TrueType fonts, font_units_per_em is often a power of two and generally 1024 or 2048. + In OpenType fonts, font_units_per_em is often 1000. + In PostScript fonts, font_units_per_em is often 1000. + figure_type - [in] + True if the glyphs are single stroke and open glyphs should not + be closed. + coordinate_type - [in] + ON_OutlineAccumulator::Coordinate::Integer + The points passed to the figure drawing methods will be ON_2iPoint values. + The resulting outline will contain ON_2iPoint values. + ON_OutlineAccumulator::Coordinate::Float + The points passed to the figure drawing methods will be ON_2fPoint values. + The resulting outline will contain ON_2fPoint values. + ON_OutlineAccumulator::Coordinate::Float + The points passed to the figure drawing methods will be ON_2fPoint values + that should be rounded to the nearest integer. The resulting outline + will contain ON_2iPoint values. + bAccumulatePoints - [in] + True if the points should be accumulated in the m_outline_points[] + array. + False if the points are not accumulated. + In all cases, the outline bounding box is calculated. + Remarks: + Typically both the width and the height of the 'M' glyph + in the font are less than font_units_per_em. + */ + bool BeginGlyphOutline( + ON__UINT32 font_units_per_em, + ON_OutlineFigure::Type figure_type, + ON_Outline* destination_outline + ); + + void Clear(); + + ON_Outline* HarvestOutline(); + + /* + Returns: + EndOutline(false,ON_Outline::DefaultOuterOrientation); + */ + bool EndOutline(); + + /* + Parameters: + bNegatePointY - [in] + If true, the y coordinate of the accumulated points is negated. + This is done before any orientation adjustments are performed. + outer_orientation - [in] + If outer_orientation is ON_OutlineFigure::Orientation::Clockwise, + or ON_OutlineFigure::Orientation::CounterClockwise, then + the figures are oriented so that outer boundaries have + the specified orientation. + Otherwise this parameter is ignored. + */ + bool EndOutline( + bool bNegatePointY, + ON_OutlineFigure::Orientation outer_orientation + ); + + /////////////////////////////////////////////////////////// + // + // Tools for adding figures to the outline + // + + /* + Description: + Begins a figure. A glyph outline has zero or more figures. + Parameters: + point_type - [in] + One of + ON_OutlineFigurePoint::Type::BeginFigureUnknown + ON_OutlineFigurePoint::Type::BeginFigureFilled + ON_OutlineFigurePoint::Type::BeginFigureHollow + ON_OutlineFigurePoint::Type::BeginFigureOpen + ON_OutlineFigurePoint::Type::BeginFigureClosed + figure_starting_point - [in] + First point in the figure. + */ + bool BeginFigure( + ON_OutlineFigurePoint::Type point_type, + ON_2fPoint figure_starting_point + ); + + /* + Description: + Appends a line segment to the current figure. + The line segment begins at the current_point and ends at line_end_point. + Parameters: + line_end_point - [in] + */ + bool AppendLine( + ON_2fPoint line_end_point + ); + + /* + Description: + Appends a quadratic (degree = 2, order = 3) bezier to the current figure. + The quadratic bezier begins at the current_point and ends at cv2. + The quadratic bezier has three control points + (current point, cv1, cv2, cv3). + Parameters: + cv1 - [in] + cv2 - [in] + end of the quadratic bezier. + */ + bool AppendQuadraticBezier( + ON_2fPoint cv1, + ON_2fPoint cv2 + ); + + /* + Description: + Appends a cubic (degree = 3, order = 4) bezier to the current figure. + The cubic bezier begins at the current_point and ends at cv3. + The cubic bezier has four control points + (current point, cv1, cv2, cv3). + Parameters: + cv1 - [in] + cv2 - [in] + cv3 - [in] + end of the cubic bezier. + */ + bool AppendCubicBezier( + ON_2fPoint cv1, + ON_2fPoint cv2, + ON_2fPoint cv3 + ); + + /* + Description: + Terminates a figure that was started with the previous call to + BeginFigure2i() or BeginFigure2f(). + The locations of the figure's starting and final points are always identical. + The point_type parameter is used to indicate if a line segment from the + starting point to the final point is included in the figure. + Parameters: + point_type - [in] + One of + ON_OutlineFigurePoint::Type::EndFigureUnknown + If FigureType() is SingleStroke, this value is treated as + if it were ON_OutlineFigurePoint::Type::EndFigureOpen. + Otherwise, the final point in the figure will have this type. + ON_OutlineFigurePoint::Type::EndFigureClosed + If FigureType() is SingleStroke is true, this value is treated as + if it were ON_OutlineFigurePoint::Type::EndFigureOpen. + Otherwise, the final point in the figure will have this type. + ON_OutlineFigurePoint::Type::EndFigureOpen + The final point in the figure will have this type. + */ + bool EndFigure( + ON_OutlineFigurePoint::Type point_type + ); + + void AbandonCurrentFigure(); + + /* + Returns: + Number of points in the current figure. + */ + unsigned int CurrentFigurePointCount() const; + + /* + Returns: + Number of input errors that have occured. + Remarks: + When an error occurs, the current figure is terminated. + */ + unsigned int ErrorCount() const; + + const ON_OutlineFigurePoint CurrentFigureStartPoint() const; + + const ON_OutlineFigurePoint CurrentFigurePreviousPoint() const; + + const ON_OutlineFigurePoint CurrentFigurePoint() const; + + const bool CurrentFigureAccumulating() const; + + /* + Returns: + Outline design units per em. + */ + ON__UINT32 UnitsPerEM() const; + + ON_OutlineFigure::Type FigureType() const; + + bool IsInitialized() const; + bool IsFinalized() const; + bool IsInitializedOrFinalized() const; + +private: + // Units per EM > 0 + // This is the height and width of the square grid font design grid. + // The width of the 'M' glyph in a font can be different from UPM. + // The height of the 'M' glyph in a font is typically less than UPM. + // In TrueType fonts, UPM is often a power of two and generally 1024 or 2048. + // In OpenType fonts, UPM is often 1000. + // In PostScript fonts, UPM is often 1000. + ON__UINT32 m_units_per_em = 0; + + ON__UINT8 m_status = 0; // 0 = none, 1 initialized, 2 finalized. + ON_OutlineFigure::Type m_figure_type = ON_OutlineFigure::Type::Unset; + + // 0 = not accumulating points in a figure. + // 1 = accumulating points in a figure. + int m_figure_depth = 0; + + // Total number of errors + ON__UINT32 m_error_count = 0; + + // current figure accumulator + ON_OutlineFigurePoint m_figure_start = ON_OutlineFigurePoint::Unset; + ON_OutlineFigurePoint m_figure_prev = ON_OutlineFigurePoint::Unset; + ON_OutlineFigurePoint m_figure_current = ON_OutlineFigurePoint::Unset; + ON_SimpleArray< ON_OutlineFigurePoint > m_point_accumulator; + ON_Outline* m_outline = nullptr; + ON_Outline* m_managed_outline = nullptr; + +public: + /* + Expert user tool for getting the start point of + the figure currently being accumulated. + */ + const ON_OutlineFigurePoint ActiveFigureStartPoint() const; + + /* + Expert user tool for getting the curent point of + the figure being accumulated. + */ + const ON_OutlineFigurePoint ActiveFigureCurrentPoint() const; + + const ON_Outline& Outline() const; + +private: + bool Internal_InFigure() const; + + void Internal_AccumulateError( + bool bCancelCurrentFigure + ); + + bool Internal_AccumulatePoint( + ON_OutlineFigurePoint::Type point_type, + ON_2fPoint point_location, + bool bPointInBoundingBox + ); + + ON_Outline& Internal_Outline(); +}; + + +/* + The best way to get a useful ON_FontGlyph is to call + ON_Font.CodePointGlyph(unicode_code_point) +*/ +class ON_CLASS ON_FontGlyph +{ +public: + /* + The best way to get a useful ON_FontGlyph is to call + ON_Font.CodePointGlyph(unicode_code_point) + */ + ON_FontGlyph() = default; + ~ON_FontGlyph() = default; + ON_FontGlyph(const ON_FontGlyph& src); + ON_FontGlyph& operator=(const ON_FontGlyph& src); + + + /* + If the font and code point are valid, constructs an unmanaged + glyph with the specified font and code point. + The glyph box is not set. + */ + ON_FontGlyph( + const class ON_Font* font, + ON__UINT32 code_point + ); + +public: + static const ON_FontGlyph Unset; + + const class ON_Font* Font() const; + + const ON__UINT32 CodePoint() const; + + bool IsEndOfLineCodePoint() const; + + static bool IsEndOfLineCodePoint( + ON__UINT32 unicode_code_point + ); + + static bool IsCarriageReturnAndLineFeed( + ON__UINT32 unicode_code_point, + ON__UINT32 next_unicode_code_point + ); + + /* + Returns: + Glyph box in opennurbs normalized font coordinates. + */ + const ON_TextBox& GlyphBox() const; + + /* + Returns: + Font unit glyph box. + Remarks: + Must be used with ON_Font::FontUnitFontMetrics() and a single font to obtain useful results. + You are probably better of using normalized font coordinates in a ON_FontGlyph.GlyphBox(). + */ + const ON_TextBox& FontUnitGlyphBox() const; + + static int CompareCodePointAndFont( + const ON_FontGlyph& lhs, + const ON_FontGlyph& rhs + ); + + /* + Parameters: + text - [in] + Null terminated wchar_t string. + font - [in] + The font used to render the glyphs. + unicode_CRLF_code_point - [in] + If unicode_CRLF_code_point is a valid unicode code point, + then consecutive carriage return line feed pairs are converted + to a single glyph with code point = unicode_CRLF_code_point. + + ON_UnicodeCodePoint::ON_LineSeparator is a good choice when you want to + condense carriage return line feed pairs to a single unambiguous code point. + + ON_UnicodeCodePoint::ON_InvalidCodePoint is a good choice when you want to + preserve carriage return line feed pairs as two separate glyphs. + + glyph_list - [out] + Note that glyph_list.Count() is often different than the + length of the text string or the number of unicode codepoints + in the decoded text. + Adjacent carriage return and line feed codepoints are + converted to single a hard end of line. + All trailing end of line code points are removed from text. + Invalid unicode encoding sequences are replaced with + ON_UnicodeCodePoint::ReplacementCharacter glyphs. + + text_box - [out] + tight bounding boxt of text extents. + text_box.m_advance.i = maximum of all line horizontal advance values.. + text_box.m_advance.j = vertical advance to baseline of last line + If if the font height + is ON_Font::Constants::AnnotationFontCellHeight. If you will render the font + at a different height from ON_Font::Constants::AnnotationFontCellHeight, then + use ON_TextBox::Scale as follows: + ON_TextBox scaled_box + = ON_TextBox::Scale( + text_box, + (font render height)/((double)ON_Font::Constants::AnnotationFontCellHeight) + ); + Return: + number of lines of text or 0 if input is not valid or text is empty. + */ + static int GetGlyphList + ( + const wchar_t* text, + const class ON_Font* font, + ON__UINT32 unicode_CRLF_code_point, + ON_SimpleArray& glyph_list, + ON_TextBox& text_box + ); + + static int GetGlyphList + ( + size_t code_point_count, + ON__UINT32* code_points, + const class ON_Font* font, + ON__UINT32 unicode_CRLF_code_point, + ON_SimpleArray& glyph_list, + ON_TextBox& text_box + ); + + /* + Parameters: + font - [in] + The font used to render the glyphs. + text_box - [out] + tight bounding boxt of text extents. + text_box.m_advance.i = maximum of all line horizontal advance values.. + text_box.m_advance.j = vertical advance to baseline of last line + If if the font height + is ON_Font::Constants::AnnotationFontCellHeight. If you will render the font + at a different height from ON_Font::Constants::AnnotationFontCellHeight, then + use ON_TextBox::Scale as follows: + ON_TextBox scaled_box + = ON_TextBox::Scale( + text_box, + (font render height)/((double)ON_Font::Constants::AnnotationFontCellHeight) + ); + Return: + number of lines of text or 0 if input is not valid or text is empty. + */ + static int GetGlyphListBoundingBox + ( + const wchar_t* text, + const class ON_Font* font, + ON_TextBox& text_box + ); + + static int GetGlyphListBoundingBox + ( + size_t code_point_count, + ON__UINT32* code_points, + const class ON_Font* font, + ON_TextBox& text_box + ); + + /* + Description: + Sets the font and code point and unsets every other property including the + glyph box and substitute information. + Parameters: + font - [in] + code_point - [in] + */ + bool SetCodePoint( + const class ON_Font* font, + ON__UINT32 code_point + ); + + /* + Returns: + True if the unicode code point and font are set + */ + bool CodePointIsSet() const; + + /* + Returns: + true if this is a managed instance. + Managed instances persist for the lifetime of the application + and the pointer can be safely saved and referenced at any time. + */ + bool IsManaged() const; + + /* + Returns: + If this->CodePointIsSet() is true, then a persistent pointer + to a managed glyph with the same code point and font is returned. + Otherwise nullptr is returned. + */ + const ON_FontGlyph* ManagedGlyph() const; + + /* + Parameters: + bUseReplacementCharacter - [in] + When this->CodePointIsSet() is true, + and bUseReplacementCharacter is true, + and no reasonable glyph definition exists, + and no substitued is available, + then the replacement character glyph for UNICODE code point + ON_UnicodeCodePoint::ON_ReplacementCharacter (U+FFFD) will be returned. + + Returns: + A managed glyph that can be used to render "this". + If this->CodePointIsSet() is false, nullptr is returned. + If this->CodePointIsSet() is true, the returned glyph may + have a different font and code point when the current + computer requires font or glyph substitution to draw + the glyph. When the current platform cannot render this, + nullptr or the replacement glyph is returned depending on + the value of bUseReplacementCharacter. + + See Also: + ON_FontGlyph.SubstituteGlyph(). + */ + const ON_FontGlyph* RenderGlyph( + bool bUseReplacementCharacter + ) const; + + /* + Returns: + If this is a managed glyph or a copy of a managed glyph, + and a substitute font or code point is used to render the glyph, + then the substitue is returned. + In all other cases, nullptr is returned. + See Also: + ON_FontGlyph.RenderGlyph(). + */ + const ON_FontGlyph* SubstituteGlyph() const; + + /* + Parameters: + bIncludeCharMaps - [in] + If true, then char information is printed. + */ + void Dump( + bool bIncludeCharMaps, + ON_TextLog& text_log + ) const; + + void Dump( + bool bIncludeFont, + bool bIncludeCharMaps, + bool bIncludeSubstitute, + bool bIncludeFontUnitTextBox, + ON_TextLog& text_log + ) const; + +#if defined(OPENNURBS_FREETYPE_SUPPORT) +// Look in opennurbs_system_rumtime.h for the correct place to define OPENNURBS_FREETYPE_SUPPORT. +// Do NOT define OPENNURBS_FREETYPE_SUPPORT here or in your project setting ("makefile"). + + +public: + /* + Description: + This is a debugging tool to test the code that starts with a font and + Unicode code point and and finds a glyph in the font definition for + that code point. + Parameters: + text_log - [in] + If text_log is not nullptr, then diagnostic messages are sent to this log. + Returns: + True: + No errors were found. Every available charmap either returned the same glyph id + that FontGlyphId() function returns or had no glyph id for this code point. + False: + Inconsistent results were returned from different charmaps. + Remarks: + If a font or charmap is known to contain a bug and that bug is + handled by opennurbs, then true is returned and a message is printed + to the log. + */ + bool TestFreeTypeFaceCharMaps( + ON_TextLog* text_log + ) const; + +public: + /* + Description: + If opennurbs is built with FreeType support then + FT_Face freetype_face = (FT_Face)glyph->FreeTypeFace() + will return a FreeType face that can be used to render the glyph. + Parameters: + font - [in] + Returns: + A value that can be cast as a FreeType FT_Face. + Example + const ON_Font* font = ...; + FT_Face freetype_face = (FT_Face)glyph->FreeTypeFace(font); + Remarks: + Many fonts do not have a glyph for a every UNICODE codepoint and font + substitution is required. If you want to get the freetype face + used for a specfic UNICODE codepoint, call ON_Font::CodepointFreeTypeFace(). + */ + const ON__UINT_PTR FreeTypeFace() const; +#endif + +public: + /* + Returns: + Font glyph id. + Remarks: + The glyph id depends on the font and is assigned by the font designer. + In particular the font glyph id for the same Unicode code point + often varies from font to font. In a font, it is often the case that + multiple Unicode code points map to the same glyph. For example, + space an non-breaking space typically map to the same font glyph id. + */ + unsigned int FontGlyphIndex() const; + + bool FontGlyphIndexIsSet() const; + + + ON_DEPRECATED_MSG("Use FontGlyphIndex()") + const ON__UINT_PTR FontGlyphId() const; + + ON_DEPRECATED_MSG("Use FontGlyphIndexIsSet()") + bool FontGlyphIdIsSet() const; + + /* + Description: + Get glyph contours as NURBS curves. + Parameters: + bSingleStrokeFont - [in] + If true, open contours will not be closed by adding a line segment. + height_of_capital - [in] + If > 0, ouptut curves, bounding box, and advance vector are scaled + by height_of_capital/(font design capital height). For fonts like + Arial, Helvetica, Times Roman, and Courier this means the height + of H and I will be height_of_capital. + Otherwise, no scaling is applied to the output curves, bounding box, + and advance vector. + Pass 0.0 or in this->Font()->HeightOfI() to get the contours to be in opennurbs + normalized font coordinates. + All other values < 0 are treated as 0.0. + glyph_contours - [out] + glyph_bbox - [out] + glyph bounding box. + glyph_advance - [out] + glyph_advance->x = horizontal advance to apply when rendering glyphs horizontally. + A positive horizontal advance indicates advance to the right. + glyph_advance->y = vertical advance to apply when rendering glyphs vertically. + A positive vertical advance indicates advance downwards. + */ + bool GetGlyphContours( + bool bSingleStrokeFont, + double height_of_capital, + ON_ClassArray< ON_SimpleArray< ON_Curve* > >& glyph_contours, + ON_BoundingBox* glyph_bbox, + ON_3dVector* glyph_advance + ) const; + + bool GetOutline( + bool bSingleStrokeFont, + class ON_Outline& outline + ) const; + + + static bool GetStringContours( + const wchar_t* text_string, + const class ON_Font* font, + bool bSingleStrokeFont, + double height_of_capital, + double small_caps_scale, + ON_ClassArray< ON_ClassArray< ON_SimpleArray< ON_Curve* > > >& string_contours + ); + + +private: + friend class ON_GlyphMap; + friend class ON_Font; + + // NOTE WELL: + // The offset of m_codepoint in ON_FontGlyph must be >= 8 bytes. + // so the ON_FixeSizePool that manages memory for the glyph cache + // can efficiently iteratate all active managed glyphs. + // + ON_TextBox m_font_unit_glyph_bbox; // values in the native font definition units (freetype FT_LOAD_NO_SCALE units) + ON_TextBox m_normalized_glyph_bbox; // bounding box in opennurbs normalized font coordinates + + // This box is for the platform native glyph. It can be different than m_glyph_box. + // Example: + // Start with a Windows LOGFONT with face = Arial, height = ON_Font::Constants::AnnotationFontCellHeight (256) + // Native Windows height of Arial I = 165, height of LF = ... + // FreeType made from the same LOGFONT on the same has height of Arial I = 184, height of LF = ... + + // When font does not contain a glyph to render a specified unicode codepoint, + // then one or more glyphs from one or more subsitution fonts are used to + // render the codepoint. In this case, m_substitutes points to a linked + // list of substitute used to render the glyph. + // + ON__UINT32 m_code_point = ON_UnicodeCodePoint::ON_InvalidCodePoint; + + ON__UINT8 m_is_managed = 0; // 1 = managed glyph + ON__UINT8 m_reserved1 = 0; + ON__UINT16 m_reserved2 = 0; + ON__UINT32 m_reserved3 = 0; + ON__UINT32 m_font_glyph_index = 0; + const class ON_Font* m_managed_font = nullptr; + const class ON_FontGlyph* m_substitute = nullptr; + + +private: + void Internal_SetFontGlyphIndex(unsigned int font_glyph_index); + void Internal_CopyFrom(const ON_FontGlyph& src); + static ON_FontGlyph* Internal_AllocateManagedGlyph(const ON_FontGlyph& src); + bool Internal_GetPlatformSubstitute( + ON_FontGlyph& substitue + ) const; +}; + + +#if defined(ON_OS_WINDOWS_GDI) +class ON_CLASS ON_WindowsDWriteFontInformation +{ +public: + ON_WindowsDWriteFontInformation() = default; + ~ON_WindowsDWriteFontInformation() = default; + ON_WindowsDWriteFontInformation(const ON_WindowsDWriteFontInformation&) = default; + ON_WindowsDWriteFontInformation& operator=(const ON_WindowsDWriteFontInformation&) = default; + +public: + void Dump(ON_TextLog& text_log) const; + + static int CompareFamilyName(const ON_WindowsDWriteFontInformation* lhs, const ON_WindowsDWriteFontInformation* rhs); + static int CompareFamilyNameFaceNameWeightStretchStyle(const ON_WindowsDWriteFontInformation* lhs, const ON_WindowsDWriteFontInformation* rhs); + static int ComparePostScriptName(const ON_WindowsDWriteFontInformation* lhs, const ON_WindowsDWriteFontInformation* rhs); + +public: + // value passed to IDWriteFontCollection.GetFontFamily(m_family_index,...) + // IDWriteFactory.GetSystemFontCollection() is used to get the IDWriteFontCollection. + unsigned int m_family_index = 0; + + // value passed to IDWriteFontFamily.GetFont(m_family_font_index,...) + unsigned int m_family_font_index = 0; + + struct IDWriteFont* m_dwrite_font = nullptr; + + // prefered locale used to get the localized name values. + // If the a parrticular string was not available in the prefered locale, + // then other locales are used with "en-us" being the prefered alternate locale. + ON_wString m_prefered_locale; + + // from IDWriteFontFamily.GetFamilyNames() + const ON_wString FamilyName() const; + ON_wString m_loc_family_name; + ON_wString m_en_family_name; + + // from IDWriteFont.GetFaceNames() + const ON_wString FaceName() const; + ON_wString m_loc_face_name; + ON_wString m_en_face_name; + + // DWRITE_FONT_WEIGHT value from IDWriteFont.GetWeight() + unsigned int m_weight = 0; + + // DWRITE_FONT_STRETCH value from IDWriteFont.GetStretch() + unsigned int m_stretch = 0; + + // DWRITE_FONT_STYLE value from IDWriteFont.GetStyle() + unsigned int m_style = 0; + + + // from IDWriteFont.IsSymbolFont() + bool m_bIsSymbolFont = false; + + // deconstructed DWRITE_FONT_SIMULATIONS value from IDWriteFont.GetSimulations() + bool m_bSimulatedBold = false; // DWRITE_FONT_SIMULATIONS_BOLD + bool m_bSimulatedOblique = false; // DWRITE_FONT_SIMULATIONS_OBLIQUE + bool m_bSimulatedOther = false; // future DWRITE_FONT_SIMULATIONS_... + + // from IDWriteFont.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_FULL_NAME, ... ) + ON_wString m_loc_full_name; + ON_wString m_en_full_name; + + // from IDWriteFont.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME, ... ) + const ON_wString PostScriptName() const; + ON_wString m_loc_postscript_name; + ON_wString m_en_postscript_name; + + // from IDWriteFont.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, ... ) + // == LOGFONT lfFaceName + const ON_wString WindowsLogfontName() const; + ON_wString m_loc_gdi_family_name; + ON_wString m_en_gdi_family_name; + + // from IDWriteFont.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES, ... ) + ON_wString m_loc_gdi_subfamily_name; + ON_wString m_en_gdi_subfamily_name; + + // from IDWriteFont.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_WEIGHT_STRETCH_STYLE_FAMILY_NAME, ... ) + ON_wString m_loc_weight_stretch_style_model_name; + ON_wString m_en_weight_stretch_style_model_name; + + // from IDWriteFont.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_COPYRIGHT_NOTICE, ... ) + ON_wString m_loc_field_0_copyright; + ON_wString m_en_field_0_copyright; + + // from IDWriteFont.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_VERSION_STRINGS, ... ) + ON_wString m_loc_field_5_version; + ON_wString m_en_field_5_version; + + // from IDWriteFont.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_TRADEMARK, ... ) + ON_wString m_loc_field_7_trademark; + ON_wString m_en_field_7_trademark; + + // from IDWriteFont.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_MANUFACTURER, ... ) + ON_wString m_loc_field_8_manufacturer; + ON_wString m_en_field_8_manufacturer; + + // from IDWriteFont.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_DESIGNER, ... ) + ON_wString m_loc_field_9_designer; + ON_wString m_en_field_9_designer; + + // from IDWriteFont.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_DESCRIPTION, ... ) + // Opennurbs searches the description saved in field 10 of the name table + // for the strings "Engraving - single stroke" / "Engraving - double stroke" / "Engraving" + // to identify fonts that are desgned for engraving (and which tend to render poorly when + // used to dispaly text devices like screens, monitors, and printers). + // The SLF (single line fonts) are examples of fonts that have Engraving in field 10. + ON_wString m_loc_field_10_description; + ON_wString m_en_field_10_description; + + // from IDWriteFont.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_FONT_VENDOR_URL, ... ) + ON_wString m_loc_field_11_vendor_URL; + ON_wString m_en_field_11_vendor_URL; + + // from IDWriteFont.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_DESIGNER_URL, ... ) + ON_wString m_loc_field_12_designer_URL; + ON_wString m_en_field_12_designer_URL; + + // from IDWriteFont.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_LICENSE_DESCRIPTION, ... ) + ON_wString m_loc_field_13_license; + ON_wString m_en_field_13_license; + + // from IDWriteFont.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_LICENSE_INFO_URL, ... ) + ON_wString m_loc_field_14_license_URL; + ON_wString m_en_field_14_license_URL; + + // from IDWriteFont.GetInformationalStrings( DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME, ... ) + ON_wString m_loc_field_20_postscript_cid; // NOT the same as PostScriptName + ON_wString m_en_field_20_postscript_cid; + + // from IDWriteGdiInterop.ConvertFontToLOGFONT + LOGFONT m_gdi_interop_logfont; + + // from IDWriteGdiInterop.ConvertFontToLOGFONT + bool m_gdi_interop_logfont_bIsSystemFont = false; + + // from IDWriteFont.GetMetrics + ON_FontMetrics m_font_metrics; + + // Sample glyph metrics from IDWriteFontFace.GetDesignGlyphMetrics + + // "standard" metric glpyhs + ON_FontGlyph m_Spacebox; + ON_FontGlyph m_Hbox; + ON_FontGlyph m_Ibox; + ON_FontGlyph m_xbox; + + ON_PANOSE1 m_panose1; + + ON_OutlineFigure::Type m_outline_figure_type = ON_OutlineFigure::Type::Unset; +}; +#endif + +class ON_CLASS ON_FontFaceQuartet +{ +public: + + enum class Member : unsigned char + { + Unset = 0, + Regular = 1, + Bold = 2, + Italic = 3, + BoldItalic = 4 + }; + + static const ON_wString MemberToString( + ON_FontFaceQuartet::Member member + ); + + static ON_FontFaceQuartet::Member MemberFromUnsigned( + unsigned int member_as_unsigned + ); + + static ON_FontFaceQuartet::Member MemberFromBoldAndItalic( + bool bMemberIsBold, + bool bMemberIsItalic + ); + + /* + Description: + When an exact quartet face bold/italic match is not available, choosing + an available quartet face that minimizes ON_FontFaceQuartet::BoldItalicDeviation() + is one way to select which available quartet face to use. + Returns: + A distance between two quartet face members. + */ + static unsigned BoldItalicDeviation( + ON_FontFaceQuartet::Member desired_member, + ON_FontFaceQuartet::Member available_member + ); + + ON_FontFaceQuartet() = default; + ~ON_FontFaceQuartet() = default; + ON_FontFaceQuartet(const ON_FontFaceQuartet&) = default; + ON_FontFaceQuartet& operator=(const ON_FontFaceQuartet&) = default; + + ON_FontFaceQuartet( + const wchar_t* quartet_name, + const class ON_Font* regular, + const class ON_Font* bold, + const class ON_Font* italic, + const class ON_Font* bold_italic + ); + + static int CompareQuartetName( + const ON_FontFaceQuartet* lhs, + const ON_FontFaceQuartet* rhs + ); + + /* + Returns a sample rich text string demonstrating the faces in the quartet. + */ + const ON_wString RichTextSample( + ON::RichTextStyle rich_text_style + ) const; + +public: + static const ON_FontFaceQuartet Empty; + +public: + bool HasRegularFace() const; + bool HasBoldFace() const; + bool HasItalicFace() const; + bool HasBoldItalicFace() const; + bool HasAllFaces() const; + + + /// True if FaceCount() = 0. (The name may be empty or not empty.) + bool IsEmpty() const; + + /// True if FaceCount() > 0. (The name may be empty or not empty.) + bool IsNotEmpty() const; + + /// Total number of available faces (0 to 4). + unsigned int FaceCount() const; + + /// Number of faces that are not installed on this device (0 to FaceCount()). + unsigned int NotInstalledFaceCount() const; + + /// Number of faces that are simulated (0 to FaceCount()). + unsigned int SimulatedFaceCount() const; + + const ON_wString QuartetName() const; + const class ON_Font* RegularFace() const; + const class ON_Font* BoldFace() const; + const class ON_Font* ItalicFace() const; + const class ON_Font* BoldItalicFace() const; + + /* + Parameters: + font - [in] + Font to test + Returns: + If font exactly matches a quartet member, that member is identified. + Otherwise, ON_FontFaceQuartet::Member::Unset is returned. + */ + ON_FontFaceQuartet::Member QuartetMember( + const ON_Font* font + ) const; + + /* + Parameters: + member - [in] + Returns: + Specified quartet member. + */ + const ON_Font* Face( + ON_FontFaceQuartet::Member member + ) const; + + /* + Parameters: + member - [in] + Returns: + Closest quartet member. + */ + const ON_Font* ClosestFace( + ON_FontFaceQuartet::Member member + ) const; + + const ON_Font* Face( + bool bBold, + bool bItalic + ) const; + + const ON_Font* ClosestFace( + bool bPreferedBold, + bool bPreferedItalic + ) const; + + void Dump(ON_TextLog& text_log) const; + +private: + ON_wString m_quartet_name; + const class ON_Font* m_regular = nullptr; + const class ON_Font* m_bold = nullptr; + const class ON_Font* m_italic = nullptr; + const class ON_Font* m_bold_italic = nullptr; +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; +#endif + +/// +/// An ON_Font is a face in a font family. It corresponds to a Windows LOGFONT, +/// a .NET System.Drawing.Font or a FreeType FT_Face. +/// +class ON_CLASS ON_Font +{ +public: + + #pragma region RH_C_SHARED_ENUM [ON_Font::Origin] [Rhino.DocObjects.Font.FontOrigin] [nested:byte] + /// + /// Platform where font originated. This information is useful when + /// searching for appropriate substitues. + /// + enum class Origin : unsigned char + { + /// Not set. + Unset = 0, + + /// Origin unknown. Changing an ON_Font characteristic like weight or sytle sets the origin to unknown. + Unknown = 1, + + /// + /// Set from a Windows IDWriteFont by ON_Font::SetFromDWriteFont() + /// or a Windows LOGFONT by ON_Font::SetFromWindowsLogFont() and + /// FaceName and WindowLogfontName match a font installed on a Windows device. + /// + WindowsFont = 2, + + /// + /// Set from an Apple CTFont. The PostScriptName() and FamilyName() match a + /// font installed on device running MacOS or iOS. The FaceName() matches + /// the "typeface" name shonw in the MacOS FontBook app. + /// + AppleFont = 3 + }; +#pragma endregion + +#pragma region RH_C_SHARED_ENUM [ON_Font::FontType] [Rhino.DocObjects.Font.FontType] [nested:byte] + /// + /// An enum that reports if the font face is avaialable on the current device. + /// + enum class FontType : unsigned char + { + /// Not set. + Unset = 0, + + /// + /// In the managed font list. + /// + ManagedFont = 1, + + /// + /// In the installed font list. + /// + InstalledFont = 2 + }; +#pragma endregion + +#pragma region RH_C_SHARED_ENUM [ON_Font::Weight] [Rhino.DocObjects.Font.FontWeight] [nested:byte] + /// + /// Weight enum values + /// Avoid casting these values to int. + /// Use ON_Font::WindowsLogfontWeightFromWeight() or + /// ON_Font::AppleWeightOfFontFromWeight() or + /// add another converter. + /// + enum class Weight : unsigned char + { + /// Not set. + Unset = 0, + + /// IsLight = true + Thin = 1, + + /// IsLight = true + Ultralight = 2, + + //ExtraLight = 2, + + /// IsLight = true + Light = 3, + + /// Default font weight. IsNormalWeight = true Also called Regular. + Normal = 4, + + //Regular = 4, + + /// IsNormalWeight = true + Medium = 5, + + /// IsBold = true + Semibold = 6, + + //Demibold = 6, + //Demi = 6, + //Semi = 6, + + /// IsBold = true + Bold = 7, + + /// IsBold = true + Ultrabold = 8, + + //ExtraBold = 8, + + /// IsBold = true Also called Black + Heavy = 9 + + //Black = 9, + }; +#pragma endregion + + /* + Returns: + -1: weight_a is lighter, weight_b is heavier + +1: weight_a is heavier, weight_b is lighter + 0: weight_a = weight_b + */ + static int CompareWeight( + ON_Font::Weight weight_a, + ON_Font::Weight weight_b + ); + + /* + Description: + In the rare cases when an ON_Font::Weight value must be passed + as an unsigned int, use ON_Font::FontWeightFromUnsigned() to + convert the unsigned value to an ON_Font::Weight value. + Parameters: + unsigned_font_weight - [in] + */ + static ON_Font::Weight FontWeightFromUnsigned( + unsigned int unsigned_font_weight + ); + + /* + Description: + The correspondence between Windows LOGFONT lfWeight values and + ON_Font::Weight enum values is + ON_Font::Weight::Thin = 100 LOGFONT lfWeight + ON_Font::Weight::Ultralight = 200 LOGFONT lfWeight + ON_Font::Weight::Light = 300 LOGFONT lfWeight + ON_Font::Weight::Normal = 400 LOGFONT lfWeight + ON_Font::Weight::Medium = 500 LOGFONT lfWeight + ON_Font::Weight::Semibold = 600 LOGFONT lfWeight + ON_Font::Weight::Bold = 700 LOGFONT lfWeight + ON_Font::Weight::Ultrabold = 800 LOGFONT lfWeight + ON_Font::Weight::Heavy = 900 LOGFONT lfWeight + Returns: + The Windows LOGFONT lfWeight value that corresponds to the ON_Font::Weight enum value. + */ + static int WindowsLogfontWeightFromWeight( + ON_Font::Weight font_weight + ); + + /* + Description: + The correspondence between Apple "weight of font" values and + ON_Font::Weight enum values is + ON_Font::Weight::Thin = 1 + ON_Font::Weight::Ultralight = 2 + ON_Font::Weight::Light = 3 + ON_Font::Weight::Normal = 4 + ON_Font::Weight::Medium = 5 + ON_Font::Weight::Semibold = 6 + ON_Font::Weight::Bold = 7 + ON_Font::Weight::Ultrabold = 8 + ON_Font::Weight::Heavy = 9 + Returns: + The Apple "weight of font" value that corresponds to the ON_Font::Weight enum value. + */ + static int AppleWeightOfFontFromWeight( + ON_Font::Weight font_weight + ); + + /* + Description: + The correspondence between Apple "font weight trait" values and + ON_Font::Weight enum values is + ON_Font::Weight::Thin = -0.4 Apple font weight trait + ON_Font::Weight::Ultralight = -0.2667 Apple font weight trait + ON_Font::Weight::Light = -0.1333 Apple font weight trait + ON_Font::Weight::Normal = 0.0 Apple font weight trait + ON_Font::Weight::Medium = 0.1333 Apple font weight trait + ON_Font::Weight::Semibold = 0.2667 Apple font weight trait + ON_Font::Weight::Bold = 0.4 Apple font weight trait + ON_Font::Weight::Ultrabold = 0.5333 Apple font weight trait + ON_Font::Weight::Heavy = 0.6667 Apple font weight trait + Returns: + The Apple "WeightTrait" value that corresponds to the ON_Font::Weight enum value. + */ + static double AppleFontWeightTraitFromWeight( + ON_Font::Weight font_weight + ); + + /* + Description: + The correspondence between Windows LOGFONT lfWeight values and + ON_Font::Weight enum values is + + ON_Font::Weight::Thin = 100 + ON_Font::Weight::Ultralight = 200 + ON_Font::Weight::Light = 300 + ON_Font::Weight::Normal = 400 + ON_Font::Weight::Medium = 500 + ON_Font::Weight::Semibold = 600 + ON_Font::Weight::Bold = 700 + ON_Font::Weight::Ultrabold = 800 + ON_Font::Weight::Heavy = 900 + Returns: + The best ON_Font::Weight enum value for the Windows LOGFONT weight. + */ + + static ON_Font::Weight WeightFromWindowsLogfontWeight( + int windows_logfont_weight + ); + + /* + Description: + The correspondence between Apple "weight of font" values and + ON_Font::Weight enum values is + ON_Font::Weight::Thin = 1 + ON_Font::Weight::Ultralight = 2 + ON_Font::Weight::Light = 3 + ON_Font::Weight::Normal = 4 + ON_Font::Weight::Medium = 5 + ON_Font::Weight::Semibold = 6 + ON_Font::Weight::Bold = 7 + ON_Font::Weight::Ultrabold = 8 + ON_Font::Weight::Heavy = 9 + Returns: + The best ON_Font::Weight enum value for the Apple weight of font. + */ + static ON_Font::Weight WeightFromAppleWeightOfFont( + int apple_weight_of_font + ); + + /* + Parameters: + apple_font_weight_trait - [in] + Apple WeightTrait + The valid value range is from -1.0 to 1.0. The value of 0.0 corresponds to the regular or medium font weight. + */ + static ON_Font::Weight WeightFromAppleFontWeightTrait( + double apple_font_weight_trait + ); + + static const wchar_t* WeightToWideString( + ON_Font::Weight font_weight + ); + + /* + Returns: + True if weight is ON_Font::Weight::Semibold or heavier. + */ + static bool IsBoldWeight( + ON_Font::Weight weight + ); + + +#pragma region RH_C_SHARED_ENUM [ON_Font::Stretch] [Rhino.DocObjects.Font.FontStretch] [nested:byte] + /// + /// Horizontal expansion or contraction of font + /// + enum class Stretch : unsigned char + { + /// Not set. + Unset = 0, + /// + Ultracondensed = 1, + /// + Extracondensed = 2, + /// + Condensed = 3, + /// + Semicondensed = 4, + + /// Default font stretch. + Medium = 5, + + //Normal = 5, + + /// + Semiexpanded = 6, + /// + Expanded = 7, + /// + Extraexpanded = 8, + /// + Ultraexpanded = 9 + }; +#pragma endregion + + /* + Description: + In the rare cases when an ON_Font::Stretch value must be passed + as an unsigned int, use ON_Font::FontStretchFromUnsigned() to + convert the unsigned value to an ON_Font::Stretch value. + Parameters: + unsigned_font_stretch - [in] + */ + static ON_Font::Stretch FontStretchFromUnsigned( + unsigned int unsigned_font_stretch + ); + + static const wchar_t* StretchToWideString( + ON_Font::Stretch font_stretch + ); + +#if defined(ON_OS_WINDOWS_GDI) + static ON_Font::Stretch FontStretchFromDWriteStretch( + unsigned int dwrite_stretch, + ON_Font::Stretch undefined_result + ); +#endif + + + +#pragma region RH_C_SHARED_ENUM [ON_Font::Style] [Rhino.DocObjects.Font.FontStyle] [nested:byte] + /// + /// Vertical angle of font + /// Upright, Italic, or Oblique + /// + enum class Style : unsigned char + { + /// Not set. + Unset = 0, + + /// Default font style. + Upright = 1, + + //Normal = 1, + //Roman = 1, + + /// + /// The face is sloped so the top is to the right of the base. + /// Face names sometimes use the word "oblique" for italic faces. + /// + Italic = 2, + + /// + /// The face is sloped so the top is to the left of the base. + /// This is extremely rare. + /// NOTE WELL: Face names sometimes use the word "oblique" for italic faces. + /// + Oblique = 3 + }; +#pragma endregion + + /* + Description: + In the rare cases when an ON_Font::Style value must be passed + as an unsigned int, use ON_Font::FontStyleFromUnsigned() to + convert the unsigned value to an ON_Font::Style value. + Parameters: + unsigned_font_style - [in] + */ + static ON_Font::Style FontStyleFromUnsigned( + unsigned int unsigned_font_style + ); + + static const wchar_t* StyleToWideString( + ON_Font::Style font_style + ); + + + /* + Returns: + If this font is installed or managed, the installed or mangaged font face quartet is returned. + Otherwise ON_FontFaceQuartet::Empty is returned. + Note that managed font quartets can be enlarged to include missing faces by calling + ON_Font::FontFromRichTextProperties(). Installed font quartets exactly match + what is installed on the current defice. + if this font is not a member of an installed face quartet. + */ + const ON_FontFaceQuartet FontQuartet() const; + + /* + Returns: + The installed font face quartet for this font or ON_FontFaceQuartet::Empty + if this font is not a member of an installed face quartet. + */ + const ON_FontFaceQuartet InstalledFontQuartet() const; + +public: + + /* + Returns: + True if lhs an rhs are in the same font family. + */ + static bool EqualFontFamily( + const ON_Font* lhs, + const ON_Font* rhs + ); + + /* + Returns: + True if lhs and rhs have equal family names and equal face names + in with the name local or in English. + */ + static bool EqualFontFamilyAndFace( + const ON_Font* lhs, + const ON_Font* rhs + ); + + static bool EqualWeightStretchStyle( + const ON_Font* lhs, + const ON_Font* rhs, + bool bUnsetIsEqual + ); + + static bool EqualWeight( + const ON_Font* lhs, + const ON_Font* rhs, + bool bUnsetIsEqual + ); + + static bool EqualStretch( + const ON_Font* lhs, + const ON_Font* rhs, + bool bUnsetIsEqual + ); + + static bool EqualStyle( + const ON_Font* lhs, + const ON_Font* rhs, + bool bUnsetIsEqual + ); + + +public: + + // ON_Font::Default depends on the platform. + // Arial on Windows + // Helvetica Neue on Mac OS + static const ON_Font Default; + + // ON_Font::Unset has unset face name and platform font name. + static const ON_Font Unset; + + /* + Returns: + Windows: "Arial" + Apple: "Helvetica Neue" + */ + static const wchar_t* DefaultFamilyName(); + + /* + Returns: + Windows: "Regular" + Apple: "Regular" + */ + static const wchar_t* DefaultFaceName(); + + /* + Returns: + Windows: "ArialMT" + Apple: "HelveticaNeue" + */ + static const wchar_t* DefaultPostScriptName(); + + + /* + Returns: + Windows: "ArialMT" + Apple: "HelveticaNeue" + */ + static const wchar_t* DefaultWindowsLogfontName(); + + /* + Description: + This function is poorly designed, poorly named, named and doesn't do + anything very useful. Avoid it. It will be deleted when it is possible + to break the SDK. + Parameters: + face_name - [in] + Name to test + Returns: + False if face_name is nullptr, or face_name is the empty string, + or the first element in the name is < ON_wString::Space, + or the face_name contains any of these elements: ; " ' ` = # + True otherwise. + */ + static bool IsValidFaceName( + const wchar_t* face_name + ); + +private: + // This private constructor is used to construct ON_Font::Default, managed fonts, + // and installed fonts. Never make this constructor protected or public. + ON_Font( + ON_Font::FontType font_type, + const ON_Font& src + ); + +private: + // Use ON_Font( const ON_Font& ) or ON_Font::operator= if you need to make a copy. + // Never make CopyHelper protected or public. + void Internal_CopyFrom( + const ON_Font& src + ); + +public: + /* + Description: + Get a font managed by the application from the font characteristics. + Never delete a font returned by GetManagedFont(). + Parameters: + face_name - [in] + font_weight - [in] + default = ON_Font::Default.FontWeight() + font_style - [in] + default = ON_Font::Default.FontStyle() + font_stretch - [in] + default = ON_Font::Default.FontStretch() + bUnderlined - [in] + default = ON_Font::Default.Underlined() = false + bStrikethrough - [in] + default = ON_Font::Default.Strikethrough() = false + linefeed_ratio - [in] + default = ON_Font::Default.LinefeedRatio() + windows_charset - [in] + default = ON_Font::WindowsCharSet::DefaultCharSet + */ + static const ON_Font* GetManagedFont( + const wchar_t* face_name + ); + + static const ON_Font* GetManagedFont( + double point_size, + const wchar_t* face_name + ); + + static const ON_Font* GetManagedFont( + const wchar_t* face_name, + bool bBold + ); + + static const ON_Font* GetManagedFont( + double point_size, + const wchar_t* face_name, + bool bBold + ); + + static const ON_Font* GetManagedFont( + const wchar_t* face_name, + bool bBold, + bool bItalic + ); + + static const ON_Font* GetManagedFont( + double point_size, + const wchar_t* face_name, + bool bBold, + bool bItalic + ); + + static const ON_Font* GetManagedFont( + const wchar_t* face_name, + ON_Font::Weight font_weight, + ON_Font::Style font_style + ); + + static const ON_Font* GetManagedFont( + double point_size, + const wchar_t* face_name, + ON_Font::Weight font_weight, + ON_Font::Style font_style + ); + + static const ON_Font* GetManagedFont( + const wchar_t* face_name, + ON_Font::Weight font_weight, + ON_Font::Style font_style, + ON_Font::Stretch font_stretch, + bool bUnderlined, + bool bStrikethrough, + double linefeed_ratio, + unsigned int logfont_charset + ); + + static const ON_Font* GetManagedFont( + double point_size, + const wchar_t* face_name, + ON_Font::Weight font_weight, + ON_Font::Style font_style, + ON_Font::Stretch font_stretch, + bool bUnderlined, + bool bStrikethrough, + double linefeed_ratio, + unsigned int logfont_charset + ); + + static const ON_Font* GetManagedFontFromFontDescription( + const wchar_t* font_description + ); + +#if defined(ON_OS_WINDOWS_GDI) + /* + Description: + Get a managed font from a LOGFONT + Parameters: + map_mode - [in] + If map_mode is 0, then ::GetMapMode(hdc) is called to get the mapping mode. + Otherwised, map_mode must identify a Windows mapping mode + (MM_TEXT, MM_LOMETRIC, MM_HIMETRIC, MM_LOENGLISH, MM_HIENGLISH, M_TWIPS). + If map_mode = MM_TEXT (1), then hdc is used as described in the hdc parameter. + hdc - [in] + Windows device context. + If map_mode is set and not MM_TEXT, then hdc is ignored. + Otherwise the device context is used to get the mapping mode ( GetMapMode(hdc) ). + If the mapping mode is MM_TEXT, then the additional device context values + GetDeviceCaps(hdc, LOGPIXELSY) and conversion between device and logical pixel heights + DPtoLP(hdc,...) and LPtoDP(hdc,...) are used. + logfont - [in] + These logfont properties are used to find the managed font. + lfHeight (when dc is not zero) + lfWeight; + lfItalic; + lfUnderline; + lfStrikeOut; + lfCharSet; + lfFaceName[LF_FACESIZE]; + All other LOGFONT properties is ignored. + */ + static const ON_Font* GetManagedFontFromWindowsLogfont( + int map_mode, + HDC hdc, + const LOGFONT& logfont + ); + + enum : int + { + MAP_MODE_ZERO_ERROR_SUPPRESS = MM_MAX + 3 + }; +#endif + + ON_DEPRECATED_MSG("Use ON_Font::GetManagedFontFromPostScriptName()") + static const ON_Font* GetManagedFontFromAppleFontName( + const char* postscript_name + ); + + ON_DEPRECATED_MSG("Use ON_Font::GetManagedFontFromPostScriptName()") + static const ON_Font* GetManagedFontFromAppleFontName( + const wchar_t* postscript_name + ); + + /* + Parameters: + postscript_name - [in] + Windows: PostScript name = IDWriteFont.GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME,...) + Apple: PostScript name = CTFontCopyPostScriptName() / NSFont.fontName + */ + static const ON_Font* GetManagedFontFromPostScriptName( + const char* postscript_name + ); + + /* + Parameters: + postscript_name - [in] + Windows: PostScript name = IDWriteFont.GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME,...) + Apple: PostScript name = CTFontCopyPostScriptName() / NSFont.fontName + */ + static const ON_Font* GetManagedFontFromPostScriptName( + const wchar_t* postscript_name + ); + +#if defined(ON_RUNTIME_APPLE_CORE_TEXT_AVAILABLE) + static const ON_Font* GetManagedFontFromAppleCTFont( + CTFontRef apple_font, + bool bAnnotationFont + ); +#endif + +//#if defined(ON_RUNTIME_APPLE_OBJECTIVE_C_AVAILABLE) +// static const ON_Font* GetManagedFontFromAppleNSFont( +// NSFont* apple_font, +// bool bAnnotationFont +// ); +//#endif + + /* + Returns: + The managed font for this font. + Remarks: + If this->IsManagedFont() is true, then "this" is returned. + */ + const ON_Font* ManagedFont() const; + + /* + Description: + It is better to call ON_Font::FontFromRichTextProperties(). + Parameters: + rtf_font_name - [in] + Rich text format name. This name is not well defined and depends on + the device and application that created the rich text. On Windows this + is often a LOGFONT.lfFaceName. On MacOS it is often a PostScript name. + + bRtfBold - [in] + RTF bold flag + + bRtfItalic - [in] + RTF italic flag + Returns: + A managed font to use for these rich text properties. + */ + ON_DEPRECATED_MSG("Call ON_Font::FontFromRichTextProperties()") + static const ON_Font* ManagedFontFromRichTextProperties( + const wchar_t* rtf_font_name, + bool bRtfBold, + bool bRtfItalic, + bool bRftUnderlined, + bool bRftStrikethrough + ); + + static const ON_wString RichTextPropertiesToString( + bool bRtfBold, + bool bRtfItalic, + bool bRtfUnderlined, + bool bRtfStrikethrough + ); + + static const ON_wString RichTextPropertiesToString( + ON_Font::Weight rtf_weight, + ON_Font::Style rtf_style, + bool bRtfUnderlined, + bool bRtfStrikethrough + ); + + static const ON_wString RichTextPropertiesToString( + const ON_Font* font + ); + + /* + Returns: + The list of managed fonts in a class with lots of searching tools. + */ + static const class ON_FontList& ManagedFontList(); + + /* + Description: + Look for a font installed on the current device that matches this font. + The Strikethrough, Underlined, and PointSize properties are ignored. + Parameters: + bAllowBestMatch - [in] + If no exact match is available and bAllowBestMach is true and + there are installed fonts with a matching familiy name, + then the best match in the family is returned. + Returns: + If there is a matching installed font, it is returned. + Otherwise, nullptr is returned. + */ + const ON_Font* InstalledFont( + bool bAllowBestMatch + ) const; + + /* + Parameters: + desired_weight - [in] + Pass ON_Font::Weight::Unset if you do not want to change the weight. + desired_stretch - [in] + Pass ON_Font::Stretch::Unset if you do not want to change the stretch. + desired_style - [in] + Pass ON_Font::Style::Unset if you do not want to change the style. + + Returns: + The installed font in the same family as this with the best match + for the desired weight, stretch, and style. + If nothing close to suitable is available, nullptr is returned. + */ + const ON_Font* InstalledFamilyMemberWithWeightStretchStyle( + ON_Font::Weight desired_weight, + ON_Font::Stretch desired_stretch, + ON_Font::Style desired_style + ) const; + + + /* + Parameters: + desired_weight - [in] + Pass ON_Font::Weight::Unset if you do not want to change the weight. + desired_stretch - [in] + Pass ON_Font::Stretch::Unset if you do not want to change the stretch. + desired_style - [in] + Pass ON_Font::Style::Unset if you do not want to change the style. + bUnderlined - [in] + bStrikethrough - [in] + + Returns: + The installed font in the same family as this with the best match + for the desired weight, stretch, and style. + If nothing close to suitable is available, nullptr is returned. + */ + const ON_Font* ManagedFamilyMemberWithWeightStretchStyle( + ON_Font::Weight desired_weight, + ON_Font::Stretch desired_stretch, + ON_Font::Style desired_style, + bool bUnderlined, + bool bStrikethrough + ) const; + + /* + Parameters: + bBold - [in] + True for the rich text quartet "bold face" with is typically heavier than the "regular" face. + bItalic - [in] + True for the rich text quartet "italic" with is typically more slanted than the "regular" face. + bUnderlined - [in] + True for an underlined face + bStrikethrough - [in] + True for a strikethrough face + Returns: + ON_Font::ManagedFontFromRichTextProperties(this->RichTextName(),bBold,bItalic,bUnderlined,bStrikethrough); + */ + const ON_Font* ManagedFamilyMemberWithRichTextProperties( + bool bBold, + bool bItalic, + bool bUnderlined, + bool bStrikethrough + ) const; + + /* + Returns: + The list of installed fonts in a class with lots of searching tools. + */ + static const class ON_FontList& InstalledFontList(); + + /* + Description: + Tests InstalledFontList(). + Parameters: + text_log - [in] + Summary of the test. + If errors are detected, they are printed in error_log. + Returns: + true: Test passed - no errors detected. + false: Test failed. + */ + static bool TestInstalledFontList( + class ON_TextLog& text_log + ); + + /* + Description: + This is the best way to get a font from rich text properties. + Parameters: + rich_text_font_name - [in] + Rich text quartet name. If you have an ON_Font, then ON_Font.RichTextName() + gets a good choice for this name. + * For Windows installed fonts, this is identical to the Windows LOGFONT.lfFaceName. + * For MacOS this is an invented name and is chosen to work cross platform as well + as possible. For Apple families with up to 4 faces that align with the rich text + quartet "regular/bold/italic/bold-italic" faces, things tend to work as expected. + for common Apple families like Helvetica Neue with a dozen or so faces that are + designed to work well for western european languages, opennurbs selects 4 faces in + the family that tend to align with would many people expect as the rich text + "regular/bold/italic/bold-italic" face. Things get dicier with less common + families and fonts designed for non-western european languages. + Basically, Apple and richt text do not play nicely together. + + bBoldQuartetMember - [in] + True to select the heavier members of the rich text quartet. + + bItalicQuartetMember - [in] + True to select the more slanted memmers of the rich text quartet. + + bUnderlined - [in] + True if you want underlined text. + (Underlining is created as a rendering effect and not a separate face.) + + bStrikethrough - [in] + True if you want strikethrough text. + (Strikethrough is created as a rendering effect and not a separate face.) + + Returns: + If there is an installed font, it is returned. Othewise a managed font + is returned. When the managed font is not installed, the corresponding + member of ON_Font::Default::InstalledQuartet() is used to render the font. + */ + static const ON_Font* FontFromRichTextProperties( + ON_wString rich_text_font_name, + bool bBoldQuartetMember, + bool bItalicQuartetMember, + bool bUnderlined, + bool bStrikethrough + ); + + +private: + // this must be a managed or installed font. + const ON_Font* Internal_DecoratedFont( + bool bUnderlined, + bool bStrikethrough + ) const; + +public: + + /* + Description: + Unless you are certain you want to restrict your choices to installed fonts, + it is better to call ON_Font::FontFromRichTextProperties(). + Parameters: + rtf_font_name - [in] + Rich text quartet neame. This name is not well defined and depends on + the device and application that created the rich text. For Windows installed + fonts, this is identical to the Windows LOGFONT.lfFaceName. + On MacOS this is a name Rhino cooks up and is chosen to + work cross platform as well as possible. Apple and richt text do not + play nicely together. + bRtfBold - [in] + True to prefer the heavier memmbers of the installed rich text quartet. + bRtfItalic - [in] + True to prefer the more slanted memmbers of the installed rich text quartet. + Returns: + An installed font to use for this rich text face font or nullptr if the current + device does not have a in installed font with for this rich text quartet. + */ + static const ON_Font* InstalledFontFromRichTextProperties( + const wchar_t* rtf_font_name, + bool bRtfBold, + bool bRtfItalic + ); + + /* + Description: + Returns the glpyh informationh for used to render a specific code point + Parameters: + unicode_code_point + UNICODE code point value + Returns: + Glyph rendering information. + + Remarks: + Typically the returned glpyh uses is a single glpyh in this->ManagedFont(). + In this case, glyph->SubstitueCount() is 0. + + In some cases one or more glyphs from one or more substitute fonts are required + to render the code point. In this case, glyph->SubstitueCount() is 0. + + Example: + ON_Font* font = ...; + unsigned int code_point = ...; + const ON_FontGlyph* g = font->CodePointGlyph(code_point); + if (nullptr != g ) + { + if ( g->SubstituteCount() > 0 ) + { + // complicate case - one of more substitutes must be rendered to render g + for ( const ON_FontGlyph* gsub = g.NextSubstitute(); nullptr != gsub; gsub = gsub->NextSubstitute() ) + { + ... + } + } + else + { + // simple case - this computer can directly render g + ... + } + } + */ + const class ON_FontGlyph* CodePointGlyph( + ON__UINT32 unicode_code_point + ) const; + +private: + friend class ON_FontGlyph; + friend class ON_FontList; + const class ON_FontGlyph* Internal_ManagedCodePointGlyph( + ON__UINT32 unicode_code_point, + bool bCreateIfMissing, + bool bFindSubstitutes + ) const; + +public: + + /* + Description: + When reading version 5 3dm achives, the font description can be + a generic font description or an Apple font name. This function + rejects certain descriptions like "Default" and "Arial" for + use as Apple font names. + */ + static bool IsNotAppleFontName( + const wchar_t* font_description + ); + + static const ON_Font* GetManagedFont( + const ON_Font& font_characteristics, + bool bCreateIfNotFound + ); + + /* + Returns: + If there is a managed font with the specified serial number, it is returned. + Otherwise, nullptr is returned. + */ + static const ON_Font* GetManagedFontFromSerialNumber( + unsigned int managed_font_runtime_serial_number + ); + + /* + Parameters: + managed_fonts - [out] + The current list of managed fonts. + Returns: + Number of managed fonts. + */ + static unsigned int GetManagedFontList( + ON_SimpleArray< const ON_Font* >& managed_fonts + ); + + /* + Parameters: + installed_fonts - [out] + A list of all fonts available on the current computer + sorted by font family name. + Returns: + Number of fonts available on the current computer. + */ + static unsigned int GetInstalledFontList( + ON_SimpleArray< const ON_Font* >& installed_fonts + ); + + /* + Parameters: + font_family_name - [in] + A font family name like Arial or Helvetica. + bIncludePartialMatch - [in] + If true, family names that begin with font_family_name + will be included. + installed_fonts - [out] + A list of all fonts available on the current computer + with a matching font family name. + Returns: + Number of fonts available on the current computer. + */ + static unsigned int GetInstalledFontFamily( + const wchar_t* font_family_name, + ON_SimpleArray< const ON_Font* >& installed_fonts + ); + + /* + Parameters: + font_list - [in] + Fonts to search for a match. All fonts in this list + are tested (search time is proportional to font_list.Count()). + If the list returned by GetInstalledFontFamily() contains + reasonable options, it is a good choice for the font_list[] + parameter. + Returns: + A pointer to the font in font_list[] that is the best + match to this. + */ + const ON_Font* BestMatch( + const ON_SimpleArray< const ON_Font* >& font_list + ) const; + + /* + Parameters: + font_list - [in] + Fonts to search for a match. All fonts in this list + are tested (search time is proportional to font_list.Count()). + If the list returned by GetInstalledFontFamily() contains + reasonable options, it is a good choice for the font_list[] + parameter. + font_count - [in] + Number of elements in the font_list[] array. + Returns: + A pointer to the font in font_list[] that is the best + match to this. + */ + const ON_Font* BestMatch( + ON_Font const*const* font_list, + size_t font_count + ) const; + + static unsigned int WeightStretchStyleDeviation( + ON_Font::Weight prefered_weight, + ON_Font::Stretch prefered_stretch, + ON_Font::Style prefered_style, + ON_Font::Weight available_weight, + ON_Font::Stretch available_stretch, + ON_Font::Style available_style + ); + + static unsigned int WeightStretchStyleDeviation( + ON_Font::Weight prefered_weight, + ON_Font::Stretch prefered_stretch, + ON_Font::Style prefered_style, + const ON_Font* available_font + ); + + static unsigned int WeightStretchStyleDeviation( + const ON_Font* prefered_weight_stretch_style, + const ON_Font* available_font + ); + + static unsigned int UnderlinedStrikethroughDeviation( + bool bPreferedUnderline, + bool bPreferedStrikethrough, + bool bAvailableUnderline, + bool bAvailableStrikethrough + ); + + static unsigned int UnderlinedStrikethroughDeviation( + bool bPreferedUnderline, + bool bPreferedStrikethrough, + const ON_Font* available_font + ); + + static unsigned int UnderlinedStrikethroughDeviation( + const ON_Font* prefered_underlined_strikethrough, + const ON_Font* available_font + ); + + static unsigned int RichTextPropertyDeviation( + bool bPreferedRtfBold, + bool bPreferedItalic, + bool bPreferedUnderline, + bool bPreferedStrikethrough, + bool bAvailableRtfBold, + bool bAvailableItalic, + bool bAvailableUnderline, + bool bAvailableStrikethrough + ); + + static unsigned int RichTextPropertyDeviation( + bool bPreferedRtfBold, + bool bPreferedItalic, + bool bPreferedUnderline, + bool bPreferedStrikethrough, + const ON_Font* available_font + ); + +private: + static const ON_Font* Internal_BestMatchWeightStretchStyle( + ON_Font::Weight prefered_weight, + ON_Font::Stretch prefered_stretch, + ON_Font::Style prefered_style, + ON_Font const*const* font_list, + size_t font_count + ); + +public: + + /* + Returns: + True if this font is a managed font returned by one of the + static ON_Font::GetManagedFont(...) functions. + Remarks: + ON_Font::Default is managed. + */ + bool IsManagedFont() const; + + /* + Returns: + True if this is a managed font and the font is installed on this device. + False otherwise. + Remarks: + If this->IsManagedFont() is true, then exactly one of IsManagedInstalledFont() + or IsManagedSubstitutedFont() is true. + When this->IsManagedInstalledFont() is true, this->InstalledFont() returns the installed font. + */ + bool IsManagedInstalledFont() const; + + /* + Returns: + True if this font is a managed font that references a font that is not installed on this computer. + Remarks: + If this->IsManagedFont() is true, then exactly one of IsManagedInstalledFont() + or IsManagedSubstitutedFont() is true. + When this->IsManagedSubstitutedFont() is true, this->SubstituteFont() returns the installed font. + */ + bool IsManagedSubstitutedFont() const; + + /* + Returns: + If this font is a managed font that references a font that is not installed on this computer, + then a pointer to the installed font that is the substitue for the missing font is returned. + Otherwise nullptr is returned. + */ + const ON_Font* SubstituteFont() const; + + /* + Returns: + True if this font is a mangaged font with a face that is installed on the current device + or this is an installed font returned by a function like ON_Font::InstalledFont(), + ON_Font::GetInstalledFontFamily(), or ON_Font::GetInstalledFontList(). + False in all other cases. + */ + bool IsInstalledFont() const; + +private: + const ON_Font* Internal_ManagedFontToInstalledFont() const; + +public: + ON_Font(); + ~ON_Font() = default; + ON_Font(const ON_Font& src); + ON_Font& operator=(const ON_Font& src); + +public: + /* + Description: + Create a font with a specified facename and properties. + Parameters: + gdi_logfont_name - [in] + Windows LOGFONT.lfFaceName. + bBold - [in] + True for a bold version of the font. + bItalic - [in] + True for an italic version of the font. + Returns: + True if the font characteristics were valid and set on the font. + */ + bool SetFontCharacteristics( + const wchar_t* gdi_logfont_name, + bool bBold, + bool bItalic, + bool bUnderlined, + bool bStrikethrough + ); + + /* + Description: + Create a font with a specified facename and properties. + Parameters: + point_size - [in] + If point_size > 0.0, then it specifies which size of font definition + should be used. Otherwise the font size used for annotation text + is used. + For high quality fonts it is generally the case that + different point sizes of the same font face have + subtle differences in glyph design and are not + simply scaled versions of a base glyph. + face_name - [in] + Windows LOGFONT.lfFaceName value. + bBold - [in] + True for a bold version of the font. + bItalic - [in] + True for an italic version of the font. + Returns: + True if the font characteristics were valid and set on the font. + */ + bool SetFontCharacteristics( + double point_size, + const wchar_t* gdi_logfont_name, + bool bBold, + bool bItalic, + bool bUnderlined, + bool bStrikethrough + ); + + /* + Description: + Set the font's face name and characteristics. + Parameters: + gdi_logfont_name - [in] + Windows LOGFONT.lfFaceName value. + Returns: + True if the font characteristics were valid and set on the font. + */ + bool SetFontCharacteristics( + const wchar_t* gdi_logfont_name, + ON_Font::Weight font_weight, + ON_Font::Style font_style, + ON_Font::Stretch font_stretch, + bool bUnderlined, + bool bStrikethrough + ); + + bool SetFontCharacteristics( + double point_size, + const wchar_t* gdi_logfont_name, + ON_Font::Weight font_weight, + ON_Font::Style font_style, + ON_Font::Stretch font_stretch, + bool bUnderlined, + bool bStrikethrough + ); + + bool SetFontCharacteristics( + const wchar_t* gdi_logfont_name, + ON_Font::Weight font_weight, + ON_Font::Style font_style, + ON_Font::Stretch font_stretch, + bool bUnderlined, + bool bStrikethrough, + double linefeed_ratio, + unsigned int logfont_charset + ); + + bool SetFontCharacteristics( + double point_size, + const wchar_t* gdi_logfont_name, + ON_Font::Weight font_weight, + ON_Font::Style font_style, + ON_Font::Stretch font_stretch, + bool bUnderlined, + bool bStrikethrough, + double linefeed_ratio, + unsigned int logfont_charset + ); + + bool SetFontCharacteristicsForExperts( + double point_size, + const ON_wString postscript_name, + const ON_wString quartet_name, + ON_FontFaceQuartet::Member quartet_member, + const ON_wString family_name, + const ON_wString face_name, + ON_Font::Weight font_weight, + ON_Font::Style font_style, + ON_Font::Stretch font_stretch, + bool bUnderlined, + bool bStrikethrough, + unsigned char logfont_charset, + int windows_logfont_weight, + double apple_font_weight_trait, + ON_PANOSE1 panose1 + ); + + + /* + Description: + The font properties weight, style, stretch, underlined, + and strikethrough are encoded in the returned value. + Remarks: + This is a legacy value used in 3dm archive reading/writing + and some sorting operations. + */ + unsigned int FontCharacteristicsAsUnsigned() const; + +private: + /* + Description: + All font characterisics defined by the input parameters are encoded + in the returned value. + Remarks: + Used in 3dm archive reading/writing. + */ + static unsigned int Internal_FontCharacteristicsAsUnsigned( + ON_Font::Weight font_weight, + ON_Font::Style font_style, + ON_Font::Stretch font_stretch, + bool bUnderlined, + bool bStrikethrough + ); + + /* + Description: + All font characterisics except facename (weight, style, stretch, + underlined, strikethrough, charset) are encoded in the returned + value. + Parameters: + font_characteristics_as_unsigned - [in] + Value returned from ON_Font.FontCharacteristicsAsUnsigned() + Returns: + True if the characterstics were set. + Remarks: + Used in 3dm archive reading/writing. + */ + bool Internal_SetFontCharacteristicsFromUnsigned( + unsigned int font_characteristics_as_unsigned + ); + + static void Internal_GetFontCharacteristicsFromUnsigned( + unsigned int font_characteristics_as_unsigned, + ON_Font::Weight& font_weight, + ON_Font::Stretch& font_stretch, + ON_Font::Style& font_style, + bool& bUnderlined, + bool& bStrikethrough + ); + +public: + /* + Description: + Returns a 32-bit crc of the font weight, style, stretch, underline, strikethrough, + and WIndows logfont name characteristics. + + Parameters: + bIgnoreWindowsLogfontNameOrdinalCase - [in] + If true, ON_wString::MapStringOrdinal() is applied to the windows logfont name + and the returned CRC is ordinal case independent. + */ + ON__UINT32 CRC32( + bool bIgnoreNameOrdinalCase + ) const; + +public: +// BUSTED #pragma region RH_BUSTED_C_SHARED_ENUM [ON_Font::NameLocale] [Rhino.DocObjects.Font.NameLocale] [nested:byte] + /// + /// ON_Font::NameLocale selects what locale is used for font name (PostScript, family, face, LOGFONT) queries. + /// + enum class NameLocale : ON__UINT8 + { + /// + /// If the localalized name is not empty, return it. Otherwise return the en-us name. + /// + LocalizedFirst = 0, + + /// + /// Localized name. + /// + Localized = 1, + + /// + /// en-us name. + /// + English = 2 + }; +// BUSTED #pragma endregion + + /* + Returns: + Locale for the font localized font names. + */ + const ON_wString Locale() const; + + /* + Returns: + The font's PostScript name. + Remarks: + The PostScript name is not always unique for each face. For example, + OpenType variable fonts like Windows 10 Bahnschrift have "Bahnschrift" + as the PostScript name for at least 10 different Bahnschrift faces. + + Platform equivalents: + Apple: = CTFontCopyPostScriptName(...) / NSFont.fontName + Windows: = IDWriteFont.GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME,...) + */ + const ON_wString PostScriptName( + ON_Font::NameLocale name_locale + ) const; + + /* + Returns: + ON_Font::PostScriptName(ON_Font::NameLocale::LocalizedFirst) + */ + const ON_wString PostScriptName() const; + + /* + Returns: + The font's family name. + Remarks: + Typically a font family has many faces. + + Platform equivalents: + Apple: = CTFontCopyFamilyName(...) / NSFont.familyName + Windows: = IDWriteFontFamily.GetFamilyNames() + + NOTE WELL: This is NOT the Windows LOGFONT lfFaceName. + */ + const ON_wString FamilyName( + ON_Font::NameLocale name_locale + ) const; + + /* + Returns: + ON_Font::FamilyName(ON_Font::NameLocale::LocalizedFirst) + */ + const ON_wString FamilyName() const; + + /* + Returns: + The font's face name. + Remarks: + Typically a font family has many faces and the face name gives a clue about the + weight, stretch, and style of the face. + + For example, Arial is a common font family that often includes faces like + "Regular", "Bold", "Italic", "Bold Italic", + "Narrow", "Narrow Bold", "Narrow Italic", "Narrow Bold Italic", + "Black", and "Black Oblique". + + Platform equivalents: + Apple: = not available + Windows: = IDWriteFontFamily.GetFaceNames() + + NOTE WELL: This is NOT the Windows LOGFONT lfFaceName. + */ + const ON_wString FaceName( + ON_Font::NameLocale name_locale + ) const; + + /* + Returns: + ON_Font::FaceName(ON_Font::NameLocale::LocalizedFirst) + */ + const ON_wString FaceName() const; + + + /* + Returns: + The font's Windows GDI LOGFONT.lfFaceName. + Remarks: + This name is preserved so Rhino can write early version files and + so some old code can use Windows GDI tools. + Every effort should be made to avoid using Windows LOGFONT lfFaceName. + */ + const ON_wString WindowsLogfontName( + ON_Font::NameLocale name_locale + ) const; + + /* + Returns: + ON_Font::WindowsLogfontName(ON_Font::NameLocale::LocalizedFirst) + */ + const ON_wString WindowsLogfontName() const; + + /* + Description: + On non-WIndows platforms like Mac OS, iOS, and Android, this function can + be used to generate fake windows logfont names. + For fonts that have at most 4 faces with the same stretch and variations + in weight and slant, the family_name is a good choice. + For fonts that have many faces, like Helvetica Neue on Mac OS, + this funciton will generate names that act like a Windows LOGFONT name + for use in archaic name + regular/bold/italic/bold-italic font selction + user interfaces. + Returns: + A fake windows logfont name. + */ + static const ON_wString FakeWindowsLogfontNameFromFamilyAndPostScriptNames( + ON_wString family_name, + ON_wString postscript_name + ); + + /* + Returns: + Name of the quartet for this font. See ON_FontFaceQuartet for more details. + */ + const ON_wString QuartetName( + ON_Font::NameLocale name_locale + ) const; + + /* + Returns: + Name of the quartet for this font. See ON_FontFaceQuartet for more details. + */ + const ON_wString QuartetName() const; + + /* + Returns: + If known, this font's quartet face (regular, bold, italic, bold-italic). + Otherwise ON_FontFaceQuartet::Member::Unset + Remarks: + For Windows installed fonts, the LOGFONT partition determines the quartet face. + On Apple platforms, opennurbs uses a table for common fonts and leaves the rest unset. + When unset, this is the best way to determine which quartet member this font represents. + In all cases, the absolute weight or the ON_Font.IsBold() is unreliable and should + be avoided at all costs. + */ + ON_FontFaceQuartet::Member QuartetFaceMember() const; + + /* + Description: + Get a string like "Arial (Regular)" that describes this font's quartet. + Returns: + quartet name + (face) + */ + const ON_wString QuartetDescription() const; + + /* + Returns: + A long description that includes family, face, weight, stretch and style information. + Generally not useful for finding matching fonts. + Remarks: + Calls + ON_Font.Description(ON_Font::NameLocale::localizeFirst, ON_wString::HyphenMinus,ON_wString::Space,true) + */ + const ON_wString Description() const; + + const ON_wString WidthWeightSlantDescription() const; + + static const ON_wString WidthWeightSlantDescription(ON_Font::Stretch width, ON_Font::Weight weight, ON_Font::Style slant); + + + /* + Description: + Get a text descripton with family weight, width (stretch), slope (style). + Parameters: + family_separator - [in] + character to place after family name in the description. + 0 = no separator. + 0, ON_wSting::HyphenMinus, and ON_wString::Space are common choices. + weight_width_slope_separator - [in] + character to place bewtween weight, stretch, and style descriptions + 0 = no separator. + 0, ON_wSting::HyphenMinus, and ON_wString::Space are common choices. + bIncludeUndelinedAndStrikethrough - [in] + If true, underlined and strikethrough attributes are appended + 0 = no separator. + 0, ON_wSting::HyphenMinus, and ON_wString::Space are common choices. + Returns: + A font description with family name, weight, stretch, and style. + If present, the weight, stretch, style, underlined, and strikethrough + descriptions begin with a capital letter followed by lowercase letters. + Remarks: + A description similar to the PostScript name is returned by + DescriptionFamilyWeightStretchStyle(ON_wString::HyphenMinus,0,false). + However, this often differs from the actual PostScript name. + */ + const ON_wString Description( + ON_Font::NameLocale name_local, + wchar_t family_separator, + wchar_t weight_width_slope_separator, + bool bIncludeUndelinedAndStrikethrough + ) const; + + + + /* + Description: + Get a text descripton with family weight, width (stretch), slope (style). + Parameters: + family_separator - [in] + character to place after family name in the description. + 0 = no separator. + 0, ON_wSting::HyphenMinus, and ON_wString::Space are common choices. + weight_width_slope_separator - [in] + character to place bewtween weight, stretch, and style descriptions + 0 = no separator. + 0, ON_wSting::HyphenMinus, and ON_wString::Space are common choices. + bIncludeUndelinedAndStrikethrough - [in] + If true, underlined and strikethrough attributes are appended + 0 = no separator. + 0, ON_wSting::HyphenMinus, and ON_wString::Space are common choices. + bIncludeNotOnDevice - [in] + If true and this->IsManagedSubstitutedFont() is true, then the + returned string begins with "[Not on device]" followed by the font's + description. + Returns: + A font description with family name, weight, stretch, and style. + If present, the weight, stretch, style, underlined, and strikethrough + descriptions begin with a capital letter followed by lowercase letters. + Remarks: + A description similar to the PostScript name is returned by + DescriptionFamilyWeightStretchStyle(ON_wString::HyphenMinus,0,false). + However, this often differs from the actual PostScript name. + */ + const ON_wString Description( + ON_Font::NameLocale name_local, + wchar_t family_separator, + wchar_t weight_width_slope_separator, + bool bIncludeUndelinedAndStrikethrough, + bool bIncludeNotOnDevice + ) const; + +private: + static const ON_wString& Internal_GetName( + ON_Font::NameLocale name_locale, + const ON_wString& localized_name, + const ON_wString& english_name + ); + + +#if defined(ON_OS_WINDOWS_GDI) + +public: + /* + Description: + Get the scale factors for converting heights beween + Windows device coordinates and Windows logical coordinates. + + Parameters: + hdc - [in] + Windows device context. + The device context is used to get the conversion between device + and logical pixel heights. The Windows GDI functions + DPtoLP(hdc,...) and LPtoDP(hdc,...) are used. + + device_to_logical_scale - [out] + logical_height = device_to_logical_scale*device_height + + logical_to_device_scale - [out] + device_height = logical_to_device_scale*logical_height + + Returns: + True if successful. + False otherwise. In the returned scale factors are set to 1.0. + */ + static bool GetWindowsDeviceToLogicalHeightScales( + HDC hdc, + double* device_to_logical_scale, + double* logical_to_device_scale + ); + + /* + Description: + Convert a character height in points to a Windows LOGFONT lfHeight value (negative number). + + The mapping mode determines the length unit system for the returned value. + + + The Windows convention is to use negative lfHeight values to specify + font character heights and postive height values to specify font cell heights. + + font cell height = font acsent + font descent. + + font character height = Cell height - internal leading. + + Parameters: + map_mode - [in] + If map_mode is 0, then ::GetMapMode(hdc) is called to get the mapping mode. + Otherwised, map_mode must identify a Windows mapping mode + (MM_TEXT, MM_LOMETRIC, MM_HIMETRIC, MM_LOENGLISH, MM_HIENGLISH, M_TWIPS). + If map_mode = MM_TEXT (1), then hdc is used as described in the hdc parameter. + + hdc - [in] + Windows device context. + If map_mode is set and not MM_TEXT, then hdc is ignored. + Otherwise the device context is used to get the mapping mode ( GetMapMode(hdc) ). + If the mapping mode is MM_TEXT, then the additional device context values + GetDeviceCaps(hdc, LOGPIXELSY) and conversion between device and logical pixel heights + DPtoLP(hdc,...) and LPtoDP(hdc,...) are used. + + point_size - [in] + Font character height in points (1 point = 1/72 inch = 25.4/72 millimeters). + In terms of font metrics, character height = ascent + descent - internal leading. + + Returns: + LOGFONT lfHeight value. + + This value is always negative. + + The absolute value of the returned value + = character height + = ascent + descent - internal leading + For many common fonts, the "character height" is close to the distance + from the bottom of a lower case g to the top of an upper case M. + The internal leading is space reseved for diacritical marks like the + ring above the A in the UNICODE "LATIN LETTER A WITH RING" U+00C5 glyph. + Character height is also known as the "em height". + Note that the "em height" is typically larger than the height of the + letter M because "em height" inlcude descent. + */ + static int WindowsLogfontCharacterHeightFromPointSize( + int map_mode, + HDC hdc, + double point_size + ); + + /* + Parameters: + map_mode - [in] + If map_mode is 0, then ::GetMapMode(hdc) is called to get the mapping mode. + Otherwised, map_mode must identify a Windows mapping mode + (MM_TEXT, MM_LOMETRIC, MM_HIMETRIC, MM_LOENGLISH, MM_HIENGLISH, M_TWIPS). + If map_mode = MM_TEXT (1), then hdc is used as described in the hdc parameter. + + hdc - [in] + Windows device context. + If map_mode is set and not MM_TEXT, then hdc is ignored. + Otherwise the device context is used to get the mapping mode ( GetMapMode(hdc) ). + If the mapping mode is MM_TEXT, then the additional device context values + GetDeviceCaps(hdc, LOGPIXELSY) and conversion between device and logical pixel heights + DPtoLP(hdc,...) and LPtoDP(hdc,...) are used. + + logfont_character_height - [in] + This value must be a Windows LOGFONT character height in units + determine from map_mode and hdc. If you have a LOGFONT with postive + lfHeight value, you must get the fonts TEXTMETRICS and subbr + + Returns: + Character height in points (1 point = 1/72 inch). + + font character height = font ascent + font descent - font internal leading. + + Remarks: + See ON_Font::PointSize() for information about point units, + font character height, and font cell height. + */ + static double PointSizeFromWindowsLogfontCharacterHeight( + int map_mode, + HDC hdc, + int logfont_character_height + ); + + /* + Description: + Get a Windows LOGFONT character height + = -(TEXTMETRIC.tmAscent + TEXTMETRIC.tmDescent - TEXTMETRIC.tmLeading ) + as a negative integer. + + Parameters: + map_mode - [in] + The best results are obtained when map_mode = MM_TEXT and the hdc is + correctly set for the context where the font is being rendered. Otherwise + the loss of precision when length units system conversion scale factors + are applied and results are stored in int LOGFONT and TEXTMETRIC fields + lead to discrepancies. + + If map_mode is 0, then ::GetMapMode(hdc) is called to get the mapping mode. + Otherwised, map_mode must identify a Windows mapping mode + (MM_TEXT, MM_LOMETRIC, MM_HIMETRIC, MM_LOENGLISH, MM_HIENGLISH, M_TWIPS). + If map_mode = MM_TEXT (1), then hdc is used as described in the hdc parameter. + + hdc - [in] + Windows device context. + If map_mode is set and not MM_TEXT, then hdc is ignored. + Otherwise the device context is used to get the mapping mode ( GetMapMode(hdc) ). + If the mapping mode is MM_TEXT, then the additional device context values + GetDeviceCaps(hdc, LOGPIXELSY) and conversion between device and logical pixel heights + DPtoLP(hdc,...) and LPtoDP(hdc,...) are used. + + logfont - [in] + If logfont.lfHeight <= 0, then logfont.lfHeight is returned. + If logfont.lfHeight > 0, then logfont face name, map_mode and hdc are + used to calculate the font's TEXTMETRICS tmInternalLeading value + -((tm.tmAscent + tm.tmDescent) - tmInternalLeading) is returned. + + Returns: + 0: failure + <0: Windows LOGFONT character height in units specified by map_mode and hdc. + */ + static int WindowsLogfontCharacterHeight( + int map_mode, + HDC hdc, + const LOGFONT& logfont + ); + + /* + Description: + Get a Windows LOGFONT cell height + = (TEXTMETRIC.tmAscent + TEXTMETRIC.tmDescent) + as a positive integer. + + Parameters: + map_mode - [in] + The best results are obtained when map_mode = MM_TEXT and the hdc is + correctly set for the context where the font is being rendered. Otherwise + the loss of precision when length units system conversion scale factors + are applied and results are stored in int LOGFONT and TEXTMETRIC fields + lead to discrepancies. + + If map_mode is 0, then ::GetMapMode(hdc) is called to get the mapping mode. + Otherwised, map_mode must identify a Windows mapping mode + (MM_TEXT, MM_LOMETRIC, MM_HIMETRIC, MM_LOENGLISH, MM_HIENGLISH, M_TWIPS). + If map_mode = MM_TEXT (1), then hdc is used as described in the hdc parameter. + + hdc - [in] + Windows device context. + If map_mode is set and not MM_TEXT, then hdc is ignored. + Otherwise the device context is used to get the mapping mode ( GetMapMode(hdc) ). + If the mapping mode is MM_TEXT, then the additional device context values + GetDeviceCaps(hdc, LOGPIXELSY) and conversion between device and logical pixel heights + DPtoLP(hdc,...) and LPtoDP(hdc,...) are used. + + logfont - [in] + If logfont.lfHeight >= 0, then logfont.lfHeight is returned. + If logfont.lfHeight < 0, then logfont face name, map_mode and hdc are + used to calculate the font's TEXTMETRIC and + (tm.tmAscent + tm.tmDescent) is returned. + + Returns: + 0: failure + >0: Windows LOGFONT cell height in units specified by map_mode and hdc. + */ + static int WindowsLogfontCellHeight( + int map_mode, + HDC hdc, + const LOGFONT& logfont + ); + + + /* + Description: + Get a Windows text metrics. + + Parameters: + map_mode - [in] + The best results are obtained when map_mode = MM_TEXT and the hdc is + correctly set for the context where the font is being rendered. Otherwise + the loss of precision when length units system conversion scale factors + are applied and results are stored in int LOGFONT and TEXTMETRIC fields + lead to discrepancies. + + If map_mode is 0, then ::GetMapMode(hdc) is called to get the mapping mode. + Otherwised, map_mode must identify a Windows mapping mode + (MM_TEXT, MM_LOMETRIC, MM_HIMETRIC, MM_LOENGLISH, MM_HIENGLISH, M_TWIPS). + If map_mode = MM_TEXT (1), then hdc is used as described in the hdc parameter. + + hdc - [in] + Windows device context. + If map_mode is set and not MM_TEXT, then hdc is ignored. + Otherwise the device context is used to get the mapping mode ( GetMapMode(hdc) ). + If the mapping mode is MM_TEXT, then the additional device context values + GetDeviceCaps(hdc, LOGPIXELSY) and conversion between device and logical pixel heights + DPtoLP(hdc,...) and LPtoDP(hdc,...) are used. + + logfont - [in] + If logfont.lfHeight >= 0, then logfont.lfHeight is returned. + If logfont.lfHeight < 0, then logfont face name, map_mode and hdc are + used to calculate the font's TEXTMETRIC and + (tm.tmAscent + tm.tmDescent) is returned. + + textmetric - [out] + + Returns: + 0: failure + >0: Windows LOGFONT cell height in units specified by map_mode and hdc. + */ + static bool GetWindowsTextMetrics( + int map_mode, + HDC hdc, + const LOGFONT& logfont, + TEXTMETRIC& textmetric + ); + +public: + /* + Example: + HDC font_hdc = ON_Font::CreateWindowsLogfontDeviceContext(); + if ( nullptr != font_hdc ) + { + ... + Calls to Windows SDK font managment functions needing an HDC + ... + ON_Font::DeleteWindowsLogfontDeviceContext(font_hdc); + } + + Returns: + Default HDC used for Windows GDI font management + */ + static HDC CreateWindowsLogfontDeviceContext(); + + /* + Parameters: + font_hdc - [in] + HDC from call to ON_Font::CreateWindowsLogfontDeviceContext(); + */ + static void DeleteWindowsLogfontDeviceContext( + HDC hdc + ); + +public: + /* + Description: + Set ON_Font properties from a subset of the LOGFONT properties. + Parameters: + map_mode - [in] + If logfont.lfHeight = 0, then map_mode is ignored. Otherwise ... + If map_mode is 0, then ::GetMapMode(hdc) is called to get the mapping mode. + Otherwise, map_mode must identify a Windows mapping mode + (MM_TEXT, MM_LOMETRIC, MM_HIMETRIC, MM_LOENGLISH, MM_HIENGLISH, M_TWIPS). + If map_mode = MM_TEXT (1), then hdc is used as described in the hdc parameter. + hdc - [in] + If logfont.lfHeight = 0 or map_mode is set and not MM_TEXT, then hdc is ignored. + Otherwise the device context is used to get the mapping mode ( GetMapMode(hdc) ). + If the mapping mode is MM_TEXT, then the additional device context values + GetDeviceCaps(hdc, LOGPIXELSY) and conversion between device and logical pixel heights + DPtoLP(hdc,...) and LPtoDP(hdc,...) are used. + logfont - [in] + These logfont properties are used to set the ON_Font. + lfHeight + lfWeight + lfItalic + lfUnderline + lfStrikeOut + lfCharSet + lfFaceName[LF_FACESIZE]; + All other LOGFONT properties are ignored. + */ + bool SetFromWindowsLogFont( + int map_mode, + HDC hdc, + const LOGFONT& logfont + ); + + + /* + Description: + Use the Windows GDI EnumFontFamiliesEx tool to get a list of LOGFONTS. + Parameters: + logfont_list - [out] + */ + static unsigned int GetInstalledWindowsLogFonts( + ON_SimpleArray& logfont_list + ); + + /* + Description: + Use the Windows GDI EnumFontFamiliesEx tool to get a list of LOGFONTS. + Parameters: + preferedLocale - [in] + If not empty, names from this locale will be prefered. + If preferedLocale = L"GetUserDefaultLocaleName", then + ::GetUserDefaultLocaleName will be used to set the preferedLocale. + bIncludeSimulatedFontFaces - [in] + True to include simulated font faces. + bKeepDWriteFont - [in] + If true, then bKeepDWriteFont.m_dwrite_font will be set and the caller + is responsible for calling m_dwrite_font->Release(). + logfont_list - [out] + */ + static unsigned int GetInstalledWindowsDWriteFonts( + const wchar_t* preferedLocale, + bool bIncludeSimulatedFontFaces, + bool bKeepDWriteFont, + ON_SimpleArray& dwrite_font_list + ); + + + /* + Parameters: + map_mode - [in] + If map_mode is 0, then ::GetMapMode(hdc) is called to get the mapping mode. + Otherwised, map_mode must identify a Windows mapping mode + (MM_TEXT, MM_LOMETRIC, MM_HIMETRIC, MM_LOENGLISH, MM_HIENGLISH, M_TWIPS). + If map_mode = MM_TEXT (1), then hdc is used as described in the hdc parameter. + hdc - [in] + Windows device context. + If map_mode is set and not MM_TEXT, then hdc is ignored. + Otherwise the device context is used to get the mapping mode ( GetMapMode(hdc) ). + If the mapping mode is MM_TEXT, then the additional device context values + GetDeviceCaps(hdc, LOGPIXELSY) and conversion between device and logical pixel heights + DPtoLP(hdc,...) and LPtoDP(hdc,...) are used. + Returns: + A Windows LOGFONT with propeties copied from this ON_Font. + If WindowsLogFontIsComplete() is true, then all LOGFONT properties + are copied from the ON_Font. + If WindowsLogFontIsComplete() is false, then the LOGFONT lfHeight, + lfWidth, lfEscapement, lfOrientation, lfClipPrecision, lfQuality, + lfPitchAndFamily, and lfOutPrecision properties are set to ON_Font + default values. + */ + const LOGFONT WindowsLogFont( + int map_mode, + HDC hdc + ) const; + + const MAT2 WindowsFontMat2() const; + +#endif + + +#if defined (ON_RUNTIME_APPLE_CORE_TEXT_AVAILABLE) + +public: + /* + Parameters: + size - [in] + If size is not > 0, then the size is set to units_per_em. + */ + static CTFontRef AppleCTFontSetSize( + CTFontRef original, + CGFloat size, + bool bReleaseOriginal + ); + + static unsigned int AppleCTFontUnitsPerEm(CTFontRef apple_font); + + bool SetFromAppleCTFont ( + CTFontRef apple_font, + bool bAnnotationFont + ); + + /* + Parameters + bIsSubstituteFont - [out] + true if the returned CTFontRef was a substitute automatically + created by Mac OS. + Returns: + An Apple CTFontRef managed by the Apple platform. + Do not delete this font. + */ + CTFontRef AppleCTFont( + bool& bIsSubstituteFont + ) const; + + /* + Parameters + bIsSubstituteFont - [out] + true if the returned CTFontRef was a substitute automatically + created by Mac OS. + Returns: + An Apple CTFontRef managed by the Apple platform. + Do not delete this font. + */ + CTFontRef AppleCTFont( + double point_size, + bool& bIsSubstituteFont + ) const; + + /* + Parameters + postscript_name - [in] + PostScript name of the desired font + point_size - [in] + bIsSubstituteFont - [out] + true if the returned CTFontRef was a substitute automatically + created by Mac OS (failed to match postscript name). + Returns: + An Apple CTFontRef managed by the Apple platform. + Do not delete this font. + */ + static CTFontRef AppleCTFont( + const wchar_t* postscript_name, + double point_size, + bool& bIsSubstituteFont + ); + + + static const ON_wString AppleCTFontPostScriptName( + CTFontRef apple_font + ); + + static const ON_wString AppleCTFontFamilyName( + CTFontRef apple_font + ); + + + /* + Description: + Apple CTFont, NSFont, and MacOS do not have "face names" as a font attribute. + This is the "typeface" name shown in the Apple FontBook Application + and the closest approximation to the Windows font face name. + The value from CTFontCopyName(...,kCTFontStyleNameKey) + */ + static const ON_wString AppleCTFontFaceName( + CTFontRef apple_font + ); + + /* + Description: + The Apple display name is used in some Apple apps + as a short description of the font. + When working in MacOS, the PostScript name is most reliable + way to uniquely identify a font. + */ + static const ON_wString AppleCTFontDisplayName( + CTFontRef apple_font + ); + + static ON_PANOSE1 AppleCTFontPANOSE1( + CTFontRef apple_font + ); + +#if defined (ON_RUNTIME_APPLE_OBJECTIVE_C_AVAILABLE) + // NSFont* appleNSFont = (__bridge NSFont*)(appleCTFont); + static NSFont* AppleTollFreeNSFont(CTFontRef appleCTFont); + + // CTFontRef appleCTFont = (__bridge CTFontRef)(appleNSFont); + static CTFontRef AppleTollFreeCTFont(NSFont* appleNSFont); +#endif + +#endif + +#if defined (OPENNURBS_FREETYPE_SUPPORT) +public: + /* + Description: + If opennurbs is built with FreeType support then + FT_Face freetype_face = (FT_Face)ON_Font::FreeTypeFace(font) + will return a FreeType face that can be used to render the font. + Parameters: + font - [in] + Returns: + A value that can be cast as a FreeType FT_Face. + Example + const ON_Font* font = ...; + FT_Face freetype_face = (FT_Face)ON_Font::FreeTypeFace(font); + Remarks: + Many fonts do not have a glyph for a every UNICODE codepoint and font + substitution is required. If you want to get the freetype face + used for a specfic UNICODE codepoint, call ON_Font::CodepointFreeTypeFace(). + */ + static ON__UINT_PTR FreeTypeFace( + const ON_Font* font + ); + +private: + /* + Description: + Helper function used by destructor to deallocate memory used + by FreeType face + */ + static void DestroyFreeTypeFace( + const ON_Font* font + ); + +public: + void DumpFreeType( + ON_TextLog& text_log + ) const; + +public: + static void DumpFreeTypeFace( + ON__UINT_PTR free_type_face_ptr, + ON_TextLog& text_log + ); +#endif + +public: + + /* + Parameters: + postscript_name - [in] + From CTFontCopyPostScriptName(...) / NSFont.fontName + Remarks: + The "Apple Font Name" is the PostScript font name in the + Mac OS "Font Book" application and in some other Apple documentation. + It is CTFontCopyPostScriptName(...) / NSFont.fontName. + */ + bool SetFromAppleFontName( + const wchar_t* postscript_name + ); + + /* + Parameters: + postscript_name - [in] + From CTFontCopyPostScriptName(...) / NSFont.fontName + point_size - [in] + Pass 0.0 for annotation fonts + Remarks: + The "Apple Font Name" is the PostScript font name in the + Mac OS "Font Book" application and in some other Apple documentation. + It is CTFontCopyPostScriptName(...) / NSFont.fontName. + */ + bool SetFromAppleFontName( + const wchar_t* postscript_name, + double point_size + ); + + ON_DEPRECATED_MSG("Use ON_Font::PostScriptName(ON_Font::NameLocale)") + const ON_wString& AppleFontName() const; + + ON_DEPRECATED_MSG("Use ON_Font::PostScriptName(ON_Font::NameLocale)") + const wchar_t* AppleFontNameAsPointer() const; + + /* + Returns: + A pointer for immediate use in formatted printing as in + FormattedPrint(L"PostScript name = \"&ls\"\n",font.PostScriptNameAsPointer()); + Remarks: + WARNING: + Do not save this pointer for later use. + It points to memory in a dynamic string. + */ + const wchar_t* PostScriptNameAsPointer() const; + + /* + Description: + Sets the ON_Font information from the platform font with the specified + postscript_name. + Parameters: + postscript_name - [in] + bAcceptPartialMatch - [in] + If bAcceptPartialMatch is true, there is not a font on the device with a + matching name, but there are fonts with names that have siginificant overlap, + then the font with the best overlap is returned. + For example if "Arial-Black" is not present and "Arial-BoldMT" is present, + then ON_Font.SetFromPostScriptName(L"Arial-Black",true) will return the + font with PostScript name "Arial-BoldMT". + Returns: + True if the font was set. + */ + bool SetFromPostScriptName( + const wchar_t* postscript_name + ); + + /* + Paramaters: + font_name - [in] + A UTF-16 or UTF-32 encoded null terminated string. + bStopAtHyphen - [in] + If true, the hash calculation terminates at the first hyphen. + This is useful when font_name is a PostScript name and you + don't want to include face weight or style information in the hash. + + For example, if bStopAtHyphen is true, then the four PostScript names + "Calibri", "Calibri-Bold", "Calibri-Italic", and "Calibri-BoldItalic" + have the same hash. + + There are some fonts where a hyphen is an integral part of the font face name. + Examples include "Arial-Black", "AvenirLT-Roman", "MecSoftFont-1", "MS-Gothic", + "MS-PGothic", "MS-UIGothic", "SLF-RHN-Architect", "SLF-RHN-Industrial", + "SLF-RHN-WhiteLiinen", and so on. + These hyphens are exempt from the bStopAtHyphen check. + Returns: + A hash of the font_name parameter that ignores spaces, hyphens, underbars, and case. + For example, the four names "Yu Gothic Regular", "YuGothic-Regular", + "YUGOTHICREGULAR", and "yugothicregular" have the same FontNameHash(). + The hash will be identical for UTF-16 and UTF-32 encodings. + */ + static const ON_SHA1_Hash FontNameHash( + const wchar_t* font_name, + bool bStopAtHyphen + ); + + /* + Description: + Compare the font names ignoring hyphens, underbars, and spaces. + Paramaters: + lhs - [in] + font name to compare + rhs - [in] + font name to compare + Returns: + If ON_Font::FontNameHash(lsh,false) and ON_Font::FontNameHash(rsh,false) are equal, + then 0 is returned. + Otherwise ON_wString::CompareOrdinal(lhs,rhs,true) is returned. + Remarks: + Useful for sorting font names. + */ + static int CompareFontName( + const ON_wString& lhs, + const ON_wString& rhs + ); + + /* + Description: + Compare the font names ignoring hyphens, underbars, and spaces. + Paramaters: + lhs - [in] + font name to compare + rhs - [in] + font name to compare + Returns: + If ON_Font::FontNameHash(lsh,false) and ON_Font::FontNameHash(rsh,false) are equal, + then 0 is returned. + Otherwise ON_wString::CompareOrdinal(lhs,rhs,true) is returned. + Remarks: + Useful for sorting font names. + */ + static int CompareFontNameWideChar( + const wchar_t* lhs, + const wchar_t* rhs + ); + + /* + Description: + Compare the font names ignoring hyphens, underbars, and spaces. + Paramaters: + lhs - [in] + font name to compare + rhs - [in] + font name to compare + Returns: + If ON_Font::FontNameHash(lsh,false) and ON_Font::FontNameHash(rsh,false) are equal, + then 0 is returned. + Otherwise ON_wString::CompareOrdinal(lhs,rhs,true) is returned. + Remarks: + Useful for sorting font names. + */ + static int CompareFontNamePointer( + const ON_wString* lhs, + const ON_wString* rhs + ); + + /* + Description: + Compare the font names ignoring hyphens, underbars, and spaces. + Ignore portions of PostScript names after the hyphen that separates the + font family and font face. + Paramaters: + lhs - [in] + font name to compare + rhs - [in] + font name to compare + Returns: + If ON_Font::FontNameHash(lsh,true) and ON_Font::FontNameHash(rsh,true) are equal, + then 0 is returned. + Otherwise ON_wString::CompareOrdinal(lhs,rhs,true) is returned. + Remarks: + Useful for sorting font names. + */ + static int CompareFontNameToHyphen( + const ON_wString& lhs, + const ON_wString& rhs + ); + + /* + Description: + Compare the font names ignoring hyphens, underbars, and spaces. + Ignore portions of PostScript names after the hyphen that separates the + font family and font face. + Paramaters: + lhs - [in] + font name to compare + rhs - [in] + font name to compare + Returns: + If ON_Font::FontNameHash(lsh,true) and ON_Font::FontNameHash(rsh,true) are equal, + then 0 is returned. + Otherwise ON_wString::CompareOrdinal(lhs,rhs,true) is returned. + Remarks: + Useful for sorting font names. + */ + static int CompareFontNameToHyphenPointer( + const ON_wString* lhs, + const ON_wString* rhs + ); + + /* + Description: + Compare the font names ignoring hyphens, underbars, and spaces. + Ignore portions of PostScript names after the hyphen that separates the + font family and font face. + Paramaters: + lhs - [in] + font name to compare + rhs - [in] + font name to compare + Returns: + If ON_Font::FontNameHash(lsh,true) and ON_Font::FontNameHash(rsh,true) are equal, + then 0 is returned. + Otherwise ON_wString::CompareOrdinal(lhs,rhs,true) is returned. + Remarks: + Useful for sorting font names. + */ + static int CompareFontNameToHyphenWideChar( + const wchar_t* lhs, + const wchar_t* rhs + ); + + /* + Paramaters: + dirty_font_name - [in] + A UTF-16 or UTF-32 encoded null terminated string. + map - [in] + Map to apply + Returns: + The input name with all spaces and hyphens removed. + */ + static const ON_String CleanFontName( + const wchar_t* dirty_font_name, + ON_StringMapOrdinalType map + ); + + /* + Parameters: + font - [in] + bDefaultIfEmpty - [in] + If true and font is nullptr or has emtpy names, then + the rich text font name for ON_Font::Default is returned, + Returns: + Font name to use in rich text file fonttbl sections. + {\\fonttbl...{\\fN ;}...} + */ + static const ON_wString RichTextFontName( + const ON_Font* font, + bool bDefaultIfEmpty + ); + + /* + Returns: + ON_Font::RichTextFontName(this,false); + Remarks: + For Windows installed fonts, this is identical to the Windows LOGFONT name. + For Apple platforms and rich text quartet names do not play nicely together. + */ + const ON_wString RichTextFontName() const; + + /* + Parameters: + family_name - [in] + The font family name. + + This a name like "Arial". + It is NOT a name like ArialMT, Arial-..., "Arial Black", "Arial Narrow", ... + Generally, family names do NOT contain word that specify + weight (Bold, Light, Heavy, ...), + width (Medium, Condensed, ...), + or slope (Oblique, Italic, Upright). + Generally, family names do NOT contain hyphens (like thos in PostScript names). + + Apple: = CTFontCopyFamilyName() / NSFont.familyName + Windows: = IDWriteFontFamily.GetFamilyNames() + NOTE WELL: GDI LOGFONT.lfFaceName is NOT a font family name. + + https://blogs.msdn.microsoft.com/text/2009/04/15/introducing-the-directwrite-font-system/ + */ + bool SetFamilyName( + const wchar_t* family_name + ); + + /* + Parameters: + dirty_name - [in] + A Windows GDI LOGFONT name or PostScript name. + Returns: + A family name + */ + static const ON_wString FamilyNameFromDirtyName( + const wchar_t* dirty_name + ); + + bool SetFromFontDescription( + const wchar_t* font_description + ); + + bool SetFromFontDescription( + const wchar_t* font_description, + const wchar_t* postscript_name + ); + + /* + Description: + Tests an object to see if its data members are correctly + initialized. + Parameters: + text_log - [in] if the object is not valid and text_log + is not nullptr, then a brief englis description of the + reason the object is not valid is appened to the log. + The information appended to text_log is suitable for + low-level debugging purposes by programmers and is + not intended to be useful as a high level user + interface tool. + Returns: + @untitled table + true object is valid + false object is invalid, uninitialized, etc. + */ + bool IsValid( ON_TextLog* text_log = nullptr ) const; + + void Dump( ON_TextLog& ) const; // for debugging + + +#if defined(ON_RUNTIME_APPLE_CORE_TEXT_AVAILABLE) + // Used to create installed fonts from Apple CTFont + ON_Font( + ON_Font::FontType font_type, + const class ON_AppleCTFontInformation& apple_font_information + ); +#endif + + +#if defined(ON_OS_WINDOWS_GDI) +public: + static void DumpLogfont( + const LOGFONT* logfont, + ON_TextLog& text_log + ); + static void DumpTextMetric( + const TEXTMETRIC* tm, + ON_TextLog& text_log + ); + + bool SetFromWindowsDWriteFont ( + struct IDWriteFont* dwrite_font, + const wchar_t* preferedLocale + ); + +private: + ON_Font( + ON_Font::FontType font_type, + const class ON_WindowsDWriteFontInformation& dwrite_font_information + ); + +public: + + struct IDWriteFont* WindowsDWriteFont() const; + + static const ON_wString PostScriptNameFromWindowsDWriteFont( + struct IDWriteFont* dwrite_font, + const wchar_t* preferedLocale + ); + + // DWRITE_INFORMATIONAL_STRING_WEIGHT_STRETCH_STYLE_FAMILY_NAME + static const ON_wString WeightStretchStyleModelFamilyNameFromWindowsDWriteFont( + struct IDWriteFont* dwrite_font, + const wchar_t* preferedLocale + ); + + static const ON_wString Field_0_CopyrightFromWindowsDWriteFont( + struct IDWriteFont* dwrite_font, + const wchar_t* preferedLocale + ); + + static const ON_wString Field_5_VersionFromWindowsDWriteFont( + struct IDWriteFont* dwrite_font, + const wchar_t* preferedLocale + ); + + static const ON_wString Field_7_TrademarkFromWindowsDWriteFont( + struct IDWriteFont* dwrite_font, + const wchar_t* preferedLocale + ); + + static const ON_wString Field_8_ManufacturerFromWindowsDWriteFont( + struct IDWriteFont* dwrite_font, + const wchar_t* preferedLocale + ); + + static const ON_wString Field_9_DesignerFromWindowsDWriteFont( + struct IDWriteFont* dwrite_font, + const wchar_t* preferedLocale + ); + + // Returns the desription saved in field 10. + // Opennurbs searches the description saved in field 10 of the name table + // for the strings "Engraving - single stroke" / "Engraving - double stroke" / "Engraving" + // to identify fonts that are desgned for engraving (and which tend to render poorly when + // used to dispaly text devices like screens, monitors, and printers). + // The SLF (single line fonts) are examples of fonts that have Engraving in field 10. + static const ON_wString Field_10_DescriptionFromWindowsDWriteFont( + struct IDWriteFont* dwrite_font, + const wchar_t* preferedLocale + ); + + static const ON_wString Field_11_VendorURLFromWindowsDWriteFont( + struct IDWriteFont* dwrite_font, + const wchar_t* preferedLocale + ); + + static const ON_wString Field_12_DesignerURLFromWindowsDWriteFont( + struct IDWriteFont* dwrite_font, + const wchar_t* preferedLocale + ); + + static const ON_wString Field_13_LicenseFromWindowsDWriteFont( + struct IDWriteFont* dwrite_font, + const wchar_t* preferedLocale + ); + + static const ON_wString Field_14_LicenseURLFromWindowsDWriteFont( + struct IDWriteFont* dwrite_font, + const wchar_t* preferedLocale + ); + + static const ON_wString Field_20_PostScriptCIDNameFromWindowsDWriteFont( + struct IDWriteFont* dwrite_font, + const wchar_t* preferedLocale + ); + + /* + Parameters: + dwrite_font - [in] + preferedLocale - [in] + prefered local for strings (family name, font name, face name, postscript name, ...) + A locale name often has the form "es-es", "en-us", ... + Pass nullptr or empty string list all locales and use "en-us" as the prefered locale name. + (Most modern fonts distributed with Windows 10 in all locales have en-us names). + Pass "*..." if you want to list all locale names and specify a prefered locale. + For example, "*es-es" will list all local names but use "es-es" as the preferedLocale. + text_log - [in] + destintion for the text description of the font. + */ + static void DumpWindowsDWriteFont( + struct IDWriteFont* dwrite_font, + const wchar_t* preferedLocale, + ON_TextLog& text_log + ); + +#endif + +#if defined (ON_RUNTIME_APPLE_CORE_TEXT_AVAILABLE) +public: + static void DumpCTFont( + CTFontRef apple_font, + ON_TextLog& text_log + ); +#endif + +public: + + // serialize definition to binary archive + bool Write( ON_BinaryArchive& ) const; + + // restore definition from binary archive + bool Read( ON_BinaryArchive& ); + + // V6 separated the V5 ON_Font into ON_TextStyle and ON_Font. + bool WriteV5( + int V5_font_index, + ON_UUID V5_font_id, + ON_BinaryArchive& + ) const; + + // V6 separated the V5 ON_Font into ON_TextStyle and ON_Font. + bool ReadV5( + ON_BinaryArchive&, + int* V5_font_index, + ON_UUID* V5_font_id + ); + + /* + Returns: + 0: This is not a managed font. + 1: This is the managed font ON_Font::Default. + >= 2: This is a managed font other than ON_Font::Default. + Remark: + For managed fonts other than ON_Font::Default, the value of RuntimeSerialNumber() + typically varies between instances of the same application. + Different platforms and application versions may use different font faces for ON_Font::Default. + If an ON_Font is a managed font, then RuntimeSerialNumber() and ManagedFontSerialNumber() + are identical. If an ON_Font is not a managed font, then RuntimeSerialNumber() is zero. + */ + unsigned int RuntimeSerialNumber() const; + + /* + Description: + Two ON_Font classes reference the same platform font and create identical glyphs + if and only if the have the same ManagedFontSerialNumber(). + Returns: + 0: This font is unset. + >= 1: Serial number of the managed font with the same characteristics. + Remark: + For managed fonts other than ON_Font::Default, the value of ManagedFontSerialNumber() + typically varies between instances of the same application. + Different platforms and application versions may use different font faces + for ON_Font::Default. + If an ON_Font is a managed font, then RuntimeSerialNumber() and ManagedFontSerialNumber() + are identical. If an ON_Font is not a managed font, then RuntimeSerialNumber() is zero. + */ + unsigned int ManagedFontSerialNumber() const; + + ////////////////////////////////////////////////////////////////////// + // + // Interface + + enum WindowsConstants : unsigned char + { + // Values used to set Windows LOGFONT fields. +#if defined(ON_OS_WINDOWS_GDI) + logfont_ansi_charset = ANSI_CHARSET, + logfont_default_charset = DEFAULT_CHARSET, // LOGFONT.lfCharSet + logfont_symbol_charset = SYMBOL_CHARSET, // LOGFONT.lfCharSet + logfont_out_precis = OUT_TT_ONLY_PRECIS, // LOGFONT.lfOutPrecision + + // 2017-07-27, Brian Gillespie + // Changed ON_Font::WindowsConstants::logfont_quality from ANTIALIASED_QUALITY to DEFAULT_QUALITY. + // This makes it so that ON_Font conversion to LOGFONT results in a good-looking font when rendered by MFC. + // With lfQuality set to ANTIALIASED_QUALITY, the font looks crummy - probably because all the rest of the fonts + // are being rendered today with CLEARTYPE_QUALITY. Letting Windows decide what to do is probably better. + logfont_quality = DEFAULT_QUALITY, // LOGFONT.lfQuality + + logfont_pitch_and_family = (DEFAULT_PITCH | FF_DONTCARE), // LOGFONT.lfPitchAndFamily +#else + // The values below are identical to the ones above and + // are used to insure code compiles for Apple and other + // platforms. + logfont_ansi_charset = 0, + logfont_default_charset = 1, + logfont_symbol_charset = 2, + logfont_out_precis = 7, + logfont_quality = 4, + logfont_pitch_and_family = 0 +#endif + }; + + + #if defined(ON_OS_WINDOWS_GDI) + static unsigned char WindowsLogfontCharSetFromLogfont( + const LOGFONT* logfont, + bool bValidateSymbolFont + ); + #endif + /* + Parameters: + face_name - [in] + GDI LOGFONT.lfFaceName value. + Note well: This is not the font "face name" or the font "family name". + It is typically a combination of the face name and "GDI sub-family" name + and typically does not include words that identify face weight or + face style. + Returns: + If the code is running on Windows: + The appropriate value of LOGFONT.lfCharSet for the input facename. + If the code is not running on Windows: + ON_Font::WindowsConstants::logfont_default_charset. + */ + static unsigned char WindowsLogfontCharSetFromFaceName( + const wchar_t* face_name + ); + + // miscellaneous constants use to initialize Windows LOGFONT fields + enum Constants: int + { + // 1995 - 2015: + // Windows fonts have variations in glyph size, design and kerning + // for different point sizes. Text in Rhino is generally + // placed around geometry and the relative spatial + // relationships between the text and the geometry must + // remain constant on all devices and at all "zoom" levels. + // We have to choose a point size and then apply appropriate + // scaling during display, printing, and in other rendering + // calculations. After many experiments and 20 years of commercial use, + // (1995-2015) we have found 256 works best. + // This value is used on all platforms because the calculations + // it is used in occur on all platforms. These calculations must return + // consistent results so models exchanged between platforms maintain + // spatial relationships between text and geometry. + // + // 2017: + // (switching to freetype) + // The value ON_Font::Constants::AnnotationFontCellHeight is used to define + // "opennurbs normalized font coordinates". The scale + // ((double)ON_Font::Constants::AnnotationFontCellHeight)/(font definition grid height) + // is used to convert bounding information and outlines from a native + // font definition to opennurbs normalized font coordinates. + // Many TrueType fonts have font definition grid height = 2048. + // Many PostScript fonts have font definition grid height = 1000. + AnnotationFontCellHeight = 256, // Windows LOGFONT.lfHeight value (NOT A POINT SIZE) + + // This value is used on Apple platforms to get fonts used for rendering annotation. + // The size should be a power of 2. Ideally we want access to the font and glyph + // design size returned by CTFontGetUnitsPerEm(). + AnnotationFontApplePointSize = 256, + + // ON_Font::Constants::metric_char is the unicode code point value + // for the glpyh used to calculate critical glyph metrics. + // It must be an 'I' or 'H', but we have not tested 'H'. + // There are problems with any other upper case latin letter in common fonts. + // In particular, the standard 'M' does not work. + // We have used 'I' for 22 years (1995 - 2017). + // This value is used on all platforms because the calculations + // it is used in occur on all platforms. These calculations must return + // consistent results so models exchanged between platforms maintain + // spatial relationships between text and geometry. + MetricsGlyphCodePoint = 'I' + }; + + ON_DEPRECATED_MSG("Use ON_Font::Description() or ON_Font::PostScriptName()") + const ON_wString& FontDescription() const; + + ON_DEPRECATED_MSG("V6 ON_Font does not have a description property.") + bool SetFontDescriptionForExperts( + const wchar_t* ignored_parameter + ); + + ON_DEPRECATED_MSG("Use ON_Font::PostScriptName()") + const wchar_t* FontDescriptionAsPointer() const; + + ON_DEPRECATED_MSG("Use ON_FontMetrics::DefaultLineFeedRatio") + double LinefeedRatio() const; + + /* + Returns: + Normalized font metrics. + + Remarks: + Font metric "normalized" units are comparable between different fonts. + Normalized font metrics exist so that code that positions glyphs from + multiple fonts does not have to take the unit system and resolution used + in the design of each font. + In opennurbs, much of this code that positions glyphs is located in ON_Annotation, + ON_TextContent, and ON_TextRun member functions and is used when rendering + annotation objects. + + Fonts can be designed and defined at different resolutions and + relative scaling is necessary when text contains glyphs from + fonts desinged at different grid resolutions. For example, + TrueType font grid with and height is often 1024x1024 or + 2048x2014, OpenType grids are often 1000x1000, and PostScript + grids are often 1000x1000. Opennurbs "font units" are the units + the font was designed in. + + Long ago, opennurbs and Rhino used only Windows TrueType fonts + and ran only in Microsoft Windows. During this era, + the "normalized units" were for a Windows LOGFONT created + with lfHeight = ON_Font::Constants::AnnotationFontCellHeight. + + Currently opennurbs and Rhino work on Microsoft Windows and Apple + platforms and use FreeType to access font information. When a font + is not "tricky", the "font design" units are the the units FreeType + uses when a font is loaded with FT_LOAD_NO_SCALE. + + When working with fonts and glyhphs in opennurbs and Rhino, + SDK users almost always want to use normalized font and glyph metrics. + */ + const ON_FontMetrics& FontMetrics() const; + + /* + Description: + This function is for expert users doing something complicated. + Returns: + Font metrics read directly from the font definition with no or minimal + scaling. + Remarks: + See ON_Font.FontMetrics() documentation for important information + about the differnce bewteen normalized and font unit metrics. + */ + const ON_FontMetrics& FontUnitFontMetrics() const; + + /* + Returns: + scale to apply when converting from a FT_LOAD_NO_SCALE FreeType + glyph metric or outline to normalized opennurbs font coordinates. + */ + double FontUnitToNormalizedScale() const; + + /* + Returns: + scale to apply when converting from a FT_LOAD_NO_SCALE FreeType + glyph metric or outline to normalized opennurbs font coordinates. + */ + double NormalizedToFontUnitScale() const; + + /* + Returns: + Font character height in points (1 point = 1/72 inch). + + See the remarks for a defintion of "character height". + + Remarks: + A "point" is a length unit system. + 1 point = 1/72 inch = 25.4/72 millimeters. + + Typically, fonts are designed for maximum clarity when the rendered + character height is close to PointSize(). + + font cell height = font ascent + font descent. + + font character height = font cell height - font internal leading. + + For fonts designed for languages that use latin letters, it is common for + the character height to be equal to or a little larger than the distance + from the bottom of a lower case g to the top of an upper case M. + The character height is also called the "em hieght". + + Font internal leading is the space above typical capital latin letters + that is reseved for diacritical marks like the ring above the A in + the UNICODE "LATIN LETTER A WITH RING" U+00C5 glyph (Angstrom symbol). + */ + double PointSize() const; + + /* + Parameters: + point_size - [in] + font character height in point units. + + Remarks: + See the remarks section ON_Font::PointSize() for more information + about point units and character height. + */ + bool SetPointSize( + double point_size + ); + + static bool IsValidPointSize( + double point_size + ); + + /* + Description: + This is a legacy function that traces it's heritage to Windows specific + GDI LOGFONT code from 1995. Best to avoid it whenever possible. + Ideally, use an Windows IDWriteFont or Apple CTFont to create an ON_Font that + references an installed font. Less ideally, use a complete LOGFONT structure. + Parameters: + windows_logfont_name - [in] + GDI LOGFONT.lfFaceName value. + Note well: + This is not the font "face name", not the font "family name", + and not the font PostScript name. + It is often a combination of the family name, an additional "GDI sub-family" name. + Occasionally it includes some face weight and style attributes. + Returns: + True if the value was set. + */ + ON_DEPRECATED_MSG("Use ON_Font::SetFromDWriteFont(), ON_Font::SetFromAppleFont(), or ON_Font::SetFromWindowsLogFont()") + bool SetFontFaceName( + const wchar_t* windows_logfont_name + ); + + /* + Description: + This is a legacy function that traces it's heritage to Windows specific + GDI LOGFONT code from 1995. Best to avoid it whenever possible. + Ideally, use an Windows IDWriteFont or Apple CTFont to create an ON_Font that + references an installed font. Less ideally, use a complete LOGFONT structure. + Parameters: + windows_logfont_name - [in] + GDI LOGFONT.lfFaceName value. + Note well: + This is not the font "face name", not the font "family name", + and not the font PostScript name. + It is often a combination of the family name, an additional "GDI sub-family" name. + Occasionally it includes some face weight and style attributes. + Returns: + True if the value was set. + */ + bool SetWindowsLogfontName( + const wchar_t* windows_logfont_name + ); + + ON_DEPRECATED_MSG("Use ON_Font::WindowsLogfontName(ON_Font::NameLocale)") + const wchar_t* FontFaceName() const; + + /* + Returns: + A pointer for immediate use in formatted printing as in + FormattedPrint(L"Windows LOGFONT.lfFaceName[] = \"&ls\"\n",font.WindowsLogfontNameAsPointer()); + Remarks: + WARNING: + Do not save this pointer for later use. + It points to memory in a dynamic string. + */ + const wchar_t* WindowsLogfontNameAsPointer() const; + + ON_Font::Weight FontWeight() const; + + int WindowsLogfontWeight() const; + int AppleWeightOfFont() const; + double AppleFontWeightTrait() const; + + /* + Returns: + If the font is created from a CTFont, the weight trait, + otherwise ON_UNSET_VALUE; + */ + double AppleFontWeightTraitEx() const; + + /* + Description: + Don't use this old function. If you have a font and want a face in + the same famliy with a different weight, then call + InstalledFamilyMemberWithWeightStretchStyle(desired_weight,unset,unset). + + NOTE WELL: + Changing the weight requires updating the Family, Face, PostScript + and Windows LOGFONT names as well. + */ + bool SetFontWeight( + ON_Font::Weight font_weight + ); + + /* + Description: + Don't use this old function. Higher quality font information is created + by SetFromAppleFont() and SetFromWindowsDWriteFont(). + NOTE WELL: + Changing the weight requires updating the Family, Face, PostScript + and Windows LOGFONT names as well. + */ + bool SetWindowsLogfontWeight( + int windows_logfont_weight + ); + + /* + Description: + Don't use this old function. Higher quality font information is created + by SetFromAppleFont() and SetFromWindowsDWriteFont(). + NOTE WELL: + Changing the weight requires updating the Family, Face, PostScript + and Windows LOGFONT names as well. + */ + bool SetAppleWeightOfFont( + int apple_weight_of_font + ); + + /* + Description: + Don't use this old function. Higher quality font information is created + by SetFromAppleFont() and SetFromWindowsDWriteFont(). + NOTE WELL: + Changing the weight requires updating the Family, Face, PostScript + and Windows LOGFONT names as well. + */ + bool SetAppleFontWeightTrait( + double apple_font_weight_trait + ); + + /* + Paramaters: + bCheckFamilyName - [in] + bCheckPostScriptName - [in] + Returns: + True if any of LOGFONT face name is empty. + True if any of weight, stretch, or style is unset. + True if bCheckFamilyName is true and FamilyName() is empty. + True if bCheckPostScriptName is true and PostScriptName() is empty. + False otherwise. + */ + bool HasUnsetProperties( + bool bCheckFamilyName, + bool bCheckPostScriptName + ) const; + + /* + Description: + If a propery is unset in this and set in source, then it is set + to the source value. + Parameters: + source - [in] + bUpdateDescription - [in] + When in doubt, pass true. + If bUpdateDescription is true and at least one property + is changed, then the description is also updated. + Returns: + Number of changed properties. + */ + unsigned int SetUnsetProperties( + const ON_Font& source, + bool bUpdateDescription + ); + +private: + bool Internal_SetFontWeightTrio( + ON_Font::Weight font_weight, + int windows_logfont_weight, + double apple_font_weight_trait, + bool bUpdateFontDescription + ); + + // Unsets origin and resets cache + void Internal_AfterModification(); + +public: + + /* + Description: + User interfaces that want to provide a name + regular/bold/italic/bold-italic + font finder must use IsBoldInQuartet() and IsItalicInQuartet(). + + This function looks at weight the font designer assigned to the font. + This is an unreliable way to determine if a font is "light/regular/bold" + compared to other faces in its font family. + + Returns: + True if FontWeight() is lighter than ON_Font::Weight::Normal + */ + bool IsLight() const; + + /* + Description: + User interfaces that want to provide a name + regular/bold/italic/bold-italic + font finder must use IsBoldInQuartet() and IsItalicInQuartet(). + + This function looks at weight the font designer assigned to the font. + This is an unreliable way to determine if a font is "light/regular/bold" + compared to other faces in its font family. + + Returns: + True if FontWeight() is ON_Font::Normal or ON_Font::Weight::Medium + */ + bool IsNormalWeight() const; + + /* + Description: + User interfaces that want to provide a name + regular/bold/italic/bold-italic + font finder must use IsBoldInQuartet() and IsItalicInQuartet(). + + This function looks at weight the font designer assigned to the font. + This is an unreliable way to determine if a font is "light/regular/bold" + compared to other faces in its font family. + + Returns: + True if heavier than ON_Font::Weight::Medium. + + Remarks: + Just in case you didn't read the description, ON_Font.IsBold() is a terrible + way to decide if a font is "bold" in a quartet (regular,bold,italic,bold-italic). + Use ON_Font.QuartetFaceMember() + */ + bool IsBold() const; + + /* + Returns: + True if this font is considered a bold member in its installed font ON_FontFaceQuartet. + Remarks: + In a traditional regular/bold/italic/bold-italic font face interfaces, + "bold" is relative to the quartet members and cannot be determined + by inspecting the numerical value of the font's weight. For example, + Arial Black has a weight of 900=ON_FontWeight::Weight::Heavy, + but the Arial Black quartet has only two faces, regular and italic. + In quartets for fonts with a simulated bold, like AvenirLT-Roman, + the bold member often has a LOGFONT weight of 551 < SemiBold = 600. + The Windows AvenirLT-Roman quartet has four faces and the bold faces in + the quartet have weights 551. + */ + bool IsBoldInQuartet() const; + + /* + Returns: + True if this font is considered an italic member in its installed font ON_FontFaceQuartet. + Remarks: + When working with rich text you want to use IsItalicInQuartet(). + For fonts with a slanted regular face like Corsiva, + ON_Font.FontStyle() = ON_Font::Style::Italic, ON_Font.IsItalic() = true, + and ON_Font.IsItalicInQuartet() = false. + */ + bool IsItalicInQuartet() const; + + /* + Remarks: + When working with rich text you want to use IsItalicInQuartet(). + For fonts with a slanted regular face like Corsiva, + ON_Font.FontStyle() = ON_Font::Style::Italic, ON_Font.IsItalic() = true, + and ON_Font.IsItalicInQuartet() = false. + */ + ON_Font::Style FontStyle() const; + + /* + Description: + Don't use this old function. If you have a font and want a face in + the same famliy with a different style, then call + InstalledFamilyMemberWithWeightStretchStyle(nullptr,unset,desired_style). + + NOTE WELL: + Changing the style requires updating the Family, Face, PostScript + and Windows LOGFONT names as well. + */ + bool SetFontStyle( + ON_Font::Style font_style + ); + + /* + Description: + If is better to use IsItalicInQuartet(). + + Returns: + true if FontStyle() is ON_Font::Style::Italic. + false if FontStyle() is ON_Font::Style::Upright or .ON_Font::Style::Oblique. + Remarks: + When working with rich text you want to use IsItalicInQuartet(). + For fonts with a slanted regular face like Corsiva, + ON_Font.FontStyle() = ON_Font::Style::Italic, ON_Font.IsItalic() = true, + and ON_Font.IsItalicInQuartet() = false. + */ + bool IsItalic() const; + + /* + Returns: + true if FontStyle() is ON_Font::Style::Upright. + false if FontStyle() is ON_Font::Style::Italic or .ON_Font::Style::Oblique. + Remarks: + When working with rich text you want to use IsItalicInQuartet(). + For fonts with a slanted regular face like Corsiva, + ON_Font.FontStyle() = ON_Font::Style::Italic, ON_Font.IsItalic() = true, + and ON_Font.IsItalicInQuartet() = false. + */ + bool IsUpright() const; + + /* + Returns: + true if FontStyle() is ON_Font::Style::Italic or is ON_Font::Style::Oblique. + Otherwise false. + Remarks: + When working with rich text you want to use IsItalicInQuartet(). + For fonts with a slanted regular face like Corsiva, + ON_Font.FontStyle() = ON_Font::Style::Italic, ON_Font.IsItalic() = true, + and ON_Font.IsItalicInQuartet() = false. + */ + bool IsItalicOrOblique() const; + + /* + Returns: + true if FontStyle() is ON_Font::Style::Oblique. + false if FontStyle() is ON_Font::Style::Upright or .ON_Font::Style::Italic. + Remarks: + When working with rich text you want to use IsItalicInQuartet(). + For fonts with a slanted regular face like Corsiva, + ON_Font.FontStyle() = ON_Font::Style::Italic, ON_Font.IsItalic() = true, + and ON_Font.IsItalicInQuartet() = false. + */ + bool IsOblique(); // ERROR - missing const + + + ON_Font::Stretch FontStretch() const; + + double AppleFontWidthTrait() const; + + /* + Description: + Don't use this old function. If you have a font and want a face in + the same famliy with a different stretch, then call + InstalledFamilyMemberWithWeightStretchStyle(nullptr,desired_stretch,unset). + + NOTE WELL: + Changing the stretch requires updating the Family, Face, PostScript + and Windows LOGFONT names as well. + */ + bool SetFontStretch( + ON_Font::Stretch font_stretch + ); + + bool IsUnderlined() const; + bool SetUnderlined( + bool bUnderlined + ); + + bool IsStrikethrough() const; + bool SetStrikethrough( + bool bStrikethrough + ); + + /* + Returns: + True if the font is a symbol font. Typically this means + that there is no meaningful correspondence between + public use UNICODE codepoints and glyphs. + Remarks: + The Linguist's Software fonts (circa 1997) with the family names + CityBlueprint + CountryBlueprint + Romantic + Technic + are classified as symbol fonts but have reasonable glyphs + for most ASCII codepoints. + */ + bool IsSymbolFont() const; + + const ON_PANOSE1 PANOSE1() const; + + void SetPANOSE1( + ON_PANOSE1 panose1 + ); + + /* + Returns: + If the outline figure type is known for certain, it is returned. + Otherwise, ON_OutlineFigure::Type::Unknown is returned. + */ + ON_OutlineFigure::Type OutlineFigureType() const; + + /* + Returns: + True if this is a known single stroke font. + False otherwise. + See Also: + IsEngravingFont() + */ + bool IsSingleStrokeFont() const; + + /* + Returns: + True if this is a known double stroke font. + False otherwise. + See Also: + IsEngravingFont() + */ + bool IsDoubleStrokeFont() const; + + /* + Returns: + True if this is a known single stroke or double stroke font. + False otherwise. + See Also: + IsEngravingFont() + */ + bool IsSingleStrokeOrDoubleStrokeFont() const; + + /* + Description: + The outlines for an engraving font have single-stroke, double-stroke, + or perimeters desinged for path engraving. + These fonts behave poorly when used for filled font rendering + or creating solid extrusions. + The OrachTech 2 line fonts are examples of engraving fonts that + are not single or double stroke. + Returns: + True if the font is a known engraving font. + */ + bool IsEngravingFont() const; + + static const ON_Font* DefaultEngravingFont(); + + unsigned char LogfontCharSet() const; + + bool SetLogfontCharSet( + unsigned char logfont_charset + ); + + ON_DEPRECATED_MSG("Use FontMetrics().AscentOfCapital()") + int HeightOfI() const; + + ON_DEPRECATED_MSG("Use FontMetrics().LineSpace()") + int HeightOfLinefeed() const; + + ON_DEPRECATED_MSG("Use FontMetrics().GlyphScale()") + double HeightScale(double text_height) const; + + ON_DEPRECATED_MSG("Use FontMetrics().StrikeoutThickness()") + int GetStrikeoutSize() const; + + ON_DEPRECATED_MSG("Use FontMetrics().StrikeoutPosition()") + int GetStrikeoutPosition() const; + + ON_DEPRECATED_MSG("Use FontMetrics().UnderscoreThickness()") + int GetUnderscoreSize() const; + + + ON_DEPRECATED_MSG("Use FontMetrics().UnderscorePosition()") + int GetUnderscorePosition() const; + + /* + Returns: + A SHA-1 hash of all font characteristics, including platform specific settings. + Two fonts have identical font characteristics, if and only if they have identical + FontCharacteristicsHash() values. + + Example: + ON_Font f1 = ... + ON_Font f2 = ... + if ( f1.FontCharacteristicsHash() == f2.FontCharacteristicsHash() ) + { + // f1 and f2 have identical font characteristics + } + else + { + // f1 and f2 have different font characteristics + } + */ + const class ON_SHA1_Hash& FontCharacteristicsHash() const; + +private: + +public: + + /* + Description: + Compares the font face name, weight, style, stretch, underline, strikethrough, + point size, and platform specific characteristics. + Returns: + -1: lhs characteristics < rhs characteristics + 0: lhs characteristics = rhs characteristics + +1: lhs characteristics > rhs characteristics + Remarks: + Use FontCharacteristicsHash() when every characteristic needs to be compared. + */ + static int CompareFontCharacteristics( + const ON_Font& lhs, + const ON_Font& rhs + ); + + + /* + Description: + Compares the font weight, style, stretch, underline, strikethrough, linefeed_ratio + and facename characteristics. + Returns: + 0 == ON_Font::CompareFontCharacteristics(lhs,rhs). + Remarks: + Use FontCharacteristicsHash() when every characteristic needs to be compared. + */ + static bool EqualFontCharacteristics( + const ON_Font& lhs, + const ON_Font& rhs + ); + + /* + Description: + Expert user tool to compares the font face name, weight, style, stretch, + underline, and strikethrough characteristics. Additional parameters + determine how unset and platform specific characteristics are compared. + + Parameters: + bComparePlatformSpecificCharacteristics - [in] + If bComparePlatformSpecificCharacteristics is true, characteristics + for the current platform are compared. Otherwise all platform specific + characteristics are ignored. + Platform specific characteristics include m_logfont_charset on Windows, + and m_apple_font_name and m_apple_font_weight_trait on Mac OS. + + bIgnoreUnsetCharacteristics - [in] + If bIgnoreUnsetCharacteristics is true, unset characteristics are + considered equal to any other value. + + WARNING: + When bIgnoredUnsetCharacteristic is true, this compare function is not a + well ordering of ON_Font classes and cannot be used in sorting algorithms. + For example, if A, B, C are fonts with weights + A.FontWeight() = ON_Font::Weight::Normal, + B.FontWeight() = ON_Font::Weight::Bold, + C.FontWeight() = ON_Font::Weight::Unset, + and all other settings identical, then A < B and A=C and B=C. + + Returns: + -1: lhs characteristics < rhs characteristics + 0: lhs characteristics = rhs characteristics + +1: lhs characteristics > rhs characteristics + */ + static int CompareFontCharacteristicsForExperts( + bool bComparePlatformSpecificCharacteristics, + bool bIgnoreUnsetCharacteristics, + const ON_Font& lhs, + const ON_Font& rhs + ); + + /* + Description: + In the rare cases when an ON_Font::Weight value must be passed + as an unsigned int, use ON_Font::FontWeightFromUnsigned() to + convert the unsigned value to an ON_Font::Weight value. + Parameters: + unsigned_font_weight - [in] + */ + static ON_Font::Origin FontOriginFromUnsigned( + unsigned int unsigned_font_origin + ); + + /* + Returns: + Source of the information used to set the font characteristics. + Unset = 0, + */ + ON_Font::Origin FontOrigin() const; + + void SetFontOrigin( + ON_Font::Origin font_origin + ); + + /* + Returns: + True if the font face is simulated in some way + */ + bool IsSimulated() const; + + /* + Returns: + often bold from normal + */ + bool SimulatedWeight() const; + + /* + Returns: + often bold from normal + */ + bool SimulatedStretch() const; + + /* + Returns: + true if the style was simulated (typically italic from upright) + */ + bool SimulatedStyle() const; + + void SetSimulated( + bool bSimulatedWeight, + bool bSimulatedStretch, + bool bSimulatedStyle, + bool bSimulatedOther + ); + +private: + friend class ON_ManagedFonts; + + ////////////////////////////////////////////////////////////////////////////////// + // + // The "font glpyh definition" parameters completely determine the appearance + // of font glyphs. + // + // If all "font glpyh definition" parameters have identical values, + // text rendered using those fonts will look identical. + // + // If two fonts have a "font glpyh definition" parameter with different values, + // text rendered using those fonts will not look identical. + // + // BEGIN "font glpyh definition" parameters: + // + + // The font ON_Font::Default has m_runtime_serial_number = 1. + // Managed fonts have m_runtime_serial_number >= 1. + // Unmanaged fonts have m_runtime_serial_number = 0; + static unsigned int __runtime_serial_number_generator; + const unsigned int m_runtime_serial_number = 0; + + int m_windows_logfont_weight = 400; // 100 <= m_windows_logfont_weight <= 1000 + double m_point_size = 0.0; // 0.0 indicates the annotation font size will be used. + double m_apple_font_weight_trait = 0.0; // = Apple WeightTrait value -1.0 <= m_apple_font_weight < 1.0, 0.0 = "normal" + ON_Font::Weight m_font_weight = ON_Font::Weight::Normal; + + ON_Font::Style m_font_style = ON_Font::Style::Upright; // m_font_style corresponds to Windows LOGFONT.lfItalic field + ON_Font::Stretch m_font_stretch = ON_Font::Stretch::Medium; + bool m_font_bUnderlined = false; // Same as Windows LOGFONT.lfUnderlined + bool m_font_bStrikethrough = false; // Same as Windows LOGFONT.lfStrikeOut + + // There are two permitted values for m_logfont_charset. + // ON_Font::WindowsConstants::logfont_default_charset = 1 + // ON_Font::WindowsConstants::logfont_symbol_charset = 2 + unsigned char m_logfont_charset = ON_Font::WindowsConstants::logfont_default_charset; + +private: + ON_Font::Origin m_font_origin = ON_Font::Origin::Unset; + +private: + const ON_Font::FontType m_font_type = ON_Font::FontType::Unset; + +private: + // Locale for localized m_locale_* font names. + ON_wString m_locale_name; + + // Localized and English font PostScript name + // Apple: = CTFontCopyPostScriptName() / NSFont.fontName + // Windows: = IDWriteFont.GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME,...) + // NOTE WELL: + // This is NOT the GDI LOGFONT.lfFaceName. + ON_wString m_loc_postscript_name; + ON_wString m_en_postscript_name; + + // Localized and English font family name + // Apple: = CTFontCopyFamilyName() / NSFont.familyName + // Windows: = IDWriteFontFamily.GetFamilyNames() + // NOTE WELL: + // This is NOT the GDI LOGFONT.lfFaceName. + ON_wString m_loc_family_name; + ON_wString m_en_family_name; + + // Localized and English font face name + // Apple: = CTFontCopyName( ..., kCTFontStyleNameKey) + // Windows: = IDWriteFont.GetFaceNames() + // NOTE WELL: + // This is NOT the GDI LOGFONT.lfFaceName. + ON_wString m_loc_face_name; + ON_wString m_en_face_name; + + // Localized and English Windows GDI LOGFONT.lfFaceName + // Apple: = not available + // Windows: = IDWriteFont.GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES,...) + ON_wString m_loc_windows_logfont_name; + ON_wString m_en_windows_logfont_name; + + void Internal_ClearAllNames(); + + void Internal_ClearName( + bool bClearFamilyName, + bool bClearFaceName, + bool bClearPostScriptName, + bool bClearWindowsLogfontName + ); + +private: + ON__UINT8 m_simulated = 0; // bit field (&1 = some simulation, &2 simulated weight, &4 simulated stretch, &8 simulated italic) + +private: + // = 1 if this is a managed font and the face is installed on the current device. + ON__UINT8 m_reserved1 = 0; + +private: + ON_PANOSE1 m_panose1; + +private: + // A sha1 hash of all font characteristics. + // This value is set using lazy evaluation. + // A zero digest indicates it is not set. + mutable ON_SHA1_Hash m_font_characteristics_hash; + +private: + double m_apple_font_width_trait = ON_UNSET_VALUE; + +private: + ON_OutlineFigure::Type m_outline_figure_type = ON_OutlineFigure::Type::Unset; + +private: + // When then is unset, it is the best way to determine what face this font + // corresponds to in its quartet of faces. (regular,bold,italic,bold-italic) + // The Windows OS LOGFONT partitions specify this. On Apple we have a table + // for common fonts and we make it up on the fly for the rest. + // This field is not included in the font hash because it is mutable + // and may get changed as the application adds more managed fonts. + mutable ON_FontFaceQuartet::Member m_quartet_member = ON_FontFaceQuartet::Member::Unset; + +private: + ON__UINT16 m_reserved2 = 0; + ON__UINT32 m_reserved3 = 0; + double m_reserved4 = 0.0; + +private: + bool ModificationPermitted( + const char* function_name, + const char* file_name, + int line_number + ) const; + +private: + ////////////////////////////////////////////////////////////////////////////////// + // + // BEGIN global font glyph cache interface + // + // There is a single font glyph cache for each managed font. + // Fonts that are not managed use a glyph cache from a managed font. + // This make functions like ON_Font.FindGlyph() efficient and reliable. + // + void DestroyFontGlyphCache(); + class ON_FontGlyphCache* FontGlyphCache( + bool bCreateIfMissing + ) const; +#pragma ON_PRAGMA_WARNING_PUSH +#pragma ON_PRAGMA_WARNING_DISABLE_MSC( 4251 ) + // C4251: '...std::shared_ptr...' + // needs to have dll-interface to be used by clients of class 'ON_Font' + // m_font_glyph_cache is private and all code that manages m_font_glyph_cache is explicitly implemented in the DLL. +private: + mutable std::shared_ptr m_font_glyph_cache; +#pragma ON_PRAGMA_WARNING_POP + // + // END global font cache interface + // + ////////////////////////////////////////////////////////////////////////////////// + +private: + // LEGACY field. Windows opennurbs never uses freetype. + // In rare cases, Apple opennurbs used freetype. + mutable class ON_FreeTypeFace* m_free_type_face = nullptr; + +private: + // If this font is a managed font, then m_managed_installed_font_and_bits encodes + // 1. The installed font used to render this font + // 2. If the installed font is a substituted for font not installed on this device. + // If this font is not a managed font, then m_managed_installed_font_and_bits = 0. + // LEGACY mutable ON__UINT8 m_managed_face_is_installed = 0; 1 = managed and installed 2 = managed and substituted + mutable ON__UINT_PTR m_managed_installed_font_and_bits = 0; + static void Internal_SetManagedFontInstalledFont( + const ON_Font* managed_font, + const ON_Font* installed_font, + bool bInstalledFontIsASubstitute + ); + + /// + /// + /// + /// + /// True if this is a managed font that is installed on this device. False otherwise. + /// + bool Internal_ManagedFontIsInstalled() const; + + /// + /// + /// + /// + /// True if this is a managed font that is not installed on this device. False otherwise. + /// + bool Internal_ManagedFontIsNotInstalled() const; + +public: + /* + Parameters: + font_glyph - [in] + glyph_metrics_in_font_design_units - [out] + glyph metrics in font design units + Returns: + >0: Glyph index + 0: failed + */ + typedef unsigned int (*ON_GetGlyphMetricsFuncType)( + const class ON_FontGlyph* font_glyph, + class ON_TextBox& glyph_metrics_in_font_design_units + ); + + /* + Parameters: + font - [in] + font_metrics_in_font_design_units - [out] + font metrics in font design units + */ + typedef void (*ON_GetFontMetricsFuncType)( + const class ON_Font* font, + class ON_FontMetrics& font_metrics_in_font_design_units + ); + + typedef bool (*ON_GetGlyphOutlineFuncType)( + const class ON_FontGlyph* glyph, + bool bSingleStrokeFont, + class ON_Outline& outline + ); + + static void SetCustomMeasurementFunctions( + ON_GetGlyphMetricsFuncType measureGlyphFunc, + ON_GetFontMetricsFuncType metricsFunction + ); + +private: + static ON_GetGlyphMetricsFuncType Internal_CustomGetGlyphMetricsFunc; + static ON_GetFontMetricsFuncType Internal_CustomGetFontMetricsFunc; + static ON_GetGlyphOutlineFuncType Internal_CustomGetGlyphOutlineFunc; + +public: + static void GetRunBounds( + const ON_Font& font, + const wchar_t* text, + double fontSizePixels, + ON::TextHorizontalAlignment horizontalAlignment, + ON::TextVerticalAlignment verticalAlignment, + ON_2dPoint& boundsMin, + ON_2dPoint& boundsMax, + int& lineCount + ); +}; + +typedef int (*ON_FontPtrCompareFunc)(ON_Font const* const* lhs, ON_Font const* const* rhs); + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +#endif + +class ON_CLASS ON_FontList +{ +public: + ON_FontList(); + + /* + Parameters: + bMatchUnderlineStrikethroughAndPointSize - [in] + False to ignore underline, strikethrough, and point size properties (installed font list) + True to match underline, strikethrough and point size properties (managed font list) + */ + ON_FontList( + bool bMatchUnderlineStrikethroughAndPointSize + ); + + ~ON_FontList(); + +private: + ON_FontList(const ON_FontList&) = delete; + ON_FontList& operator=(const ON_FontList&) = delete; + +public: + /* + Returns: + Number of fonts in the list. + */ + unsigned int Count() const; + + ON_Font::NameLocale NameLocale() const; + + /* + Parameters: + font_characteristics_hash - [in] + bReturnFirst - [in] + If there are multiple fonts with the same hash and bReturnFirst is true, + then the first font with tht hash is returned. + If there are multiple fonts with the same hash and bReturnFirst is false, + then nullptr is returned. + new style or unset if font style is adequate + Returns: + A font with the specified font characteristics hash. + */ + const ON_Font* FromFontCharacteristicsHash( + ON_SHA1_Hash font_characteristics_hash, + bool bReturnFirst + ) const; + + const ON_Font* FromPostScriptName( + const wchar_t* postscript_name + ) const; + + const ON_Font* FromPostScriptName( + const wchar_t* postscript_name, + ON_Font::Weight prefered_weight, + ON_Font::Stretch prefered_stretch, + ON_Font::Style prefered_style + ) const; + + const ON_Font* FromPostScriptName( + const wchar_t* postscript_name, + ON_Font::Weight prefered_weight, + ON_Font::Stretch prefered_stretch, + ON_Font::Style prefered_style, + bool bUnderlined, + bool bStrikethrough + ) const; + + const ON_Font* FromWindowsLogfontName( + const wchar_t* windows_logfont_name + ) const; + + const ON_Font* FromWindowsLogfontName( + const wchar_t* windows_logfont_name, + ON_Font::Weight prefered_weight, + ON_Font::Stretch prefered_stretch, + ON_Font::Style prefered_style + ) const; + + const ON_Font* FromWindowsLogfontName( + const wchar_t* windows_logfont_name, + ON_Font::Weight prefered_weight, + ON_Font::Stretch prefered_stretch, + ON_Font::Style prefered_style, + bool bUnderlined, + bool bStrikethrough + ) const; + + const ON_Font* FromFamilyName( + const wchar_t* family_name, + const wchar_t* prefered_face_name + ) const; + + const ON_Font* FromFamilyName( + const wchar_t* family_name, + const wchar_t* prefered_face_name, + ON_Font::Weight prefered_weight, + ON_Font::Stretch prefered_stretch, + ON_Font::Style prefered_style + ) const; + + const ON_Font* FromFamilyName( + const wchar_t* family_name, + const wchar_t* prefered_face_name, + ON_Font::Weight prefered_weight, + ON_Font::Stretch prefered_stretch, + ON_Font::Style prefered_style, + bool bUnderlined, + bool bStrikethrough + ) const; + + /* + Parameters: + rtf_font_name - [in] + Rich text format name. This name is not well defined and depends on + the device and application that created the rich text. On Windows this + is often a LOGFONT.lfFaceName. On MacOS it is often a PostScript name. + + bRtfBold - [in] + RTF bold flag + + bRtfItalic - [in] + RTF italic flag + */ + ON_DEPRECATED_MSG("Use the static ON_Font::FontFromRichTextProperties()") + const ON_Font* FromRichTextProperties( + const wchar_t* rtf_font_name, + bool bRtfBold, + bool bRtfItalic, + bool bUnderlined, + bool bStrikethrough + ) const; + + /* + Parameters: + postscript_name - [in] + windows_logfont_name - [in] + family_name - [in] + The returned font will have an exact match for one + of the three names, postscript_name, windows_logfont_name, + or family_name. + + prefered_face_name - [in] + prefered_weight - [in] + prefered_stretch - [in] + prefered_style - [in] + Prefered font properties. + + bRequireFaceMatch - [in] + If true and face_name is not empty, then the returned font + will have an exact match for either postscript_name, windows_logfont_name, + or the family and face name pair. + + bRequireStyleMatch - [in] + If true and prefered_stretch is not unset, then the returned + font will have prefered_style + Remarks: + Ignores underlined, strikethrough, and point size settings when looking for a match. + */ + const ON_Font* FromNames( + const wchar_t* postscript_name, + const wchar_t* windows_logfont_name, + const wchar_t* family_name, + const wchar_t* prefered_face_name, + ON_Font::Weight prefered_weight, + ON_Font::Stretch prefered_stretch, + ON_Font::Style prefered_style, + bool bRequireFaceMatch, + bool bRequireStyleMatch + ) const; + + /* + Parameters: + postscript_name - [in] + windows_logfont_name - [in] + family_name - [in] + The returned font will have an exact match for one + of the three names, postscript_name, windows_logfont_name, + or family_name. + + prefered_face_name - [in] + prefered_weight - [in] + prefered_stretch - [in] + prefered_style - [in] + Prefered font properties. + + bRequireFaceMatch - [in] + If true and face_name is not empty, then the returned font + will have an exact match for either postscript_name, windows_logfont_name, + or the family and face name pair. + + bRequireStyleMatch - [in] + If true and prefered_stretch is not unset, then the returned + font will have prefered_style + + bUnderlined - [in] + Exact match required. + bStrikethrough - [in] + Exact match required. + point_size - [in] + Exact match required. + */ + const ON_Font* FromNames( + const wchar_t* postscript_name, + const wchar_t* windows_logfont_name, + const wchar_t* family_name, + const wchar_t* prefered_face_name, + ON_Font::Weight prefered_weight, + ON_Font::Stretch prefered_stretch, + ON_Font::Style prefered_style, + bool bRequireFaceMatch, + bool bRequireStyleMatch, + bool bUnderlined, + bool bStrikethrough, + double point_size + ) const; + + const ON_Font* FromFontProperties( + const ON_Font* font_properties, + bool bRequireFaceMatch, + bool bRequireStyleMatch + ) const; + + const ON_Font* FromFontProperties( + const ON_Font* font_properties, + bool bRequireFaceMatch, + bool bRequireStyleMatch, + bool bUnderlined, + bool bStrikethrough, + double point_size + ) const; + + /* + Parameters: + family name - [in] + desired_weight - [in] + desired_stretch - [in] + desired_style - [in] + Returns: + A font in the same family with that comes a close as possible to matching the + desired weight, stretch and style. + */ + const ON_Font* FamilyMemberWithWeightStretchStyle( + const wchar_t* family_name, + ON_Font::Weight desired_weight, + ON_Font::Stretch desired_stretch, + ON_Font::Style desired_style + ) const; + + /* + Parameters: + font - [in] + Used to identify the family, + desired_weight - [in] + new weight or unset if font weight is adequate + desired_stretch - [in] + new stretch or unset if font stretch is adequate + desired_style - [in] + new style or unset if font style is adequate + Returns: + A font in the same family with that comes a close as possible to matching the + desired weight, stretch and style. + */ + const ON_Font* FamilyMemberWithWeightStretchStyle( + const ON_Font* font, + ON_Font::Weight desired_weight, + ON_Font::Stretch desired_stretch, + ON_Font::Style desired_style + ) const; + + /* + Description: + Get the subset of fonts in this list with matching names. + */ + unsigned int FontListFromNames( + const wchar_t* postscript_name, + const wchar_t* windows_logfont_name, + const wchar_t* family_name, + const wchar_t* face_name, + ON_SimpleArray< const ON_Font* >& font_list + ) const; + + /* + Returns: + Array of fonts in the order they were added. + */ + const ON_SimpleArray< const class ON_Font* >& ByIndex() const; + + /* + Returns: + Array of fonts sorted by ON_Font.PostScriptName(). + */ + const ON_SimpleArray< const class ON_Font* >& ByPostScriptName() const; + + /* + Returns: + Array of fonts sorted by ON_Font.WindowsLogfontName(). + */ + const ON_SimpleArray< const class ON_Font* >& ByWindowsLogfontName() const; + + /* + Returns: + Array of fonts sorted by ON_Font.FamilyName() and then by ON_Font.FaceName(). + */ + const ON_SimpleArray< const class ON_Font* >& ByFamilyName() const; + + /* + Returns: + Array of fonts sorted by ON_Font.QuartetName(). + */ + const ON_SimpleArray< const class ON_Font* >& ByQuartetName() const; + + /* + Returns: + Array of fonts sorted by ON_Font.yFontCharacteristicsHash(). + */ + const ON_SimpleArray< const class ON_Font* >& ByFontCharacteristicsHash() const; + + /* + Returns: + Array of font face quartets for this list sorted quartet name. + Remarks: + This is pribarily for old-fashioned font selection UI that harkens back + to the days of LOGFONT. The UI displays a name and a bold and italic button + that lets you select one of four releated faces. The name used to be based + on the LOGFONT name. Depending on the contents of the list, there may be + some faces in the list that do not appear in the QuartetList(). + */ + const ON_ClassArray< ON_FontFaceQuartet >& QuartetList() const; + + /* + Description: + Find a font in this list with the specified quartet properties. + Parameters: + quartet_name - [in] + bBold - [in] + bItalic - [in] + Returns: + font in the list with specified quartet properties or nullptr if none exists. + */ + const ON_Font* FontFromQuartetProperties( + const wchar_t* quartet_name, + bool bBold, + bool bItalic + ) const; + + /* + Returns: + The quartet with the specified name or ON_FontFaceQuartet::Empty if none exists. + */ + const ON_FontFaceQuartet QuartetFromQuartetName( + const wchar_t* quartet_name + ) const; + + static int CompareFontCharacteristicsHash(ON_Font const* const* lhs, ON_Font const* const* rhs); + + static int ComparePostScriptName(ON_Font const* const* lhs, ON_Font const* const* rhs); + static int CompareFamilyName(ON_Font const* const* lhs, ON_Font const* const* rhs); + static int CompareFamilyAndFaceName(ON_Font const* const* lhs, ON_Font const* const* rhs); + static int CompareWindowsLogfontName(ON_Font const* const* lhs, ON_Font const* const* rhs); + static int CompareFamilyAndWindowsLogfontName(ON_Font const* const* lhs, ON_Font const* const* rhs); + + static int CompareEnglishPostScriptName(ON_Font const* const* lhs, ON_Font const* const* rhs); + static int CompareEnglishFamilyName(ON_Font const* const* lhs, ON_Font const* const* rhs); + static int CompareEnglishFamilyAndFaceName(ON_Font const* const* lhs, ON_Font const* const* rhs); + static int CompareEnglishWindowsLogfontName(ON_Font const* const* lhs, ON_Font const* const* rhs); + + static int CompareQuartetName(ON_Font const* const* lhs, ON_Font const* const* rhs); + + static int CompareWeightStretchStyle(ON_Font const* const* lhs, ON_Font const* const* rhs); + static int CompareStretch(ON_Font const* const* lhs, ON_Font const* const* rhs); + static int CompareUnderlinedStrikethroughPointSize(ON_Font const* const* lhs, ON_Font const* const* rhs); + + unsigned int AddFont( + const ON_Font* font, + bool bCheckForDuplicates + ); + + unsigned int AddFonts( + const ON_SimpleArray< const ON_Font* >& fonts + ); + + unsigned int AddFonts( + size_t font_count, + const ON_Font * const * font_list + ); + +private: + friend class ON_ManagedFonts; + +private: + const ON_Font* Internal_FromNames( + const wchar_t* postscript_name, + const wchar_t* windows_logfont_name, + const wchar_t* family_name, + const wchar_t* prefered_face_name, + ON_Font::Weight prefered_weight, + ON_Font::Stretch prefered_stretch, + ON_Font::Style prefered_style, + bool bRequireFaceMatch, + bool bRequireStyleMatch, + bool bMatchUnderlineStrikethroughAndPointSize, + bool bUnderlined, + bool bStrikethrough, + double point_size + ) const; + +private: + const ON_Font::NameLocale m_name_locale = ON_Font::NameLocale::LocalizedFirst; + bool m_bMatchUnderlineStrikethroughAndPointSize = false; + + void Internal_EmptyLists(); + + // List of all added fonts in the order they were added + ON_SimpleArray< const ON_Font* > m_by_index; + + void Internal_UpdateSortedLists() const; + + static const ON_2dex Internal_SearchSortedList( + const ON_Font* key, + ON_FontPtrCompareFunc compare_func, + const ON_SimpleArray< const ON_Font* >& sorted_font_list + ); + + // List of recently added fonts unsorted + mutable ON_SimpleArray< const ON_Font* > m_unsorted; + + // A single instance is allocated in the default constructor + // and freed in the destructor. You may assume this point is valid. + // ON_FontListImpl contains the sorted lists. + class ON_FontListImpl& m_sorted; + + // this reserved block is here to keep sizeof(ON_FontList) unchanged between + // Rhino 7.3 and Rhino 7.4 and to insure that any 3rd party code that used ON_FontList + // in Rhino 7.3 will continue to work as expected in Rhino 7.4. + const ON__UINT_PTR m_reserved[20] = {}; + + // List of quartets sorted by quartet name. + mutable ON_ClassArray< ON_FontFaceQuartet > m_quartet_list; +}; + + +#if defined(ON_RUNTIME_WIN) + +/* +Remarks: + Windows GDI functions used by ON_WindowsMeasureGlyph fail when the + UTF-16 encoding of unicode_code_point requires a surrogate pair. +*/ +ON_DECL +bool ON_WindowsGetGlyphMetrics( + const ON_Font* font, + ON__UINT32 unicode_code_point, + class ON_TextBox& font_unit_glyph_box +); + + + +#endif + + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +#endif + +#endif + + diff --git a/opennurbs/Include/opennurbs_fpoint.h b/opennurbs/Include/opennurbs_fpoint.h new file mode 100644 index 0000000..5e147ab --- /dev/null +++ b/opennurbs/Include/opennurbs_fpoint.h @@ -0,0 +1,1161 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +//////////////////////////////////////////////////////////////// +// +// defines float precision point, vector, and array classes +// +//////////////////////////////////////////////////////////////// +#if !defined(ON_FPOINT_INC_) +#define ON_FPOINT_INC_ + +class ON_Xform; + +class ON_2fPoint; +class ON_3fPoint; +class ON_4fPoint; + +class ON_2fVector; +class ON_3fVector; + +//////////////////////////////////////////////////////////////// +// +// ON_2fPoint +// +class ON_CLASS ON_2fPoint +{ +public: + float x, y; + +public: + // x,y not initialized + ON_2fPoint() = default; + ~ON_2fPoint() = default; + ON_2fPoint(const ON_2fPoint&) = default; + ON_2fPoint& operator=(const ON_2fPoint&) = default; + +public: + static const ON_2fPoint Origin; // (0.0f,0.0f) + static const ON_2fPoint NanPoint; // (ON_FLT_QNAN,ON_FLT_QNAN) + +public: + explicit ON_2fPoint(float x,float y); + + /* + Description: + A well ordered dictionary compare function that is nan aware and can + be used for robust sorting. + */ + static int Compare( + const ON_2fPoint& lhs, + const ON_2fPoint& rhs + ); + + /* + Returns: + (A+B)/2 + Remarks: + Exact when coordinates are equal and prevents overflow. + */ + static const ON_2fPoint Midpoint(const ON_2fPoint& A, const ON_2fPoint& B); + + explicit ON_2fPoint(const ON_3fPoint& ); // from 3f point + explicit ON_2fPoint(const ON_4fPoint& ); // from 4f point + explicit ON_2fPoint(const ON_2fVector& ); // from 2f vector + explicit ON_2fPoint(const ON_3fVector& ); // from 3f vector + explicit ON_2fPoint(const float*); // from float[2] array + + explicit ON_2fPoint(const ON_2dPoint& ); // from 2d point + explicit ON_2fPoint(const ON_3dPoint& ); // from 3d point + explicit ON_2fPoint(const ON_4dPoint& ); // from 4d point + explicit ON_2fPoint(const ON_2dVector& ); // from 2d vector + explicit ON_2fPoint(const ON_3dVector& ); // from 3d vector + explicit ON_2fPoint(const double*); // from double[2] array + + // (float*) conversion operators + operator float*(); + operator const float*() const; + + // use implicit operator=(const ON_2fPoint&) + ON_2fPoint& operator=(const ON_3fPoint&); + ON_2fPoint& operator=(const ON_4fPoint&); + ON_2fPoint& operator=(const ON_2fVector&); + ON_2fPoint& operator=(const ON_3fVector&); + ON_2fPoint& operator=(const float*); // point = float[2] support + + ON_2fPoint& operator=(const ON_2dPoint&); + ON_2fPoint& operator=(const ON_3dPoint&); + ON_2fPoint& operator=(const ON_4dPoint&); + ON_2fPoint& operator=(const ON_2dVector&); + ON_2fPoint& operator=(const ON_3dVector&); + ON_2fPoint& operator=(const double*); // point = double[2] support + + ON_2fPoint& operator*=(float); + ON_2fPoint& operator/=(float); + ON_2fPoint& operator+=(const ON_2fVector&); + ON_2fPoint& operator-=(const ON_2fVector&); + + ON_2fPoint operator*(int) const; + ON_2fPoint operator/(int) const; + ON_2fPoint operator*(float) const; + ON_2fPoint operator/(float) const; + ON_2dPoint operator*(double) const; + ON_2dPoint operator/(double) const; + + ON_2fPoint operator+(const ON_2fPoint&) const; + ON_2fPoint operator+(const ON_2fVector&) const; + ON_2fVector operator-(const ON_2fPoint&) const; + ON_2fPoint operator-(const ON_2fVector&) const; + ON_3fPoint operator+(const ON_3fPoint&) const; + ON_3fPoint operator+(const ON_3fVector&) const; + ON_3fVector operator-(const ON_3fPoint&) const; + ON_3fPoint operator-(const ON_3fVector&) const; + + ON_2dPoint operator+(const ON_2dPoint&) const; + ON_2dPoint operator+(const ON_2dVector&) const; + ON_2dVector operator-(const ON_2dPoint&) const; + ON_2dPoint operator-(const ON_2dVector&) const; + ON_3dPoint operator+(const ON_3dPoint&) const; + ON_3dPoint operator+(const ON_3dVector&) const; + ON_3dVector operator-(const ON_3dPoint&) const; + ON_3dPoint operator-(const ON_3dVector&) const; + + float operator*(const ON_2fPoint&) const; // for points acting as vectors + float operator*(const ON_2fVector&) const; // for points acting as vectors + + bool operator==(const ON_2fPoint&) const; + bool operator!=(const ON_2fPoint&) const; + + // dictionary order comparisons + bool operator<=(const ON_2fPoint&) const; + bool operator>=(const ON_2fPoint&) const; + bool operator<(const ON_2fPoint&) const; + bool operator>(const ON_2fPoint&) const; + + // index operators mimic float[2] behavior + float& operator[](int); + float operator[](int) const; + float& operator[](unsigned int); + float operator[](unsigned int) const; + + /* + Returns: + False if any coordinate is ON_UNSET_FLOAT, ON_UNSET_POSITIVE_FLOAT, nan, or infinite. + True, otherwise. + */ + bool IsValid() const; + + /* + Returns: + True if any coordinate is ON_UNSET_FLOAT or ON_UNSET_POSITIVE_FLOAT + */ + bool IsUnset() const; + + // set 2d point value + void Set(float,float); + + double DistanceTo( const ON_2fPoint& ) const; + + int MaximumCoordinateIndex() const; + double MaximumCoordinate() const; // absolute value of maximum coordinate + + ON_DEPRECATED_MSG("Use p = ON_2fPoint::Origin;") + void Zero(); // set all coordinates to zero; + + /* + Returns: + true if all coordinates are not zero and no coordinates are nans. + false otherwise. + */ + bool IsZero() const; + + /* + Returns: + true if at lease one coordinate is not zero and no coordinates are unset or nans. + */ + bool IsNotZero() const; + + // These transform the point in place. The transformation matrix acts on + // the left of the point; i.e., result = transformation*point + void Transform( + const ON_Xform& + ); + + void Rotate( // rotatation in XY plane + double, // angle in radians + const ON_2fPoint& // center of rotation + ); + + void Rotate( // rotatation in XY plane + double, // sin(angle) + double, // cos(angle) + const ON_2fPoint& // center of rotation + ); + + ON__UINT32 DataCRC(ON__UINT32 current_remainder) const; +}; + +ON_DECL +ON_2fPoint operator*(int, const ON_2fPoint&); + +ON_DECL +ON_2fPoint operator*(float, const ON_2fPoint&); + +ON_DECL +ON_2dPoint operator*(double, const ON_2fPoint&); + +//////////////////////////////////////////////////////////////// +// +// ON_3fPoint +// +class ON_CLASS ON_3fPoint +{ +public: + float x, y, z; + +public: + // x,y,z not initialized + ON_3fPoint() = default; + ~ON_3fPoint() = default; + ON_3fPoint(const ON_3fPoint&) = default; + ON_3fPoint& operator=(const ON_3fPoint&) = default; + +public: + static const ON_3fPoint Origin; // (0.0f,0.0f,0.0f) + static const ON_3fPoint NanPoint; // (ON_FLT_QNAN,ON_FLT_QNAN,ON_FLT_QNAN) + + /* + Description: + A well ordered dictionary compare function that is nan aware and can + be used for robust sorting. + */ + static int Compare( + const ON_3fPoint& lhs, + const ON_3fPoint& rhs + ); + + /* + Returns: + (A+B)/2 + Remarks: + Exact when coordinates are equal and prevents overflow. + */ + static const ON_3fPoint Midpoint(const ON_3fPoint& A, const ON_3fPoint& B); + + explicit ON_3fPoint(float x,float y,float z); + explicit ON_3fPoint(const ON_2fPoint& ); // from 2f point + explicit ON_3fPoint(const ON_4fPoint& ); // from 4f point + explicit ON_3fPoint(const ON_2fVector& ); // from 2f vector + explicit ON_3fPoint(const ON_3fVector& ); // from 3f vector + explicit ON_3fPoint(const float*); // from float[3] array + + explicit ON_3fPoint(const ON_2dPoint& ); // from 2d point + explicit ON_3fPoint(const ON_3dPoint& ); // from 3d point + explicit ON_3fPoint(const ON_4dPoint& ); // from 4d point + explicit ON_3fPoint(const ON_2dVector& ); // from 2d vector + explicit ON_3fPoint(const ON_3dVector& ); // from 3d vector + explicit ON_3fPoint(const double*); // from double[3] array + + // (float*) conversion operators + operator float*(); + operator const float*() const; + + // use implicit operator=(const ON_3fPoint&) + ON_3fPoint& operator=(const ON_2fPoint&); + ON_3fPoint& operator=(const ON_4fPoint&); + ON_3fPoint& operator=(const ON_2fVector&); + ON_3fPoint& operator=(const ON_3fVector&); + ON_3fPoint& operator=(const float*); // point = float[3] support + + ON_3fPoint& operator=(const ON_2dPoint&); + ON_3fPoint& operator=(const ON_3dPoint&); + ON_3fPoint& operator=(const ON_4dPoint&); + ON_3fPoint& operator=(const ON_2dVector&); + ON_3fPoint& operator=(const ON_3dVector&); + ON_3fPoint& operator=(const double*); // point = double[3] support + + ON_3fPoint& operator*=(float); + ON_3fPoint& operator/=(float); + ON_3fPoint& operator+=(const ON_3fVector&); + ON_3fPoint& operator-=(const ON_3fVector&); + + ON_3fPoint operator*(int) const; + ON_3fPoint operator/(int) const; + ON_3fPoint operator*(float) const; + ON_3fPoint operator/(float) const; + ON_3dPoint operator*(double) const; + ON_3dPoint operator/(double) const; + + ON_3fPoint operator+(const ON_3fPoint&) const; + ON_3fPoint operator+(const ON_3fVector&) const; + ON_3fVector operator-(const ON_3fPoint&) const; + ON_3fPoint operator-(const ON_3fVector&) const; + ON_3fPoint operator+(const ON_2fPoint&) const; + ON_3fPoint operator+(const ON_2fVector&) const; + ON_3fVector operator-(const ON_2fPoint&) const; + ON_3fPoint operator-(const ON_2fVector&) const; + + ON_3dPoint operator+(const ON_3dPoint&) const; + ON_3dPoint operator+(const ON_3dVector&) const; + ON_3dVector operator-(const ON_3dPoint&) const; + ON_3dPoint operator-(const ON_3dVector&) const; + ON_3dPoint operator+(const ON_2dPoint&) const; + ON_3dPoint operator+(const ON_2dVector&) const; + ON_3dVector operator-(const ON_2dPoint&) const; + ON_3dPoint operator-(const ON_2dVector&) const; + + float operator*(const ON_3fPoint&) const; // for points acting as vectors + float operator*(const ON_3fVector&) const; // for points acting as vectors + + bool operator==(const ON_3fPoint&) const; + bool operator!=(const ON_3fPoint&) const; + + // dictionary order comparisons + bool operator<=(const ON_3fPoint&) const; + bool operator>=(const ON_3fPoint&) const; + bool operator<(const ON_3fPoint&) const; + bool operator>(const ON_3fPoint&) const; + + // index operators mimic float[3] behavior + float& operator[](int); + float operator[](int) const; + float& operator[](unsigned int); + float operator[](unsigned int) const; + + /* + Returns: + False if any coordinate is ON_UNSET_FLOAT, ON_UNSET_POSITIVE_FLOAT, nan, or infinite. + True, otherwise. + */ + bool IsValid() const; + + /* + Returns: + True if any coordinate is ON_UNSET_FLOAT or ON_UNSET_POSITIVE_FLOAT + */ + bool IsUnset() const; + + // set 3d point value + void Set(float,float,float); + + double DistanceTo( const ON_3fPoint& ) const; + + int MaximumCoordinateIndex() const; + double MaximumCoordinate() const; // absolute value of maximum coordinate + double Fuzz( double = ON_ZERO_TOLERANCE ) const; // tolerance to use when comparing 3d points + + ON_DEPRECATED_MSG("Use p = ON_3fPoint::Origin;") + void Zero(); // set all coordinates to zero; + + /* + Returns: + true if all coordinates are not zero and no coordinates are nans. + false otherwise. + */ + bool IsZero() const; + + /* + Returns: + true if at lease one coordinate is not zero and no coordinates are unset or nans. + */ + bool IsNotZero() const; + + // These transform the point in place. The transformation matrix acts on + // the left of the point; i.e., result = transformation*point + void Transform( + const ON_Xform& + ); + + void Rotate( + double, // angle in radians + const ON_3fVector&, // axis of rotation + const ON_3fPoint& // center of rotation + ); + + void Rotate( + double, // sin(angle) + double, // cos(angle) + const ON_3fVector&, // axis of rotation + const ON_3fPoint& // center of rotation + ); + + ON__UINT32 DataCRC(ON__UINT32 current_remainder) const; +}; + +ON_DECL +ON_3fPoint operator*(int, const ON_3fPoint&); + +ON_DECL +ON_3fPoint operator*(float, const ON_3fPoint&); + +ON_DECL +ON_3dPoint operator*(double, const ON_3fPoint&); + +//////////////////////////////////////////////////////////////// +// +// ON_4fPoint (homogeneous coordinates) +// +class ON_CLASS ON_4fPoint +{ +public: + float x, y, z, w; + + /* + Returns: + ON_UNSET_VALUE, if x or w is ON_UNSET_VALUE or ON_UNSET_POSITIVE_VALUE + and neither x nor w is a nan. + x/w, otherwise + Remarks: + If w is 0.0 or nan, the result will be a nan. + */ + float EuclideanX() const; + + /* + Returns: + ON_UNSET_VALUE, if y or w is ON_UNSET_VALUE or ON_UNSET_POSITIVE_VALUE + and neither y nor w is a nan. + y/w, otherwise + Remarks: + If w is 0.0 or nan, the result will be a nan. + */ + float EuclideanY() const; + + /* + Returns: + ON_UNSET_VALUE, if z or w is ON_UNSET_VALUE or ON_UNSET_POSITIVE_VALUE + and neither z nor w is a nan. + z/w, otherwise + Remarks: + If w is 0.0 or nan, the result will be a nan. + */ + float EuclideanZ() const; + +public: + // x,y,z,w not initialized + ON_4fPoint() = default; + ~ON_4fPoint() = default; + ON_4fPoint(const ON_4fPoint&) = default; + ON_4fPoint& operator=(const ON_4fPoint&) = default; + +public: + static const ON_4fPoint Zero; // (0,0,0,0) + static const ON_4fPoint Nan; // (ON_FLT_QNAN,ON_FLT_QNAN,ON_FLT_QNAN,ON_FLT_QNAN) + + /* + Description: + A well ordered projective compare function that is nan aware and can + be used for robust sorting. + Remarks: + float c = non-nan value. + ON_4fPoint h0 = ...; + ON_4fPoint h1(c*h0.x,c*h0.x,c*h0.x,c*h0.x); + 0 == ON_4fPoint::ProjectiveCompare(h0,ha); + */ + static int ProjectiveCompare( + const ON_4fPoint& lhs, + const ON_4fPoint& rhs + ); + + /* + Description: + A well ordered dictionary compare function that is nan aware and can + be used for robust sorting. + */ + static int DictionaryCompare( + const ON_4fPoint& lhs, + const ON_4fPoint& rhs + ); + + /* + Returns: + True if (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w). + */ + bool operator==(const ON_4fPoint& rhs) const; + + /* + Returns: + True if lhs.* != rhs.* for some coordinate and no values are nans. + */ + bool operator!=(const ON_4fPoint& rhs) const; + + explicit ON_4fPoint(float x,float y,float z,float w); + + ON_4fPoint(const ON_2fPoint& ); // from 2f point + ON_4fPoint(const ON_3fPoint& ); // from 3f point + ON_4fPoint(const ON_2fVector& ); // from 2f vector + ON_4fPoint(const ON_3fVector& ); // from 3f vector + + // Require explicit construction when dev must insure array has length >= 4. + explicit ON_4fPoint(const float*); // from float[4] array + + // Require explicit construction when loosing precision + explicit ON_4fPoint(const ON_2dPoint& ); // from 2d point + explicit ON_4fPoint(const ON_3dPoint& ); // from 3d point + explicit ON_4fPoint(const ON_4dPoint& ); // from 4d point + explicit ON_4fPoint(const ON_2dVector& ); // from 2d vector + explicit ON_4fPoint(const ON_3dVector& ); // from 3d vector + explicit ON_4fPoint(const double*); // from double[4] array + + // (float*) conversion operators + operator float*(); + operator const float*() const; + + // use implicit operator=(const ON_4fPoint&) + ON_4fPoint& operator=(const ON_2fPoint&); + ON_4fPoint& operator=(const ON_3fPoint&); + ON_4fPoint& operator=(const ON_2fVector&); + ON_4fPoint& operator=(const ON_3fVector&); + ON_4fPoint& operator=(const float*); // point = float[4] support + + ON_4fPoint& operator=(const ON_2dPoint&); + ON_4fPoint& operator=(const ON_3dPoint&); + ON_4fPoint& operator=(const ON_4dPoint&); + ON_4fPoint& operator=(const ON_2dVector&); + ON_4fPoint& operator=(const ON_3dVector&); + ON_4fPoint& operator=(const double*); // point = double[4] support + + ON_4fPoint& operator*=(float); + ON_4fPoint& operator/=(float); + ON_4fPoint& operator+=(const ON_4fPoint&); + ON_4fPoint& operator-=(const ON_4fPoint&); + + ON_4fPoint operator*(float) const; + ON_4fPoint operator/(float) const; + ON_4fPoint operator+(const ON_4fPoint&) const; // sum w = sqrt(w1*w2) + ON_4fPoint operator-(const ON_4fPoint&) const; // difference w = sqrt(w1*w2) + +public: + // index operators mimic float[4] behavior + float& operator[](int); + float operator[](int) const; + float& operator[](unsigned int); + float operator[](unsigned int) const; + + /* + Returns: + False if any coordinate is ON_UNSET_FLOAT, ON_UNSET_POSITIVE_FLOAT, nan, or infinite. + True, otherwise. + */ + bool IsValid() const; + + /* + Returns: + True if any coordinate is ON_UNSET_FLOAT or ON_UNSET_POSITIVE_FLOAT + */ + bool IsUnset() const; + + // set 4d point value + void Set(float,float,float,float); + + int MaximumCoordinateIndex() const; + double MaximumCoordinate() const; // absolute value of maximum coordinate + + bool Normalize(); // set so x^2 + y^2 + z^2 + w^2 = 1 + + // These transform the point in place. The transformation matrix acts on + // the left of the point; i.e., result = transformation*point + void Transform( + const ON_Xform& + ); + + ON__UINT32 DataCRC(ON__UINT32 current_remainder) const; +}; + +ON_DECL +ON_4fPoint operator*(float, const ON_4fPoint&); + +ON_DECL +ON_4dPoint operator*(double, const ON_4fPoint&); + +//////////////////////////////////////////////////////////////// +// +// ON_2fVector +// +class ON_CLASS ON_2fVector +{ +public: + float x, y; + +public: + // x,y not initialized + ON_2fVector() = default; + ~ON_2fVector() = default; + ON_2fVector(const ON_2fVector&) = default; + ON_2fVector& operator=(const ON_2fVector&) = default; + +public: + static const ON_2fVector NanVector; // (ON_FLT_QNAN,ON_FLT_QNAN) + static const ON_2fVector ZeroVector; // (0.0f,0.0f) + static const ON_2fVector XAxis; // (1.0f,0.0f) + static const ON_2fVector YAxis; // (0.0f,1.0f) + + /* + Description: + A well ordered dictionary compare function that is nan aware and can + be used for robust sorting. + */ + static int Compare( + const ON_2fVector& lhs, + const ON_2fVector& rhs + ); + + // Description: + // A index driven function to get unit axis vectors. + // Parameters: + // index - [in] 0 returns (1,0), 1 returns (0,1) + // Returns: + // Unit 3d vector with vector[i] = (i==index)?1:0; + static const ON_2fVector& UnitVector( + int // index + ); + + explicit ON_2fVector(float x,float y); + explicit ON_2fVector(const ON_2fPoint& ); // from 2f point + explicit ON_2fVector(const ON_3fPoint& ); // from 3f point + explicit ON_2fVector(const ON_3fVector& ); // from 3f vector + explicit ON_2fVector(const float*); // from float[2] array + + explicit ON_2fVector(const ON_2dPoint& ); // from 2d point + explicit ON_2fVector(const ON_3dPoint& ); // from 3d point + explicit ON_2fVector(const ON_2dVector& ); // from 2d vector + explicit ON_2fVector(const ON_3dVector& ); // from 3d vector + explicit ON_2fVector(const double*); // from double[2] array + + // (float*) conversion operators + operator float*(); + operator const float*() const; + + // use implicit operator=(const ON_2fVector&) + ON_2fVector& operator=(const ON_2fPoint&); + ON_2fVector& operator=(const ON_3fPoint&); + ON_2fVector& operator=(const ON_3fVector&); + ON_2fVector& operator=(const float*); // point = float[2] support + + ON_2fVector& operator=(const ON_2dPoint&); + ON_2fVector& operator=(const ON_3dPoint&); + ON_2fVector& operator=(const ON_2dVector&); + ON_2fVector& operator=(const ON_3dVector&); + ON_2fVector& operator=(const double*); // point = double[2] support + + ON_2fVector operator-() const; + + ON_2fVector& operator*=(float); + ON_2fVector& operator/=(float); + ON_2fVector& operator+=(const ON_2fVector&); + ON_2fVector& operator-=(const ON_2fVector&); + + float operator*(const ON_2fVector&) const; // inner (dot) product + float operator*(const ON_2fPoint&) const; // inner (dot) product point acting as a vector + double operator*(const ON_2dVector&) const; // inner (dot) product + + ON_2fVector operator*(int) const; + ON_2fVector operator/(int) const; + ON_2fVector operator*(float) const; + ON_2fVector operator/(float) const; + ON_2dVector operator*(double) const; + ON_2dVector operator/(double) const; + + ON_2fVector operator+(const ON_2fVector&) const; + ON_2fPoint operator+(const ON_2fPoint&) const; + ON_2fVector operator-(const ON_2fVector&) const; + ON_2fPoint operator-(const ON_2fPoint&) const; + ON_3fVector operator+(const ON_3fVector&) const; + ON_3fPoint operator+(const ON_3fPoint&) const; + ON_3fVector operator-(const ON_3fVector&) const; + ON_3fPoint operator-(const ON_3fPoint&) const; + + ON_2dVector operator+(const ON_2dVector&) const; + ON_2dPoint operator+(const ON_2dPoint&) const; + ON_2dVector operator-(const ON_2dVector&) const; + ON_2dPoint operator-(const ON_2dPoint&) const; + ON_3dVector operator+(const ON_3dVector&) const; + ON_3dPoint operator+(const ON_3dPoint&) const; + ON_3dVector operator-(const ON_3dVector&) const; + ON_3dPoint operator-(const ON_3dPoint&) const; + + bool operator==(const ON_2fVector&) const; + bool operator!=(const ON_2fVector&) const; + + // dictionary order comparisons + bool operator<=(const ON_2fVector&) const; + bool operator>=(const ON_2fVector&) const; + bool operator<(const ON_2fVector&) const; + bool operator>(const ON_2fVector&) const; + + // index operators mimic float[2] behavior + float& operator[](int); + float operator[](int) const; + float& operator[](unsigned int); + float operator[](unsigned int) const; + + /* + Returns: + False if any coordinate is ON_UNSET_FLOAT, ON_UNSET_POSITIVE_FLOAT, nan, or infinite. + True, otherwise. + */ + bool IsValid() const; + + /* + Returns: + True if any coordinate is ON_UNSET_FLOAT or ON_UNSET_POSITIVE_FLOAT + */ + bool IsUnset() const; + + // set 2d vector value + void Set(float,float); + + int MaximumCoordinateIndex() const; + double MaximumCoordinate() const; // absolute value of maximum coordinate + + double LengthSquared() const; + double Length() const; + + bool Decompose( // Computes a, b such that this vector = a*X + b*Y + // Returns false if unable to solve for a,b. This happens + // when X,Y is not really a basis. + // + // If X,Y is known to be an orthonormal frame, + // then a = V*X, b = V*Y will compute + // the same result more quickly. + const ON_2fVector&, // X + const ON_2fVector&, // Y + double*, // a + double* // b + ) const; + + int IsParallelTo( + // returns 1: this and other vectors are parallel + // -1: this and other vectors are anti-parallel + // 0: this and other vectors are not parallel + // or at least one of the vectors is zero + const ON_2fVector&, // other vector + double = ON_DEFAULT_ANGLE_TOLERANCE // optional angle tolerance (radians) + ) const; + + bool IsPerpendicularTo( + // returns true: this and other vectors are perpendicular + // false: this and other vectors are not perpendicular + // or at least one of the vectors is zero + const ON_2fVector&, // other vector + double = ON_DEFAULT_ANGLE_TOLERANCE // optional angle tolerance (radians) + ) const; + + ON_DEPRECATED_MSG("Use p = ON_2fVector::ZeroVector;") + void Zero(); // set all coordinates to zero; + + ON_DEPRECATED_MSG("Use v = -v;") + void Reverse(); // negate all coordinates + + bool Unitize(); // returns false if vector has zero length + + bool IsUnitVector() const; + + /* + Returns: + If this is a valid non-zero vector, a unit vector parallel to this is returned. + Otherwise the zero vector is returned. + */ + ON_2fVector UnitVector() const; + + // Description: + // Test a vector to see if it is very short + // + // Parameters: + // tiny_tol - [in] (default = ON_ZERO_TOLERANCE) a nonzero + // value used as the coordinate zero tolerance. + // + // Returns: + // ( fabs(x) <= tiny_tol && fabs(y) <= tiny_tol ) + // + bool IsTiny( + double = ON_ZERO_TOLERANCE // tiny_tol + ) const; + + // Returns: + // true if vector is the zero vector. + bool IsZero() const; + + /* + Returns: + true if at lease one coordinate is not zero and no coordinates are unset or nans. + */ + bool IsNotZero() const; + + // set this vector to be perpendicular to another vector + bool PerpendicularTo( // Result is not unitized. + // returns false if input vector is zero + const ON_2fVector& + ); + + // set this vector to be perpendicular to a line defined by 2 points + bool PerpendicularTo( + const ON_2fPoint&, + const ON_2fPoint& + ); + + ON__UINT32 DataCRC(ON__UINT32 current_remainder) const; +}; + +ON_DECL +ON_2fVector operator*(int, const ON_2fVector&); + +ON_DECL +ON_2fVector operator*(float, const ON_2fVector&); + +ON_DECL +ON_2dVector operator*(double, const ON_2fVector&); + +/////////////////////////////////////////////////////////////// +// +// ON_2fVector utilities +// + +ON_DECL +float +ON_DotProduct( + const ON_2fVector&, + const ON_2fVector& + ); + +ON_DECL +ON_3fVector +ON_CrossProduct( + const ON_2fVector&, + const ON_2fVector& + ); + +ON_DECL +bool +ON_IsOrthogonalFrame( // true if X, Y are nonzero and mutually perpendicular + const ON_2fVector&, // X + const ON_2fVector& // Y + ); + +ON_DECL +bool +ON_IsOrthonormalFrame( // true if X, Y are orthogonal and unit length + const ON_2fVector&, // X + const ON_2fVector& // Y + ); + +ON_DECL +bool +ON_IsRightHandFrame( // true if X, Y are orthonormal and right handed + const ON_2fVector&, // X + const ON_2fVector& // Y + ); + +//////////////////////////////////////////////////////////////// +// +// ON_3fVector +// +class ON_CLASS ON_3fVector +{ +public: + float x, y, z; + +public: + // x,y,z not initialized + ON_3fVector() = default; + ~ON_3fVector() = default; + ON_3fVector(const ON_3fVector&) = default; + ON_3fVector& operator=(const ON_3fVector&) = default; + +public: + static const ON_3fVector NanVector; // (ON_FLT_QNAN,ON_FLT_QNAN,ON_FLT_QNAN) + static const ON_3fVector ZeroVector; // (0.0f,0.0f,0.0f) + static const ON_3fVector XAxis; // (1.0f,0.0f,0.0f) + static const ON_3fVector YAxis; // (0.0f,1.0f,0.0f) + static const ON_3fVector ZAxis; // (0.0f,0.0f,1.0f) + + /* + Description: + A well ordered dictionary compare function that is nan aware and can + be used for robust sorting. + */ + static int Compare( + const ON_3fVector& lhs, + const ON_3fVector& rhs + ); + + // Description: + // A index driven function to get unit axis vectors. + // Parameters: + // index - [in] 0 returns (1,0,0), 1 returns (0,1,0) + // 2 returns (0,0,1) + // Returns: + // Unit 3d vector with vector[i] = (i==index)?1:0; + static const ON_3fVector& UnitVector( + int // index + ); + + explicit ON_3fVector(float x,float y,float z); + + explicit ON_3fVector(const ON_2fPoint& ); // from 2f point + explicit ON_3fVector(const ON_3fPoint& ); // from 3f point + explicit ON_3fVector(const ON_2fVector& ); // from 2f vector + explicit ON_3fVector(const float*); // from float[3] array + + explicit ON_3fVector(const ON_2dPoint& ); // from 2d point + explicit ON_3fVector(const ON_3dPoint& ); // from 3d point + explicit ON_3fVector(const ON_2dVector& ); // from 2d vector + explicit ON_3fVector(const ON_3dVector& ); // from 3d vector + explicit ON_3fVector(const double*); // from double[3] array + + // (float*) conversion operators + operator float*(); + operator const float*() const; + + // use implicit operator=(const ON_3fVector&) + ON_3fVector& operator=(const ON_2fPoint&); + ON_3fVector& operator=(const ON_3fPoint&); + ON_3fVector& operator=(const ON_2fVector&); + ON_3fVector& operator=(const float*); // point = float[3] support + + ON_3fVector& operator=(const ON_2dPoint&); + ON_3fVector& operator=(const ON_3dPoint&); + ON_3fVector& operator=(const ON_2dVector&); + ON_3fVector& operator=(const ON_3dVector&); + ON_3fVector& operator=(const double*); // point = double[3] support + + ON_3fVector operator-() const; + + ON_3fVector& operator*=(float); + ON_3fVector& operator/=(float); + ON_3fVector& operator+=(const ON_3fVector&); + ON_3fVector& operator-=(const ON_3fVector&); + + float operator*(const ON_3fVector&) const; // inner (dot) product + float operator*(const ON_3fPoint&) const; // inner (dot) product (point acting as a vector) + double operator*(const ON_3dVector&) const; // inner (dot) product + + ON_3fVector operator*(int) const; + ON_3fVector operator/(int) const; + ON_3fVector operator*(float) const; + ON_3fVector operator/(float) const; + ON_3dVector operator*(double) const; + ON_3dVector operator/(double) const; + + ON_3fVector operator+(const ON_3fVector&) const; + ON_3fPoint operator+(const ON_3fPoint&) const; + ON_3fVector operator-(const ON_3fVector&) const; + ON_3fPoint operator-(const ON_3fPoint&) const; + ON_3fVector operator+(const ON_2fVector&) const; + ON_3fPoint operator+(const ON_2fPoint&) const; + ON_3fVector operator-(const ON_2fVector&) const; + ON_3fPoint operator-(const ON_2fPoint&) const; + + ON_3dVector operator+(const ON_3dVector&) const; + ON_3dPoint operator+(const ON_3dPoint&) const; + ON_3dVector operator-(const ON_3dVector&) const; + ON_3dPoint operator-(const ON_3dPoint&) const; + ON_3dVector operator+(const ON_2dVector&) const; + ON_3dPoint operator+(const ON_2dPoint&) const; + ON_3dVector operator-(const ON_2dVector&) const; + ON_3dPoint operator-(const ON_2dPoint&) const; + + bool operator==(const ON_3fVector&) const; + bool operator!=(const ON_3fVector&) const; + + // dictionary order comparisons + bool operator<=(const ON_3fVector&) const; + bool operator>=(const ON_3fVector&) const; + bool operator<(const ON_3fVector&) const; + bool operator>(const ON_3fVector&) const; + + // index operators mimic float[3] behavior + float& operator[](int); + float operator[](int) const; + float& operator[](unsigned int); + float operator[](unsigned int) const; + + /* + Returns: + False if any coordinate is ON_UNSET_FLOAT, ON_UNSET_POSITIVE_FLOAT, nan, or infinite. + True, otherwise. + */ + bool IsValid() const; + + /* + Returns: + True if any coordinate is ON_UNSET_FLOAT or ON_UNSET_POSITIVE_FLOAT + */ + bool IsUnset() const; + + // set 3d vector value + void Set(float,float,float); + + int MaximumCoordinateIndex() const; + double MaximumCoordinate() const; // absolute value of maximum coordinate + + double LengthSquared() const; + double Length() const; + + bool IsPerpendicularTo( + // returns true: this and other vectors are perpendicular + // false: this and other vectors are not perpendicular + // or at least one of the vectors is zero + const ON_3fVector&, // other vector + double = ON_DEFAULT_ANGLE_TOLERANCE // optional angle tolerance (radians) + ) const; + + double Fuzz( double = ON_ZERO_TOLERANCE ) const; // tolerance to use when comparing 3d vectors + + ON_DEPRECATED_MSG("Use p = ON_3fVector::ZeroVector;") + void Zero(); // set all coordinates to zero + + ON_DEPRECATED_MSG("Use v = -v;") + void Reverse(); // negate all coordinates + + bool Unitize(); // returns false if vector has zero length + + bool IsUnitVector() const; + + /* + Returns: + If this is a valid non-zero vector, a unit vector parallel to this is returned. + Otherwise the zero vector is returned. + */ + ON_3fVector UnitVector() const; + + + // Description: + // Test a vector to see if it is very short + // + // Parameters: + // tiny_tol - [in] (default = ON_ZERO_TOLERANCE) a nonzero + // value used as the coordinate zero tolerance. + // + // Returns: + // ( fabs(x) <= tiny_tol && fabs(y) <= tiny_tol && fabs(z) <= tiny_tol ) + // + bool IsTiny( + double = ON_ZERO_TOLERANCE // tiny_tol + ) const; + + // Returns: + // true if vector is the zero vector. + bool IsZero() const; + + /* + Returns: + true if at lease one coordinate is not zero and no coordinates are unset or nans. + */ + bool IsNotZero() const; + + // set this vector to be perpendicular to another vector + bool PerpendicularTo( // Result is not unitized. + // returns false if input vector is zero + const ON_3fVector& + ); + + // These transform the vector in place. The transformation matrix acts on + // the left of the vector; i.e., result = transformation*vector + void Transform( + const ON_Xform& // can use ON_Xform here + ); + + void Rotate( + double, // angle in radians + const ON_3fVector& // axis of rotation + ); + + void Rotate( + double, // sin(angle) + double, // cos(angle) + const ON_3fVector& // axis of rotation + ); + + ON__UINT32 DataCRC(ON__UINT32 current_remainder) const; +}; + +ON_DECL +ON_3fVector operator*(int, const ON_3fVector&); + +ON_DECL +ON_3fVector operator*(float, const ON_3fVector&); + +ON_DECL +ON_3dVector operator*(double, const ON_3fVector&); + +/////////////////////////////////////////////////////////////// +// +// ON_3fVector utilities +// + +ON_DECL +float +ON_DotProduct( + const ON_3fVector&, + const ON_3fVector& + ); + + +ON_DECL +ON_3fVector +ON_CrossProduct( + const ON_3fVector&, + const ON_3fVector& + ); + +ON_DECL +ON_3fVector +ON_CrossProduct( // 3d cross product for old fashioned arrays + const float*, // array of 3d floats + const float* // array of 3d floats + ); + +ON_DECL +float +ON_TripleProduct( + const ON_3fVector&, + const ON_3fVector&, + const ON_3fVector& + ); + +ON_DECL +float +ON_TripleProduct( // 3d triple product for old fashioned arrays + const float*, // array of 3d floats + const float*, // array of 3d floats + const float* // array of 3d floats + ); + +ON_DECL +bool +ON_IsOrthogonalFrame( // true if X, Y, Z are nonzero and mutually perpendicular + const ON_3fVector&, // X + const ON_3fVector&, // Y + const ON_3fVector& // Z + ); + +ON_DECL +bool +ON_IsOrthonormalFrame( // true if X, Y, Z are orthogonal and unit length + const ON_3fVector&, // X + const ON_3fVector&, // Y + const ON_3fVector& // Z + ); + +ON_DECL +bool +ON_IsRightHandFrame( // true if X, Y, Z are orthonormal and right handed + const ON_3fVector&, // X + const ON_3fVector&, // Y + const ON_3fVector& // Z + ); + +#endif diff --git a/opennurbs/Include/opennurbs_freetype.h b/opennurbs/Include/opennurbs_freetype.h new file mode 100644 index 0000000..d811280 --- /dev/null +++ b/opennurbs/Include/opennurbs_freetype.h @@ -0,0 +1,122 @@ +/* +// +// Copyright (c) 1993-2017 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_FREETYPE_INC_) +#define OPENNURBS_FREETYPE_INC_ + +#if defined(OPENNURBS_FREETYPE_SUPPORT) +// Look in opennurbs_system_rumtime.h for the correct place to define OPENNURBS_FREETYPE_SUPPORT. +// Do NOT define OPENNURBS_FREETYPE_SUPPORT here or in your project setting ("makefile"). + +#if defined(ON_COMPILER_MSC) ||defined(ON_RUNTIME_WIN) +#error FreeType is not used in Windows. It does not work as well as DirectWrite based tools. +#endif + +#if defined(ON_RUNTIME_APPLE) +// Freetype is used to get single stroke font outlines. +// For everything else, use the CTFont based tools. +//#error FreeType is not used in MacOS and iOS builds. It does not work as well as CTFont based code. +#endif + +/* + Returns: + Units per em in font design units. +*/ +ON_DECL +unsigned int ON_FreeTypeGetFontUnitsPerM( + const class ON_Font* font + ); + +/* +Parameters: + font_unit_font_metrics - [in] + metrics in font units (freetype face loaded with FT_LOAD_NO_SCALE) unless + it is a "tricky" font. +*/ +ON_DECL +void ON_FreeTypeGetFontMetrics( + const class ON_Font* font, + class ON_FontMetrics& font_unit_font_metrics + ); + +/* +Parameters: + glyph_box - [out] + glyph metrics infont units (freetype face loaded with FT_LOAD_NO_SCALE) unless + it is a "tricky" font. +Returns: + 0 if box was not set. + >0: font glyph index (or other non-zero value) when box is set +*/ +ON_DECL +unsigned int ON_FreeTypeGetGlyphMetrics( + const class ON_FontGlyph* glyph, + class ON_TextBox& glyph_metrics_in_font_design_units +); + +/* +Parameters: + glyph - [in] + bSingleStrokeFont - [in] + outline - [out] + outline and metrics in font design units +*/ +ON_DECL +bool ON_FreeTypeGetGlyphOutline( + const class ON_FontGlyph* glyph, + ON_OutlineFigure::Type figure_type, + class ON_Outline& outline +); + +/* +Parameters: + glyph - [in] + glyph_index - [in] + If known for certain, pass in the glyph index. If not known, pass in 0. + figure_type - [in] + If known for certain, pass in figure_type. Otherwise, pass in ON_OutlineFigure::Type::Unset. + outline - [out] + outline and metrics in font design units +*/ +ON_DECL +bool ON_FreeTypeGetGlyphOutline( + const class ON_FontGlyph* glyph, + unsigned int glyph_index, + ON_OutlineFigure::Type figure_type, + class ON_Outline& outline +); + +/* +Description: + A wrapper for calculating parameters and calling FreeType library + functions FT_Set_Char_Size() FT_Load_Glyph(). +Parameters: + ft_face - [in] + A pointer to and FT_Face. One way to get this value is to call ON_Font::FreeTypeFace() + font_glyph_id - [in] + font glyph id +Returns: + True if glyph is available and loaded. +*/ +ON_DECL +bool ON_FreeTypeLoadGlyph( + ON__UINT_PTR ft_face, + unsigned int font_glyph_index, + bool bLoadRenderBitmap +); +#endif + + +#endif diff --git a/opennurbs/Include/opennurbs_freetype_include.h b/opennurbs/Include/opennurbs_freetype_include.h new file mode 100644 index 0000000..b976a2a --- /dev/null +++ b/opennurbs/Include/opennurbs_freetype_include.h @@ -0,0 +1,293 @@ +/* +// +// Copyright (c) 1993-2017 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +// opennurbs uses FreeType to calculate font metric, glyph metric, and glyph outline information. + +// FreeType Licensing: +// +//// Retrieved March 22, 2017 +//// https://www.freetype.org/freetype2/docs/index.html +////What is FreeType? +//// +////FreeType is a software font engine that is designed to be small, efficient, +////highly customizable, and portable while capable of producing high-quality +////output (glyph images). It can be used in graphics libraries, display servers, +////font conversion tools, text image generation tools, and many other products as well. +//// +////Note that FreeType is a font service and doesn't provide APIs to perform +////higher-level features like text layout or graphics processing +////(e.g., colored text rendering, ‘hollowing’, etc.). However, it greatly +////simplifies these tasks by providing a simple, easy to use, and uniform +////interface to access the content of font files. +//// +////FreeType is released under two open-source licenses: our own BSD-like +////FreeType License and the GNU Public License, Version 2. It can thus +////be used by any kind of projects, be they proprietary or not. +//// +////Please note that ‘FreeType’ is also called ‘FreeType 2’, to +////distinguish it from the old, deprecated ‘FreeType 1’ library, +////a predecessor no longer maintained and supported. +//// +//// http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT +//// +//// The FreeType Project LICENSE +//// ---------------------------- +//// +//// 2006-Jan-27 +//// +//// Copyright 1996-2002, 2006 by +//// David Turner, Robert Wilhelm, and Werner Lemberg +//// +//// +//// +////Introduction +////============ +//// +//// The FreeType Project is distributed in several archive packages; +//// some of them may contain, in addition to the FreeType font engine, +//// various tools and contributions which rely on, or relate to, the +//// FreeType Project. +//// +//// This license applies to all files found in such packages, and +//// which do not fall under their own explicit license. The license +//// affects thus the FreeType font engine, the test programs, +//// documentation and makefiles, at the very least. +//// +//// This license was inspired by the BSD, Artistic, and IJG +//// (Independent JPEG Group) licenses, which all encourage inclusion +//// and use of free software in commercial and freeware products +//// alike. As a consequence, its main points are that: +//// +//// o We don't promise that this software works. However, we will be +//// interested in any kind of bug reports. (`as is' distribution) +//// +//// o You can use this software for whatever you want, in parts or +//// full form, without having to pay us. (`royalty-free' usage) +//// +//// o You may not pretend that you wrote this software. If you use +//// it, or only parts of it, in a program, you must acknowledge +//// somewhere in your documentation that you have used the +//// FreeType code. (`credits') +//// +//// We specifically permit and encourage the inclusion of this +//// software, with or without modifications, in commercial products. +//// We disclaim all warranties covering The FreeType Project and +//// assume no liability related to The FreeType Project. +//// +//// +//// Finally, many people asked us for a preferred form for a +//// credit/disclaimer to use in compliance with this license. We thus +//// encourage you to use the following text: +//// +//// """ +//// Portions of this software are copyright © The FreeType +//// Project (www.freetype.org). All rights reserved. +//// """ +//// +//// Please replace with the value from the FreeType version you +//// actually use. +//// +//// +////Legal Terms +////=========== +//// +////0. Definitions +////-------------- +//// +//// Throughout this license, the terms `package', `FreeType Project', +//// and `FreeType archive' refer to the set of files originally +//// distributed by the authors (David Turner, Robert Wilhelm, and +//// Werner Lemberg) as the `FreeType Project', be they named as alpha, +//// beta or final release. +//// +//// `You' refers to the licensee, or person using the project, where +//// `using' is a generic term including compiling the project's source +//// code as well as linking it to form a `program' or `executable'. +//// This program is referred to as `a program using the FreeType +//// engine'. +//// +//// This license applies to all files distributed in the original +//// FreeType Project, including all source code, binaries and +//// documentation, unless otherwise stated in the file in its +//// original, unmodified form as distributed in the original archive. +//// If you are unsure whether or not a particular file is covered by +//// this license, you must contact us to verify this. +//// +//// The FreeType Project is copyright (C) 1996-2000 by David Turner, +//// Robert Wilhelm, and Werner Lemberg. All rights reserved except as +//// specified below. +//// +////1. No Warranty +////-------------- +//// +//// THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY +//// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +//// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +//// PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS +//// BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO +//// USE, OF THE FREETYPE PROJECT. +//// +////2. Redistribution +////----------------- +//// +//// This license grants a worldwide, royalty-free, perpetual and +//// irrevocable right and license to use, execute, perform, compile, +//// display, copy, create derivative works of, distribute and +//// sublicense the FreeType Project (in both source and object code +//// forms) and derivative works thereof for any purpose; and to +//// authorize others to exercise some or all of the rights granted +//// herein, subject to the following conditions: +//// +//// o Redistribution of source code must retain this license file +//// (`FTL.TXT') unaltered; any additions, deletions or changes to +//// the original files must be clearly indicated in accompanying +//// documentation. The copyright notices of the unaltered, +//// original files must be preserved in all copies of source +//// files. +//// +//// o Redistribution in binary form must provide a disclaimer that +//// states that the software is based in part of the work of the +//// FreeType Team, in the distribution documentation. We also +//// encourage you to put an URL to the FreeType web page in your +//// documentation, though this isn't mandatory. +//// +//// These conditions apply to any software derived from or based on +//// the FreeType Project, not just the unmodified files. If you use +//// our work, you must acknowledge us. However, no fee need be paid +//// to us. +//// +////3. Advertising +////-------------- +//// +//// Neither the FreeType authors and contributors nor you shall use +//// the name of the other for commercial, advertising, or promotional +//// purposes without specific prior written permission. +//// +//// We suggest, but do not require, that you use one or more of the +//// following phrases to refer to this software in your documentation +//// or advertising materials: `FreeType Project', `FreeType Engine', +//// `FreeType library', or `FreeType Distribution'. +//// +//// As you have not signed this license, you are not required to +//// accept it. However, as the FreeType Project is copyrighted +//// material, only this license, or another one contracted with the +//// authors, grants you the right to use, distribute, and modify it. +//// Therefore, by using, distributing, or modifying the FreeType +//// Project, you indicate that you understand and accept all the terms +//// of this license. +//// +////4. Contacts +////----------- +//// +//// There are two mailing lists related to FreeType: +//// +//// o freetype@nongnu.org +//// +//// Discusses general use and applications of FreeType, as well as +//// future and wanted additions to the library and distribution. +//// If you are looking for support, start in this list if you +//// haven't found anything to help you in the documentation. +//// +//// o freetype-devel@nongnu.org +//// +//// Discusses bugs, as well as engine internals, design issues, +//// specific licenses, porting, etc. +//// +//// Our home page can be found at +//// +//// http://www.freetype.org +//// +////--- end of FTL.TXT --- + + +#if !defined(OPENNURBS_FREETYPE_INCLUDE_INC_) +#define OPENNURBS_FREETYPE_INCLUDE_INC_ + +// NOTE: +// This header file is not included in opennurbs.h because +// FreeType 2.6.3 has deeply nested includes and uses angle brackets +// in its include files (instead of double quotes and relative paths like opennurbs), +// the directory ./freetype263/include must be in the "system" includes path. +// It is not feasable or reasonable for all projects that include opennurbs.h to have the +// freetype includes directory in the system includes path. + +#if defined(OPENNURBS_FREETYPE_SUPPORT) +// Look in opennurbs_system_rumtime.h for the correct place to define OPENNURBS_FREETYPE_SUPPORT. +// Do NOT define OPENNURBS_FREETYPE_SUPPORT here or in your project setting ("makefile"). + + +// Angle brackets are used on #include because if it fails, +// the following #include FT_FREETYPE_H will fail, but in more mysterious ways. +#if defined(OPENNURBS_EXPORTS) || defined(OPENNURBS_IMPORTS) +// WHen opennurbs is a DLL, freetype is linked as a DLL +#if defined(ON_COMPILER_MSC) +/* Windows DLL */ +#define OPENNURBS_FREETYPE_DECL __declspec(dllimport) +#elif defined(ON_COMPILER_CLANG) +/* Apple shared library */ +#define OPENNURBS_FREETYPE_DECL __attribute__ ((visibility ("default"))) +#endif +#endif + +#pragma ON_PRAGMA_WARNING_BEFORE_DIRTY_INCLUDE +// Angle brackets must be used in the ft2build.h include because +// that's what the freetype defined includes like FT_FREETYPE_H +// use and they must work. If you get a compiler (CLang) error telling you +// to use "quotes" instead, +// ignore it and include the freetype directory in the header search +// path for opennurbs_freetype.cpp. +#include +#include FT_FREETYPE_H +#pragma ON_PRAGMA_WARNING_AFTER_DIRTY_INCLUDE + +#if defined(ON_COMPILER_MSC) + +#if !defined(OPENNURBS_FREETYPE_LIB_DIR) + +#include "opennurbs_input_libsdir.h" + +#if defined(OPENNURBS_INPUT_LIBS_DIR) +// Typically, OPENNURBS_LIB_DIR is defined in opennurbs_msbuild.Cpp.props +#define OPENNURBS_FREETYPE_LIB_DIR OPENNURBS_INPUT_LIBS_DIR +#else +// Define OPENNURBS_FREETYPE_LIB_DIR to be the directory containing freetype263.lib +#error You must define OPENNURBS_FREETYPE_LIB_DIR +#endif + +#endif + +#if defined(_LIB) && !defined(OPENNURBS_IMPORTS) && !defined(OPENNURBS_EXPORTS) + +// Microsoft static library +#if defined(_MT) && !defined(_DLL) +// Microsoft dynamic library freetype263_mt.lib used multithreaded static C-runtime +#pragma message ( "Linking with freetype263_mt.lib in " OPENNURBS_PP2STR(OPENNURBS_FREETYPE_LIB_DIR) ) +#pragma comment(lib, "\"" OPENNURBS_FREETYPE_LIB_DIR "/" "freetype263_mt.lib" "\"") +#else +// Microsoft dynamic library freetype263_staticlib.lib uses DLL C-runtime +#pragma message ( "Linking with freetype263_staticlib.lib in " OPENNURBS_PP2STR(OPENNURBS_FREETYPE_LIB_DIR) ) +#pragma comment(lib, "\"" OPENNURBS_FREETYPE_LIB_DIR "/" "freetype263_staticlib.lib" "\"") +#endif + +#else +// Microsoft dynamic library freetype263.lib + freetype263.dll +#pragma message ( "Linking with freetype263.lib in " OPENNURBS_PP2STR(OPENNURBS_FREETYPE_LIB_DIR) ) +#pragma comment(lib, "\"" OPENNURBS_FREETYPE_LIB_DIR "/" "freetype263.lib" "\"") +#endif +#endif + +#endif + +#endif diff --git a/opennurbs/Include/opennurbs_fsp.h b/opennurbs/Include/opennurbs_fsp.h new file mode 100644 index 0000000..d4e0a5a --- /dev/null +++ b/opennurbs/Include/opennurbs_fsp.h @@ -0,0 +1,920 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ +#if !defined(OPENNURBS_FSP_INC_) +#define OPENNURBS_FSP_INC_ + +class ON_CLASS ON_FixedSizePoolElement +{ +private: + // ON_FixedSizePoolElement is never instantiated + ON_FixedSizePoolElement() = delete; + ~ON_FixedSizePoolElement() = delete; + ON_FixedSizePoolElement(const ON_FixedSizePoolElement&) = delete; + ON_FixedSizePoolElement operator=(const ON_FixedSizePoolElement&) = delete; + +public: + // next element - intentionally not initialized because instantiation is not permitted. + ON_FixedSizePoolElement* m_next; +}; + +class ON_CLASS ON_FixedSizePool +{ +public: + ON_FixedSizePool(); + ~ON_FixedSizePool(); + +#if defined(ON_HAS_RVALUEREF) + ON_FixedSizePool(ON_FixedSizePool&&); + ON_FixedSizePool& operator=(ON_FixedSizePool&&); +#endif + + + /* + Description: + Create a fixed size memory pool. + Parameters: + sizeof_element - [in] + number of bytes in each element. This parameter must be greater than zero. + In general, use sizeof(element type). If you pass a "raw" number as + sizeof_element, then be certain that it is the right size to insure the + fields in your elements will be properly aligned. + Remarks: + You must call Create() on an unused ON_FixedSizePool or call Destroy() + before calling create. + Returns: + True if successful and the pool can be used. + See Also + CreateForExperts(). + */ + bool Create( + size_t sizeof_element + ); + + /* + Description: + Create a fixed size memory pool. + If you have a decent estimate of how many elements you need, + CreateForExperts() is a typically a better choice. + Otherwise, Create(sizeof_element) is typically the best option. + + Parameters: + sizeof_element - [in] + number of bytes in each element. This parameter must be greater than zero. + In general, use sizeof(element type). If you pass a "raw" number as + sizeof_element, then be certain that it is the right size to insure the + fields in your elements will be properly aligned. + element_count_estimate - [in] (0 = good default) + If you know how many elements you will need, pass that number here. + It is better to slightly overestimate than to slightly underestimate. + If you do not have a good estimate, then use zero. + block_element_capacity - [in] (0 = good default) + If block_element_capacity is zero, Create() will calculate a block + size that is efficent for most applications. If you are an expert + user and want to specify the number of elements per block, + then pass the number of elements per block here. When + block_element_capacity > 0 and element_count_estimate > 0, the first + block will have a capacity of at least element_count_estimate; in this + case do not ask for extraordinarly large amounts of contiguous heap. + + Remarks: + You must call Create() on an unused ON_FixedSizePool or call Destroy() + before calling create. + Returns: + True if successful and the pool can be used. + */ + bool Create( + size_t sizeof_element, + size_t element_count_estimate, + size_t block_element_capacity + ); + + + /* + Description: + Create a fixed size memory pool. + Parameters: + sizeof_element - [in] + number of bytes in each element. This parameter must be greater than zero. + In general, use sizeof(element type). If you pass a "raw" number as + sizeof_element, then be certain that it is the right size to insure the + fields in your elements will be properly aligned. + + maximum_element_count_estimate - [in] (0 = good default) + If you have a tight upper bound on the number of elements you need + from this fixed size pool, call Create(sizeof_element) instead. + + If the description of this parameter is confusing to you, + call Create(sizeof_element) instead. + + If you have a tight upper bound on how many elements you will need, + pass that number here. When maximum_element_count_estimate > 0, the + initial memory blocks in the fixed size pool will be sized to efficiently + deliver maximum_element_count_estimate elements. + The fixed block pool can become inefficient when maximum_element_count_estimate + is a gross overestimate or a slight underestimate of the actual number of + elements that get allocated. + + minimum_block2_element_capacity - [in] (0 = good default) + If the description below is confusing, pass 0. + If maximum_element_count_estimate = 0, this parameter is ignored. + If maximum_element_count_estimate > 0 and you have an excellent choice + for a lower bound on the number of elements per block for unexpected allocations + of more than maximum_element_count_estimate elements, then pass that value for + minimum_block2_element_capacity. + + Remarks: + You must call Create() or CreateEx() on an unused ON_FixedSizePool or call Destroy() + before calling create. + Returns: + True if successful and the pool can be used. + */ + bool CreateForExperts( + size_t sizeof_element, + size_t maximum_element_count_estimate, + size_t minimum_block2_element_capacity + ); + + static size_t DefaultElementCapacityFromSizeOfElement(size_t sizeof_element); + + /* + Description: + Tool for debugging pool use when tuning block size and block capacity. + Returns: + Total operating system heap memory (in bytes) used by this ON_FixedSizePool. + Remarks: + SizeOfPool() = SizeOfAllocatedElements() + SizeOfUnusedElements(). + */ + size_t SizeOfPool() const; + + /* + Description: + Tool for debugging pool use when tuning block size and block capacity. + Returns: + Operating system heap memory (in bytes) that are used by active pool elements. + Remarks: + SizeOfPool() = SizeOfActiveElements() + SizeOfUnusedElements(). + */ + size_t SizeOfActiveElements() const; + + /* + Description: + Tool for debugging pool use when tuning block size and block capacity. + Returns: + Operating system heap memory (in bytes) that has been reserved but is not + currently used by active elements. + Remarks: + SizeOfPool() = SizeOfActiveElements() + SizeOfUnusedElements(). + */ + size_t SizeOfUnusedElements() const; + + + /* + Returns: + Size of the elements in this pool. + */ + size_t SizeofElement() const; + + /* + Returns: + A pointer to sizeof_element bytes. The memory is zeroed. + Remarks: + If multiple threads are using this pool, then use ThreadSafeAllocateElement(). + */ + void* AllocateElement(); + + /* + Returns: + A pointer to sizeof_element bytes. The values in the returned block are undefined. + Remarks: + If multiple threads are using this pool, then use ThreadSafeAllocateDirtyElement(). + */ + void* AllocateDirtyElement(); + + /* + Description: + Return an element to the pool. + Parameters: + p - [in] + A pointer returned by AllocateElement(). + It is critical that p be from this pool and that + you return a pointer no more than one time. + Remarks: + If multiple threads are using this pool, then use ThreadSafeReturnElement(). + + If you find the following remarks confusing, but you really want to use + ReturnElement(), then here are some simple guidelines. + 1) SizeofElement() must be >= 16 + 2) SizeofElement() must be a multiple of 8. + 3) Do not use FirstElement() and NextElement() to iterate through + the pool. + + If 1 to 3 don't work for you, then you need to understand the following + information before using ReturnElement(). + + ON_FixedMemoryPool uses the first sizeof(void*) bytes of the + returned element for bookkeeping purposes. Therefore, if you + are going to use ReturnElement(), then SizeofElement() must be + at least sizeof(void*). If you are using a platform that requires + pointers to be aligned on sizeof(void*) boundaries, then + SizeofElement() must be a multiple of sizeof(void*). + If you are going to use ReturnElement() and then use FirstElement() + and NextElement() to iterate through the list of elements, then you + need to set a value in the returned element to indicate that it + needs to be skipped during the iteration. This value cannot be + located in the fist sizeof(void*) bytes of the element. If the + element is a class with a vtable, you cannot call a virtual + function on a returned element because the vtable pointer is + trashed when ReturnElement() modifies the fist sizeof(void*) bytes. + */ + void ReturnElement(void* p); + + /* + Description: + Thread safe version of AllocateElement(). + Returns: + A pointer to sizeof_element bytes. The memory is zeroed. + */ + void* ThreadSafeAllocateElement(); + + /* + Description: + Thread safe version of AllocateDirtyElement(). + Returns: + A pointer to sizeof_element bytes. The values in the returned block are undefined. + */ + void* ThreadSafeAllocateDirtyElement(); + + /* + Description: + Thread safe version of ReturnElement(). + */ + void ThreadSafeReturnElement(void* p); + + /* + Description: + Return all allocated elements to the pool. No heap is freed and + the pool remains initialized and ready for AllocateElement() + to be called. + */ + void ReturnAll(); + + /* + Description: + Destroy the pool and free all the heap. The pool cannot be used again + until Create() is called. + */ + void Destroy(); + + /* + Returns: + Number of active elements. (Elements that have been returned are not active.) + */ + size_t ActiveElementCount() const; + + /* + Returns: + Total number of elements = number of active elements + number of returned elements. + */ + size_t TotalElementCount() const; + + /* + Description: + Get the i-th elment in the fixed size pool. + Parameters: + element_index - [in] + Returns: + A pointer to the element with the specified index. + The first element has element_index = 0 and is the element + returned by the first call to AllocateElement(). + The last element has element_index = ElementCount()-1. + If element_index is out of range, nullptr is returned. + Remarks: + It is faster to use ON_FixedSizePoolIterator.FirstElement() and + ON_FixedSizePoolIterator.NextElement() to iterate through the + entire list of elements. This function is relatively + efficient when there are a few large blocks in the pool + or element_index is small compared to the number of elements + in the first few blocks. + + If ReturnElement() is not used or no AllocateElement() calls + are made after any use of ReturnElement(), then the i-th + element is the one returned by the (i+1)-th call to + AllocateElement() + */ + void* Element( + size_t element_index + ) const; + + + /* + Description: + Get the fixed size pool index of an element. + Parameters: + element_pointer - [in] + Returns: + An index >= 0 and < ON_MAX_SIZE_T if the element_pointer + points to an element managed by the this fixed size pool. + ON_MAX_SIZE_T otherwise. + Remarks: + It is faster to use ON_FixedSizePoolIterator.FirstElement() and + ON_FixedSizePoolIterator.NextElement() to iterate through the + entire list of elements. This function is relatively + efficient when there are a few large blocks in the pool + or element_pointer is an element in the first few blocks. + + If ReturnElement() is not used or no AllocateElement() calls + are made after any use of ReturnElement(), then the i-th + element is the one returned by the (i+1)-th call to + AllocateElement(). + */ + size_t ElementIndex( + const void* element_pointer + ) const; + + /* + Parameters: + p - [in] + pointer to test + Returns: + True if p points to memory in this pool. + */ + bool InPool( + const void* pointer + ) const; + + /* + Description: + If you are certain that all elements in the pool (active and returned) + have an unsigned 32-bit id that is unique and increasing, then you may use + this function to find them. + Parameters: + id_offset - [in] + offset into the element where the id is stored. + id - [in] + id to search for + */ + void* ElementFromId( + size_t id_offset, + unsigned int id + ) const; + + /* + Description: + If you are certain that all elements in the pool (active and returned) + have an unsigned 32-bit id that is unique and increasing, then you may use + this function to find the maximum assigned id. + Parameters: + id_offset - [in] + offset into the element where the id is stored. + Returns: + maximum id in all elements (active and returned). + */ + unsigned int MaximumElementId( + size_t id_offset + ) const; + + bool ElementIdIsIncreasing( + size_t id_offset + ) const; + + /* + Returns: + If successful, (1 + maximum assigned id value) is returned. + Otherwise 0 is returned. + */ + unsigned int ResetElementId( + size_t id_offset, + unsigned int initial_id + ); + +public: + // Primarily used for debugging + bool IsValid() const; + +private: + friend class ON_FixedSizePoolIterator; + + void* m_first_block = nullptr; + + // ReturnElement() adds to the m_al_element stack. + // AllocateElement() will use the stack before using m_al_element_array[] + void* m_al_element_stack = nullptr; + + void* m_al_block = nullptr; // current element allocation block. + // m_al_element_array[] is in m_al_block and has length m_al_count. + void* m_al_element_array = nullptr; + size_t m_al_count = 0; + size_t m_sizeof_element = 0; + size_t m_block_element_count = 0; // block element count + + //size_t m_active_element_count = 0; // number of active elements + //size_t m_total_element_count = 0; // total number of elements (active + returned) + + unsigned int m_active_element_count = 0; // number of active elements + unsigned int m_total_element_count = 0; // total number of elements (active + returned) + +private: + // Used by The ThreadSafe...() functions and for expert users + // to use when managing memory controlled by this pool. Best + // to ingnore this unless you have a very clear idea of what + // you are doing, why you are doing it, and when you are doing it. + // Otherwise, you'll find yourself waiting forever on a nested + // access request. + friend class ON_SleepLockGuard; + ON_SleepLock m_sleep_lock; + +private: + unsigned int m_reserved0 = 0; + + +private: + // returns capacity of elements in existing block + size_t BlockElementCapacity( const void* block ) const; + + // returns number of allocated of elements in existing block + size_t BlockElementCount( const void* block ) const; + +private: + // prohibit copy construction and operator=. + ON_FixedSizePool(const ON_FixedSizePool&) = delete; + ON_FixedSizePool& operator=(const ON_FixedSizePool&) = delete; +}; + +class ON_CLASS ON_FixedSizePoolIterator +{ +public: + ON_FixedSizePoolIterator(); + ON_FixedSizePoolIterator( const class ON_FixedSizePool& fsp ); + + const class ON_FixedSizePool* FixedSizePool(); + + void Create(const ON_FixedSizePool* fsp); + + /* + Description: + Get the first element when iterating through the list of elements. + Parameters: + element_index - [in] + If you use the version of FirstElement() that has an + element_index parameter, then the iteration begins at + that element. + Example: + The loop will iteratate through all the elements returned from + AllocateElement(), including any that have be returned to the pool + using ReturnElement(). + + // iterate through all elements in the pool + // This iteration will go through TotalElements() items. + for ( void* p = FirstElement(); 0 != p; p = NextElement() ) + { + // If you are not using ReturnElement(), then you may process + // "p" immediately. If you have used ReturnElement(), then you + // must check some value in p located after the first sizeof(void*) + // bytes to see if p is active. + if ( p is not active ) + continue; + + ... process p + } + + Returns: + The first element when iterating through the list of elements. + Remarks: + FirstElement() and NextElement() will return elements that have + been returned to the pool using ReturnElement(). If you use + ReturnElement(), then be sure to mark the element so it can be + identified and skipped. + + Do not make any calls to FirstBlock() or NextBlock() when using + FirstElement() and NextElement() to iteratate through elements. + */ + void* FirstElement(); + void* FirstElement( size_t element_index ); + + /* + Description: + Get the next element when iterating through the list of elements. + If FirstElement() is not called, then the first call to + NextElement() returns the first element. + Example: + See the FirstElement() documentation. + Returns: + The next element when iterating through the list of elements. + Remarks: + FirstElement() and NextElement() will return elements that have + been returned to the pool using ReturnElement(). If you use + ReturnElement(), then be sure to mark the element so it can be + identified and skipped. + + Do not make any calls to FirstBlock() or NextBlock() when using + FirstElement() and NextElement() to iteratate through elements. + */ + void* NextElement(); + + /* + Returns: + The most recently returned value from a call to FirstElement() + or NextElement(). + Remarks: + Do not make any calls to FirstBlock() or NextBlock() when using + FirstElement() and NextElement() to iteratate through elements. + */ + void* CurrentElement() const; + + /* + Description: + Sets the state of the iterator to the initial state that + exists after construction. This is useful if the iterator + has been used the get one or more elements and then + the referenced fixed size pool is modified or code wants + to begin iteration again a used a call to NextElement() + to return the first element. + */ + void Reset(); + + + /* + Description: + Get a pointer to the first element in the first block. + Parameters: + block_element_count - [out] (can be null) + If not null, the number of elements allocated from the + first block is returned in block_element_count. + Note that if you have used ReturnElement(), some + of these elemements may have been returned. + Example: + The loop will iteratate through all the blocks. + + // iterate through all blocks in the pool + size_t block_element_count = 0; + for ( void* p = FirstBlock(&block_element_count); + 0 != p; + p = NextBlock(&block_element_count) + ) + { + ElementType* e = (ElementType*)p; + for ( size_t i = 0; + i < block_element_count; + i++, e = ((const char*)e) + SizeofElement() + ) + { + ... + } + } + + Returns: + The first block when iterating the list of blocks. + Remarks: + The heap for a fixed size memory pool is simply a linked + list of blocks. FirstBlock() and NextBlock() can be used + to iterate through the list of blocks. + + Do not make any calls to FirstElement() or NextElement() when using + FirstBlock() and NextBlock() to iteratate through blocks. + */ + void* FirstBlock( size_t* block_element_count ); + + /* + Description: + Get the next block when iterating through the blocks. + Parameters: + block_element_count - [out] (can be null) + If not null, the number of elements allocated from the + block is returned in block_element_count. Note that if + you have used ReturnElement(), some of these elemements + may have been returned. + Example: + See the FirstBlock() documentation. + Returns: + The next block when iterating through the blocks. + Remarks: + Do not make any calls to FirstElement() or NextElement() when using + FirstBlock() and NextBlock() to iteratate through blocks. + */ + void* NextBlock( size_t* block_element_count ); + +private: + const class ON_FixedSizePool* m_fsp; + void* m_it_block; + void* m_it_element; +}; + + +template class ON_SimpleFixedSizePool : private ON_FixedSizePool +{ +public: + // construction //////////////////////////////////////////////////////// + + ON_SimpleFixedSizePool(); + ~ON_SimpleFixedSizePool(); + + /* + Description: + Create a fixed size memory pool. + Parameters: + element_count_estimate - [in] (0 = good default) + If you know how many elements you will need, pass that number here. + It is better to slightly overestimate than to slightly underestimate. + If you do not have a good estimate, then use zero. + block_element_count - [in] (0 = good default) + If block_element_count is zero, Create() will calculate a block + size that is efficent for most applications. If you are an expert + user and want to specify the number of blocks, then pass the number + of elements per block here. When block_element_count > 0 and + element_count_estimate > 0, the first block will be large enough + element_count_estimate*sizeof(T) bytes; in this case do not + ask for extraordinarly large amounts of contiguous heap. + Remarks: + You must call Create() on an unused ON_FixedSizePool or call Destroy() + before calling create. + Returns: + True if successful and the pool can be used. + */ + bool Create( + size_t element_count_estimate, + size_t block_element_count + ); + + /* + Returns: + Size of the elements in this pool. + */ + size_t SizeofElement() const; + + /* + Returns: + A pointer to sizeof_element bytes. The memory is zeroed. + */ + T* AllocateElement(); + + /* + Description: + Return an element to the pool. + Parameters: + p - [in] + A pointer returned by AllocateElement(). + It is critical that p be from this pool and that + you return a pointer no more than one time. + Remarks: + If you find the following remarks confusing, but you really want to use + ReturnElement(), then here are some simple guidelines. + 1) SizeofElement() must be >= 16 + 2) SizeofElement() must be a multiple of 8. + 3) Do not use FirstElement() and NextElement() to iterate through + the pool. + + If 1 to 3 don't work for you, then you need to understand the following + information before using ReturnElement(). + + ON_FixedMemoryPool uses the first sizeof(void*) bytes of the + returned element for bookkeeping purposes. Therefore, if you + are going to use ReturnElement(), then SizeofElement() must be + at least sizeof(void*). If you are using a platform that requires + pointers to be aligned on sizeof(void*) boundaries, then + SizeofElement() must be a multiple of sizeof(void*). + If you are going to use ReturnElement() and then use FirstElement() + and NextElement() to iterate through the list of elements, then you + need to set a value in the returned element to indicate that it + needs to be skipped during the iteration. This value cannot be + located in the fist sizeof(void*) bytes of the element. If the + element is a class with a vtable, you cannot call a virtual + function on a returned element because the vtable pointer is + trashed when ReturnElement() modifies the fist sizeof(void*) bytes. + */ + void ReturnElement(T* p); + + /* + Description: + Return all allocated elements to the pool. No heap is freed and + the pool remains initialized and ready for AllocateElement() + to be called. + */ + void ReturnAll(); + + /* + Description: + Destroy the pool and free all the heap. The pool cannot be used again + until Create() is called. + */ + void Destroy(); + + /* + Returns: + Number of active elements. (Elements that have been returned are not active.) + */ + size_t ActiveElementCount() const; + + /* + Returns: + Total number of elements = number of active elements + number of returned elements. + */ + size_t TotalElementCount() const; + + /* + Description: + Get the i-th elment in the pool. + Parameters: + element_index - [in] + Returns: + A pointer to the i-th element. The first element has index = 0 + and is the element returned by the first call to AllocateElement(). + The last element has index = ElementCount()-1. + If i is out of range, null is returned. + Remarks: + It is faster to use FirstElement() and NextElement() to iterate + through the entire list of elements. This function is relatively + efficient when there are a few large blocks in the pool + or element_index is small compared to the number of elements + in the first few blocks. + + If ReturnElement() is not used or AllocateElement() calls to + are made after any use of ReturnElement(), then the i-th + element is the one returned by the (i+1)-th call to + AllocateElement(). + */ + T* Element(size_t element_index) const; + + size_t ElementIndex( + T* + ) const; + +private: + // prohibit copy construction and operator=. + ON_SimpleFixedSizePool(const ON_SimpleFixedSizePool&); + ON_SimpleFixedSizePool& operator=(const ON_SimpleFixedSizePool&); +}; + +template class ON_SimpleFixedSizePoolIterator : private ON_FixedSizePoolIterator +{ +public: + ON_SimpleFixedSizePoolIterator( const class ON_SimpleFixedSizePool& fsp ); + ON_SimpleFixedSizePoolIterator(const class ON_SimpleFixedSizePoolIterator&); + + /* + Description: + Get the first element when iterating through the list of elements. + Parameters: + element_index - [in] + If you use the version of FirstElement() that has an + element_index parameter, then the iteration begins at + that element. + Example: + The loop will iteratate through all the elements returned from + AllocateElement(), including any that have be returned to the pool + using ReturnElement(). + + // iterate through all elements in the pool + // This iteration will go through TotalElements() items. + for ( void* p = FirstElement(); 0 != p; p = NextElement() ) + { + // If you are not using ReturnElement(), then you may process + // "p" immediately. If you have used ReturnElement(), then you + // must check some value in p located after the first sizeof(void*) + // bytes to see if p is active. + if ( p is not active ) + continue; + + ... process p + } + + Returns: + The first element when iterating through the list of elements. + Remarks: + FirstElement() and NextElement() will return elements that have + been returned to the pool using ReturnElement(). If you use + ReturnElement(), then be sure to mark the element so it can be + identified and skipped. + + Do not make any calls to FirstBlock() or NextBlock() when using + FirstElement() and NextElement() to iteratate through elements. + */ + T* FirstElement(); + T* FirstElement( size_t element_index ); + + /* + Description: + Get the next element when iterating through the list of elements. + If FirstElement() is not called, then the first call to + NextElement() returns the first element. + Example: + See the FirstElement() documentation. + Returns: + The next element when iterating through the list of elements. + Remarks: + FirstElement() and NextElement() will return elements that have + been returned to the pool using ReturnElement(). If you use + ReturnElement(), then be sure to mark the element so it can be + identified and skipped. + + Do not make any calls to FirstBlock() or NextBlock() when using + FirstElement() and NextElement() to iteratate through elements. + */ + T* NextElement(); + + /* + Returns: + The most recently returned value from a call to FirstElement() + or NextElement(). + Remarks: + Do not make any calls to FirstBlock() or NextBlock() when using + FirstElement() and NextElement() to iteratate through elements. + */ + T* CurrentElement(); + + /* + Description: + Sets the state of the iterator to the initail state that + exists after construction. This is useful if the iterator + has been used the get one or more elements and then + the referenced fixed size pool is modified or code wants + to begin iteration again a used a call to NextElement() + to return the first element. + */ + void Reset(); + + + /* + Description: + Get a pointer to the first element in the first block. + Parameters: + block_element_count - [out] (can be null) + If not null, the number of elements allocated from the + first block is returned in block_element_count. + Note that if you have used ReturnElement(), some + of these elemements may have been returned. + Example: + The loop will iteratate through all the blocks. + + // iterate through all blocks in the pool + size_t block_element_count = 0; + for ( void* p = FirstBlock(&block_element_count); + 0 != p; + p = NextBlock(&block_element_count) + ) + { + ElementType* e = (ElementType*)p; + for ( size_t i = 0; + i < block_element_count; + i++, e = ((const char*)e) + SizeofElement() + ) + { + ... + } + } + + Returns: + The first block when iterating the list of blocks. + Remarks: + The heap for a fixed size memory pool is simply a linked + list of blocks. FirstBlock() and NextBlock() can be used + to iterate through the list of blocks. + + Do not make any calls to FirstElement() or NextElement() when using + FirstBlock() and NextBlock() to iteratate through blocks. + */ + T* FirstBlock( size_t* block_element_count ); + + /* + Description: + Get the next block when iterating through the blocks. + Parameters: + block_element_count - [out] (can be null) + If not null, the number of elements allocated from the + block is returned in block_element_count. Note that if + you have used ReturnElement(), some of these elemements + may have been returned. + Example: + See the FirstBlock() documentation. + Returns: + The next block when iterating through the blocks. + Remarks: + Do not make any calls to FirstElement() or NextElement() when using + FirstBlock() and NextBlock() to iteratate through blocks. + */ + T* NextBlock( size_t* block_element_count ); + +private: + // no implementation (you can use a copy construtor) + class ON_SimpleFixedSizePoolIterator& operator=(const class ON_SimpleFixedSizePoolIterator&); +}; + +// definitions of the template functions are in a different file +// so that Microsoft's developer studio's autocomplete utility +// will work on the template functions. +#include "opennurbs_fsp_defs.h" + +#endif + diff --git a/opennurbs/Include/opennurbs_fsp_defs.h b/opennurbs/Include/opennurbs_fsp_defs.h new file mode 100644 index 0000000..7c9406d --- /dev/null +++ b/opennurbs/Include/opennurbs_fsp_defs.h @@ -0,0 +1,148 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_FSP_DEFS_INC_) +#define ON_FSP_DEFS_INC_ + +template +ON_SimpleFixedSizePool::ON_SimpleFixedSizePool() +: ON_FixedSizePool() +{} + +template +ON_SimpleFixedSizePool::~ON_SimpleFixedSizePool() +{ + ON_FixedSizePool::Destroy(); +} + +template +bool ON_SimpleFixedSizePool::Create( + size_t element_count_estimate, + size_t block_element_count + ) +{ + return ON_FixedSizePool::Create(sizeof(T),element_count_estimate,block_element_count); +} + +template +size_t ON_SimpleFixedSizePool::SizeofElement() const +{ + return ON_FixedSizePool::SizeofElement(); +} + +template +T* ON_SimpleFixedSizePool::AllocateElement() +{ + return (T *)ON_FixedSizePool::AllocateElement(); +} + +template +void ON_SimpleFixedSizePool::ReturnElement(T* p) +{ + ON_FixedSizePool::ReturnElement(p); +} + +template +void ON_SimpleFixedSizePool::ReturnAll() +{ + ON_FixedSizePool::ReturnAll(); +} + +template +void ON_SimpleFixedSizePool::Destroy() +{ + ON_FixedSizePool::Destroy(); +} + +template +size_t ON_SimpleFixedSizePool::ActiveElementCount() const +{ + return ON_FixedSizePool::ActiveElementCount(); +} + +template +size_t ON_SimpleFixedSizePool::TotalElementCount() const +{ + return ON_FixedSizePool::TotalElementCount(); +} + +template +T* ON_SimpleFixedSizePool::Element(size_t element_index) const +{ + return (T *)ON_FixedSizePool::Element(element_index); +} + +template +size_t ON_SimpleFixedSizePool::ElementIndex(T* element_ptr) const +{ + return ON_FixedSizePool::ElementIndex(element_ptr); +} + +template +ON_SimpleFixedSizePoolIterator::ON_SimpleFixedSizePoolIterator(const class ON_SimpleFixedSizePool& fsp) +: ON_FixedSizePoolIterator((ON_FixedSizePool&)fsp) +{} + +template +ON_SimpleFixedSizePoolIterator::ON_SimpleFixedSizePoolIterator(const class ON_SimpleFixedSizePoolIterator& fsp_it) +: ON_FixedSizePoolIterator(fsp_it) +{} + +template +T* ON_SimpleFixedSizePoolIterator::FirstElement() +{ + return (T *)ON_FixedSizePoolIterator::FirstElement(); +} + + +template +T* ON_SimpleFixedSizePoolIterator::FirstElement(size_t element_index) +{ + return (T *)ON_FixedSizePoolIterator::FirstElement(element_index); +} + +template +T* ON_SimpleFixedSizePoolIterator::NextElement() +{ + return (T *)ON_FixedSizePoolIterator::NextElement(); +} + +template +T* ON_SimpleFixedSizePoolIterator::CurrentElement() +{ + return (T *)ON_FixedSizePoolIterator::CurrentElement(); +} + + +template +void ON_SimpleFixedSizePoolIterator::Reset() +{ + ON_FixedSizePoolIterator::Reset(); +} + +template +T* ON_SimpleFixedSizePoolIterator::FirstBlock( size_t* block_element_count ) +{ + return (T *)ON_FixedSizePoolIterator::FirstBlock(block_element_count); +} + +template +T* ON_SimpleFixedSizePoolIterator::NextBlock( size_t* block_element_count ) +{ + return (T *)ON_FixedSizePoolIterator::NextBlock(block_element_count); +} + +#endif diff --git a/opennurbs/Include/opennurbs_function_list.h b/opennurbs/Include/opennurbs_function_list.h new file mode 100644 index 0000000..abc2322 --- /dev/null +++ b/opennurbs/Include/opennurbs_function_list.h @@ -0,0 +1,132 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2013 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + + +#if !defined(OPENNURBS_FUNCTION_LIST_INC_) +#define OPENNURBS_FUNCTION_LIST_INC_ + +class ON_CLASS ON_FunctionList +{ +public: + /* + Parameters: + function_count_estimate - [in] + An estimate of the maximum number of functions that will + be in the list at any one time. Pass 0 if you don't know. + */ + ON_FunctionList( + size_t function_count_estimate + ); + + ~ON_FunctionList(); + + /* + Description: + Unconditionally add a function to the list. + Parameters: + function - [in] + A function that takes a single ON__UINT_PTR parameter. + function_parameter - [in] + Returns: + 0: list in use + 1: function added + 2: invalid input + */ + unsigned int AddFunction( + void (*function)(ON__UINT_PTR), + ON__UINT_PTR function_parameter + ); + + /* + Returns: + 0: list in use + 1: function removed + 2: matching function not in the list + */ + unsigned int RemoveFunction( + void (*function)(ON__UINT_PTR) + ); + + /* + Returns: + 0: list in use + 1: function removed + 2: matching function not in the list + */ + unsigned int RemoveFunction( + void (*function)(ON__UINT_PTR), + ON__UINT_PTR function_parameter + ); + + /* + Returns: + 0: Matching function and parameter are not in the list. + 1: Matching function and parameter are in the list. + 2: list in use + */ + unsigned int IsInList( + void (*function)(ON__UINT_PTR), + ON__UINT_PTR function_parameter + ) const; + + /* + Returns: + 0: list in use + 1: Matching function is in the list. + 2: Matching function is not in the list. + */ + unsigned int IsInList( + void (*function)(ON__UINT_PTR) + ) const; + + /* + Returns: + 0: list in use + 1: list was emptied + */ + bool EmptyList(); + + /* + Description: + Call all the functions in the function list. + Parameters: + bFirstToLast - [in] + true - function are called in the order added + false - functions are called in the reverse order added + Returns: + True if the functions were called or the list is empty. + False if the list is in use. + */ + bool CallFunctions( + bool bFirstToLast + ); + + /* + Returns: + True if the list is in use. + */ + bool InUse() const; + + unsigned int FunctionCount() const; + +private: + ON_FixedSizePool m_fsp; + void* m_head = nullptr; + void* m_tail = nullptr; + mutable ON_Lock m_lock; +}; + +#endif diff --git a/opennurbs/Include/opennurbs_geometry.h b/opennurbs/Include/opennurbs_geometry.h new file mode 100644 index 0000000..16f3279 --- /dev/null +++ b/opennurbs/Include/opennurbs_geometry.h @@ -0,0 +1,398 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +//////////////////////////////////////////////////////////////// +// +// virtual base class for all geomtric objects +// +//////////////////////////////////////////////////////////////// + +#if !defined(OPENNURBS_GEOMETRY_INC_) +#define OPENNURBS_GEOMETRY_INC_ + +class ON_Brep; + +//////////////////////////////////////////////////////////////// + +// Description: +// Base class for all geometry classes that must +// provide runtime class id. Provides interface +// for common geometric operations like finding bounding +// boxes and transforming. +// +class ON_CLASS ON_Geometry : public ON_Object +{ + // Any object derived from ON_Geometry should have a + // ON_OBJECT_DECLARE(ON_...); + // as the last line of its class definition and a + // ON_OBJECT_IMPLEMENT( ON_..., ON_baseclass ); + // in a .cpp file. + // + // See the definition of ON_Object for details. + ON_OBJECT_DECLARE(ON_Geometry); + +public: + const static ON_Geometry Unset; + +public: + ON_Geometry() = default; + ~ON_Geometry() = default; + ON_Geometry(const ON_Geometry&) = default; + ON_Geometry& operator=(const ON_Geometry&) = default; + +#if defined(ON_HAS_RVALUEREF) + // rvalue copy constructor + ON_Geometry( ON_Geometry&& ) ON_NOEXCEPT; + + // The rvalue assignment operator calls ON_Object::operator=(ON_Object&&) + // which could throw exceptions. See the implementation of + // ON_Object::operator=(ON_Object&&) for details. + ON_Geometry& operator=( ON_Geometry&& ); +#endif + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + // Description: + // Get object's 3d axis aligned bounding box. + // Returns: + // 3d bounding box. + // Remarks: + // Uses virtual GetBBox() function to calculate the result. + ON_BoundingBox BoundingBox() const; + + // Description: + // Get object's 3d axis aligned bounding box or the + // union of the input box with the object's bounding box. + // Parameters: + // bbox - [in/out] 3d axis aligned bounding box + // bGrowBox - [in] (default=false) + // If true, then the union of the input bbox and the + // object's bounding box is returned in bbox. + // If false, the object's bounding box is returned in bbox. + // Returns: + // true if object has bounding box and calculation was successful. + // Remarks: + // Uses virtual GetBBox() function to calculate the result. + bool GetBoundingBox( + ON_BoundingBox& bbox, + bool bGrowBox = false + ) const; + + // Description: + // Get corners of object's 3d axis aligned bounding box + // or the union of the input box with the object's bounding + // box. + // Parameters: + // bbox_min - [in/out] minimum corner of the 3d bounding box + // bbox_max - [in/out] maximum corner of the 3d bounding box + // bGrowBox - [in] (default=false) + // If true, then the union of the input bbox and the + // object's bounding box is returned. + // If false, the object's bounding box is returned. + // Returns: + // true if successful. + bool GetBoundingBox( + ON_3dPoint& bbox_min, + ON_3dPoint& bbox_max, + bool bGrowBox = false + ) const; + + // Description: + // Rotates the object about the specified axis. A positive + // rotation angle results in a counter-clockwise rotation + // about the axis (right hand rule). + // Parameters: + // sin_angle - [in] sine of rotation angle + // cos_angle - [in] sine of rotation angle + // rotation_axis - [in] direction of the axis of rotation + // rotation_center - [in] point on the axis of rotation + // Returns: + // true if object successfully rotated + // Remarks: + // Uses virtual Transform() function to calculate the result. + bool Rotate( + double sin_angle, + double cos_angle, + const ON_3dVector& rotation_axis, + const ON_3dPoint& rotation_center + ); + + // Description: + // Rotates the object about the specified axis. A positive + // rotation angle results in a counter-clockwise rotation + // about the axis (right hand rule). + // Parameters: + // rotation_angle - [in] angle of rotation in radians + // rotation_axis - [in] direction of the axis of rotation + // rotation_center - [in] point on the axis of rotation + // Returns: + // true if object successfully rotated + // Remarks: + // Uses virtual Transform() function to calculate the result. + bool Rotate( + double rotation_angle, + const ON_3dVector& rotation_axis, + const ON_3dPoint& rotation_center + ); + + // Description: + // Translates the object along the specified vector. + // Parameters: + // translation_vector - [in] translation vector + // Returns: + // true if object successfully translated + // Remarks: + // Uses virtual Transform() function to calculate the result. + bool Translate( + const ON_3dVector& translation_vector + ); + + // Description: + // Scales the object by the specified facotor. The scale is + // centered at the origin. + // Parameters: + // scale_factor - [in] scale factor + // Returns: + // true if object successfully scaled + // Remarks: + // Uses virtual Transform() function to calculate the result. + bool Scale( + double scale_factor + ); + + // Description: + // Dimension of the object. + // Returns: + // Dimension of the object. + // Remarks: + // The dimension is typically three. For parameter space trimming + // curves the dimension is two. In rare cases the dimension can + // be one or greater than three. + virtual int Dimension() const; + + // Description: + // This is the virtual function that actually calculates axis + // aligned bounding boxes. + // Parameters: + // boxmin - [in/out] array of Dimension() doubles + // boxmax - [in/out] array of Dimension() doubles + // bGrowBox - [in] (default=false) + // If true, then the union of the input bbox and the + // object's bounding box is returned in bbox. + // If false, the object's bounding box is returned in bbox. + // Returns: + // true if object has bounding box and calculation was successful + virtual bool GetBBox( + double* boxmin, + double* boxmax, + bool bGrowBox = false + ) const; + + /* + Description: + Get tight bounding box. + Parameters: + tight_bbox - [in/out] tight bounding box + bGrowBox -[in] (default=false) + If true and the input tight_bbox is valid, then returned + tight_bbox is the union of the input tight_bbox and the + curve's tight bounding box. + xform -[in] (default=nullptr) + If not nullptr, the tight bounding box of the transformed + geometry is calculated. The geometry is not modified. + Returns: + True if a valid tight_bbox is returned. + Remarks: + In general, GetTightBoundingBox is slower that BoundingBox, + especially when xform is not null. + */ + virtual bool GetTightBoundingBox( + class ON_BoundingBox& tight_bbox, + bool bGrowBox = false, + const class ON_Xform* xform = nullptr + ) const; + + // Description: + // Some objects cache bounding box information. + // If you modify an object, then call ClearBoundingBox() + // to inform the object that any cached bounding boxes + // are invalid. + // + // Remarks: + // Generally, ClearBoundingBox() overrides + // simply invalidate a cached bounding box and then wait + // for a call to GetBBox() before recomputing the bounding box. + // + // The default implementation does nothing. + virtual void ClearBoundingBox(); + + /* + Description: + Transforms the object. + + Parameters: + xform - [in] transformation to apply to object. + If xform.IsSimilarity() is zero, then you may + want to call MakeSquishy() before calling + Transform. + + Remarks: + When overriding this function, be sure to include a call + to ON_Object::TransformUserData() which takes care of + transforming any ON_UserData that may be attached to + the object. + + See Also: + ON_Geometry::IsDeformable(); + + Remarks: + Classes derived from ON_Geometry should call + ON_Geometry::Transform() to handle user data + transformations and then transform their + definition. + */ + virtual + bool Transform( + const ON_Xform& xform + ); + + /* + Returns: + True if object can be accuratly modified with + "squishy" transformations like projections, + shears, an non-uniform scaling. + See Also: + ON_Geometry::MakeDeformable(); + */ + virtual + bool IsDeformable() const; + + /* + Description: + If possible, converts the object into a form that can + be accuratly modified with "squishy" transformations + like projections, shears, an non-uniform scaling. + Returns: + False if object cannot be converted to a deformable + object. True if object was already deformable or + was converted into a deformable object. + See Also: + ON_Geometry::IsDeformable(); + */ + virtual + bool MakeDeformable(); + + // Description: + // Swaps object coordinate values with indices i and j. + // + // Parameters: + // i - [in] coordinate index + // j - [in] coordinate index + // + // Remarks: + // The default implementation uses the virtual Transform() + // function to calculate the result. If you are creating + // an object where Transform() is slow, coordinate swapping + // will be frequently used, and coordinate swapping can + // be quickly accomplished, then override this function. + // + // Example: + // + // ON_Point point(7,8,9); + // point.SwapCoordinates(0,2); + // // point = (9,8,7) + virtual + bool SwapCoordinates( + int i, + int j + ); + + + + /* + Description: + Query an object to see if it has an ON_Brep form. + Result: + Returns true if the virtual ON_Geometry::BrepForm can compute + an ON_Brep representation of this object. + Remarks: + The default implementation of ON_Geometry::BrepForm returns + false. + See Also + ON_Geometry::BrepForm + */ + virtual + bool HasBrepForm() const; + + /* + Description: + If possible, BrepForm() creates a brep form of the + ON_Geometry. + Parameters: + brep - [in] if not nullptr, brep is used to store the brep + form of the geometry. + Result: + Returns a pointer to on ON_Brep or nullptr. If the brep + parameter is not nullptr, then brep is returned if the + geometry has a brep form and nullptr is returned if the + geometry does not have a brep form. + Remarks: + The caller is responsible for managing the brep memory. + See Also + ON_Geometry::HasBrepForm + */ + virtual + class ON_Brep* BrepForm( + class ON_Brep* brep = nullptr + ) const; + + /* + Description: + If this piece of geometry is a component in something + larger, like an ON_BrepEdge in an ON_Brep, then this + function returns the component index. + Returns: + This object's component index. If this object is + not a sub-piece of a larger geometric entity, then + the returned index has + m_type = ON_COMPONENT_INDEX::invalid_type + and + m_index = -1. + */ + virtual + ON_COMPONENT_INDEX ComponentIndex() const; + + /* + Description: + Evaluate the location of a point from the object + reference. + Parameters: + objref - [in] + point - [out] + If the evaluation cannot be performed, ON_3dPoint::UnsetPoint + is returned. + Returns: + True if successful. + */ + virtual + bool EvaluatePoint( + const class ON_ObjRef& objref, + ON_3dPoint& P + ) const; +}; + +#endif + diff --git a/opennurbs/Include/opennurbs_gl.h b/opennurbs/Include/opennurbs_gl.h new file mode 100644 index 0000000..3647e6e --- /dev/null +++ b/opennurbs/Include/opennurbs_gl.h @@ -0,0 +1,246 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2011 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +//////////////////////////////////////////////////////////////// +// +// Definitions of ON_GL() functions that demonstrate how to +// use GL to display OpenNURBS objects. +// +//////////////////////////////////////////////////////////////// + +#include "opennurbs.h" + +#if defined(ON_COMPILER_MSC) + +// Tested compilers: +// Microsoft Developer Studio 6.0 +// Microsoft Visual Studio 2005 +// Support for other Windows compilers is not available. + +// Windows Open GL files require windows.h to be included before the +// Open GL header files. +#pragma ON_PRAGMA_WARNING_PUSH +#include +#include // Open GL basic definitions +#include // Open GL utilities (for GL NURBS stuff) +#pragma ON_PRAGMA_WARNING_POP + +#elif defined(ON_COMPILER_CLANG) + +// Tested compilers: +// Apple Xcode 2.4.1 +// Support for other Apple compilers is not available. +#include // Open GL auxillary functions + +#else + +// Unsupported compiler: +// Support for other compilers is not available +#include // Open GL basic definitions +#include // Open GL utilities (for GL NURBS stuff) + +#endif + + +#if !defined(OPENNURBS_GL_INC_) +#define OPENNURBS_GL_INC_ + + +// Use ON_GL( const ON_Point, ...) to render single points. +void ON_GL( + const ON_Point& + ); + +// Use ON_GL( const ON_PointCloud, ...) to render Rhino point sets. +void ON_GL( + const ON_PointCloud& + ); + +// Use ON_GL( const ON_Mesh&, ...) to render OpenNURBS meshes. +void ON_GL( + const ON_Mesh& + ); + +// Use ON_GL( const ON_Brep&, ...) to render OpenNURBS b-reps. +void ON_GL( + const ON_Brep&, + GLUnurbsObj* + ); + +// must be bracketed by calls to glBegin(GL_POINTS) / glEnd() +void ON_GL( + const ON_3dPoint& + ); + +void ON_GL( + const ON_Curve&, // + GLUnurbsObj*, // created with gluNewNurbsRenderer + GLenum = 0, // type of curve (if 0, type is automatically set) + double[][4] = nullptr // optional transformation applied to curve + ); + +// must be bracketed by calls to gluBeginSurface( nobj )/gluEndSurface( nobj ) +void ON_GL( + const ON_Surface&, // + GLUnurbsObj* // created with gluNewNurbsRenderer + ); + +// Use ON_GL( const ON_NurbsCurve&,...) in place of +// gluNurbsCurve(). See your system's gluNurbsCurve() documentation +// for details. In particular, for 3d curves the call to +// ON_GL( const ON_NurbsCurve&, nobj,...) should appear inside +// of a gluBeginCurve( nobj )/gluEndCurve( nobj ) pair. +// Generally, the GL "type" should be set using the formula +// ON_NurbsCurve:IsRational() +// ? GL_MAP1_VERTEX_4 +// : GL_MAP1_VERTEX_3; +void ON_GL( + const ON_NurbsCurve&, // + GLUnurbsObj*, // created with gluNewNurbsRenderer + GLenum = 0, // type of curve (if 0, type is automatically set) + int = 1, // bPermitKnotScaling - If true, curve knots may + // be rescaled to avoid knot vectors GL cannot handle. + double* = nullptr, // knot_scale[2] - If not nullptr and bPermitKnotScaling, + // the scaling applied to the knot vector is + // returned here. + double[][4] = nullptr // optional transformation applied to curve + ); + +void ON_GL( // low level NURBS curve renderer + int, int, int, int, // dim, is_rat, cv_count, order + const double*, // knot_vector[] + int, // cv_stride + const double*, // cv + GLUnurbsObj*, // created with gluNewNurbsRenderer + GLenum = 0, // type of curve (if 0, type is automatically set) + int = 1, // bPermitKnotScaling - If true, curve knots may + // be rescaled to avoid knot vectors GL cannot handle. + double* = nullptr, // knot_scale[2] - If not nullptr and bPermitKnotScaling, + // the scaling applied to the knot vector is + // returned here. + double[][4] = nullptr // optional transformation applied to curve + ); + + +// Use ON_GL( const ON_NurbsSurface&,...) in place of +// gluNurbsSurface(). See your system's gluNurbsSurface() documentation +// for details. In particular, the call to +// ON_GL( const ON_NurbsSurface&, nobj, ...) should appear inside +// of a gluBeginSurface( nobj )/gluEndSurface( nobj ) pair. +// Generally, the GL "type" should be set using the formula +// ON_NurbsSurface:IsRational() +// ? GL_MAP2_VERTEX_4 +// : GL_MAP2_VERTEX_3; +void ON_GL( + const ON_NurbsSurface&, // + GLUnurbsObj*, // created with gluNewNurbsRenderer + GLenum = 0, // type of surface + // (if 0, type is automatically set) + int = 1, // bPermitKnotScaling - If true, surface knots may + // be rescaled to avoid knot vectors GL cannot handle. + double* = nullptr, // knot_scale0[2] - If not nullptr and bPermitKnotScaling, + // the scaleing applied to the first parameter is + // returned here. + double* = nullptr // knot_scale0[2] - If not nullptr and bPermitKnotScaling, + // the scaleing applied to the second parameter is + // returned here. + ); + + +// Use ON_GL( const ON_BrepFace&, nobj ) to render +// the trimmed NURBS surface that defines a ON_Brep face's geometry. +// The call to ON_GL( const ON_BrepFace&, nobj ) should +// appear inside of a gluBeginSurface( nobj )/gluEndSurface( nobj ) +// pair. +void ON_GL( + const ON_BrepFace&, // + GLUnurbsObj* // created with gluNewNurbsRenderer + ); + +// Use ON_GL( const ON_Color ...) to set GL color to OpenNURBS color +void ON_GL( const ON_Color&, + GLfloat[4] + ); +void ON_GL( const ON_Color&, + double, // alpha + GLfloat[4] + ); + +// Use ON_GL( const ON_Material ...) to set GL material to OpenNURBS material +void ON_GL( + const ON_Material& + ); + +void ON_GL( + const ON_Material* // pass nullptr to get OpenNURBS's default material + ); + +// Use ON_GL( const ON_Light, ...) to add OpenNURBS spotlights to +// GL lighting model +void ON_GL( + const ON_Light*, // pass nullptr to disable the light + GLenum // GL_LIGHTi where 0 <= i <= GL_MAX_LIGHTS + // See glLight*() documentation for details + ); +void ON_GL( + const ON_Light&, + GLenum // GL_LIGHTi where 0 <= i <= GL_MAX_LIGHTS + // See glLight*() documentation for details + ); + +////////////////////////////////////////////////////////////////////////// +// Use ON_GL( ON_Viewport& ... ) to set the GL projections to match +// those used in the OpenNURBS viewport. + +//////////// +// +// Use ON_GL( ON_Viewport&, in, int, int, int ) to specify the size of the +// GL window and loads the GL projection matrix (camera to clip +// transformation). If the aspect ratio of the GL window and +// ON_Viewport's frustum do not match, the viewport's frustum is +// adjusted to get things back to 1:1. +// +// For systems where the upper left corner of a window has +// coordinates (0,0) use: +// port_left = 0 +// port_right = width-1 +// port_bottom = height-1 +// port_top = 0 +void ON_GL( ON_Viewport&, + int, int, // port_left, port_right (port_left != port_right) + int, int // port_bottom, port_top (port_bottom != port_top) + ); + +//////////// +// +// Use ON_GL( ON_Viewport& ) to load the GL model view matrix (world to +// camera transformation). +void ON_GL( const ON_Viewport& ); + +// Use ON_GL( order, cv_count, knot, bPermitScaling, glknot ) +// to create knot vectors suitable for GL NURBS rendering. +void ON_GL( + const int, // order, ON_NurbsCurve... order + const int, // cv_count, ON_NurbsCurve... cv count + const double*, // knot, ON_NurbsCurve... knot vector + GLfloat*, // glknot[] - GL knot vector + int = 0, // bPermitScaling - true if re-scaling is allowed + double* = nullptr // scale[2] - If not nullptr and bPermitScaling is true, + // then the scaling parameters are returned here. + // ( glknot = (knot = scale[0])*scale[1] ) + ); + +#endif diff --git a/opennurbs/Include/opennurbs_group.h b/opennurbs/Include/opennurbs_group.h new file mode 100644 index 0000000..8a39ede --- /dev/null +++ b/opennurbs/Include/opennurbs_group.h @@ -0,0 +1,83 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_GROUP_INC_) +#define OPENNURBS_GROUP_INC_ + +class ON_CLASS ON_Group : public ON_ModelComponent +{ + ON_OBJECT_DECLARE(ON_Group); + +public: + static const ON_Group Unset; // nil id + + /* + Parameters: + model_component_reference - [in] + none_return_value - [in] + value to return if ON_Material::Cast(model_component_ref.ModelComponent()) + is nullptr + Returns: + If ON_Material::Cast(model_component_ref.ModelComponent()) is not nullptr, + that pointer is returned. Otherwise, none_return_value is returned. + */ + static const ON_Group* FromModelComponentRef( + const class ON_ModelComponentReference& model_component_reference, + const ON_Group* none_return_value + ); + +public: + ON_Group() ON_NOEXCEPT; + ON_Group(const ON_Group& src); + ~ON_Group() = default; + ON_Group& operator=(const ON_Group& src) = default; + +private: + + ////////////////////////////////////////////////////////////////////// + // + // ON_Object overrides + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + void Dump( + ON_TextLog& text_log + ) const override; + + bool Write( + ON_BinaryArchive& archive + ) const override; + + bool Read( + ON_BinaryArchive& archive + ) override; + +private: + bool Internal_WriteV5( + ON_BinaryArchive& archive + ) const; + + bool Internal_ReadV5( + ON_BinaryArchive& archive + ); +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray; +#endif + +#endif diff --git a/opennurbs/Include/opennurbs_hash_table.h b/opennurbs/Include/opennurbs_hash_table.h new file mode 100644 index 0000000..d6a736b --- /dev/null +++ b/opennurbs/Include/opennurbs_hash_table.h @@ -0,0 +1,199 @@ +/* +// +// Copyright (c) 1993-2016 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +//////////////////////////////////////////////////////////////// +// +// defines ON_Hash32Table +// +//////////////////////////////////////////////////////////////// + +#if !defined(OPENNURBS_HASH_TABLE_INC_) +#define OPENNURBS_HASH_TABLE_INC_ + +class ON_CLASS ON_Hash32TableItem +{ +public: + ON_Hash32TableItem() = default; + ~ON_Hash32TableItem() = default; + ON_Hash32TableItem(const ON_Hash32TableItem&) = default; + ON_Hash32TableItem& operator=(const ON_Hash32TableItem&) = default; + +public: + ON__UINT32 HashTableSerialNumber() const; + + static ON__UINT32 Hash32FromSHA1Hash( + const class ON_SHA1_Hash& sha1_hash + ); + + static ON__UINT32 Hash32FromId( + const ON_UUID& id + ); + + /* + Returns: + If this item has been added to an ON_Hash32Table.AddItem(hash32,item pointer) then the + value of hash3d passed as the first argument to ON_Hash32Table.AddItem(hash32,item pointer) + is returned. This is the value the ON_Hash32Table uses for this item. + Othewise 0 is returned. + Remarks: + This function is useful when copying hash tables. + + count = src_hash_table.ItemCount(); + MyHashTableItems src_items[count]; // items added to src_hash_table + + // copy src_hash_table + MyHashTableItems copied_items[count]; + copied_items = src_items; + for (unsigned i = 0; i < count; ++i) + { + ON_SubDSurfaceInterpolatortHash32TableItem& hitem = copied_items[i]; + hitem.ClearHashTableSerialNumberForExperts(); + m_htable.AddItem(hitem.HashTableItemHash(), &hitem); + } + */ + ON__UINT32 HashTableItemHash() const; + + /* + Description: + Useful when copying hash tables to remove the hash table reference from + a copied hash item. Never remove the hash table reference from an item + that is still in a hash table. + */ + void ClearHashTableSerialNumberForExperts(); +private: + friend class ON_Hash32Table; + mutable ON_Hash32TableItem* m_internal_next = nullptr; + mutable ON__UINT32 m_internal_hash32 = 0; + mutable ON__UINT32 m_internal_hash_table_sn = 0; +}; + +/* +Description: + A hash table designed to be used for items with high quality 32-bit hash values. +*/ +class ON_CLASS ON_Hash32Table +{ +public: + ON_Hash32Table(); + ~ON_Hash32Table(); + +private: + ON_Hash32Table(const ON_Hash32Table&) = delete; + ON_Hash32Table& operator=(const ON_Hash32Table&) = delete; + +public: + ON__UINT32 HashTableSerialNumber() const; + + /* + Description: + Adds an item to the hash table. + Parameters: + hash32 - [in] + item - [in/out] + Returns: + The added item. + */ + bool AddItem( + ON__UINT32 hash32, + class ON_Hash32TableItem* item + ); + + /* + Returns: + The first item in the hash table with hash = hash32. + Parameters: + hash32 - [in] + Remarks: + This function is used to find the first element in the hash table with the + specified hash32 falue. Use ON_Hash32TableItem.NextItemWithSameHash() to get + the next item in the has table with the same hash value. + */ + class ON_Hash32TableItem* FirstItemWithHash( + ON__UINT32 hash32 + ) const; + + class ON_Hash32TableItem* NextItemWithHash( + const class ON_Hash32TableItem* current_item + ) const; + + /* + Returns: + The first item in the hash table. + Remarks: + This function is used for iterating throught every element in the hash table. + */ + class ON_Hash32TableItem* FirstTableItem( + ) const; + + /* + Returns: + The next item in the hash table. + Remarks: + This function is used for iterating throught every element in the hash table. + */ + class ON_Hash32TableItem* NextTableItem( + const ON_Hash32TableItem* item + ) const; + + /* + Description: + Remove an item from the hash table. Caller is responsible for managing item memory. + Parameters: + item - [in/out] + If the item is removed, the has table serial number is set to zero. + Returns: + The true if the item was removed. + */ + bool RemoveItem( + class ON_Hash32TableItem* item + ); + + /* + Description: + Removes all hash table items. Caller is responsible for managing the item memory. + */ + unsigned int RemoveAllItems(); + + /* + Description: + Removes all hash table items. + For each item memset(item,0,fsp.SizeofElement()) and fsp.ReturnElement(item) are called. + */ + unsigned int RemoveAllItems( + class ON_FixedSizePool& fsp + ); + + /* + Returns: + Number of items in the hash table + */ + unsigned int ItemCount() const; + + bool IsValid() const; + +private: + const ON__UINT32 m_hash_table_sn; + ON__UINT32 m_reserved = 0; + mutable ON__UINT32 m_hash_table_capacity = 0; + ON__UINT32 m_item_count = 0; + mutable class ON_Hash32TableItem** m_hash_table = nullptr; + + void Internal_AdjustTableCapacity( + ON__UINT32 item_count + ); +}; + + +#endif diff --git a/opennurbs/Include/opennurbs_hatch.h b/opennurbs/Include/opennurbs_hatch.h new file mode 100644 index 0000000..bbf34f5 --- /dev/null +++ b/opennurbs/Include/opennurbs_hatch.h @@ -0,0 +1,975 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#ifndef OPENNURBS_HATCH_H_INCLUDED +#define OPENNURBS_HATCH_H_INCLUDED + +/* + class ON_HatchLoop + ///////////////////////////////////////////////////////////////// + Represents a 3d boundary loop curve +*/ +class ON_CLASS ON_HatchLoop +{ +public: +#if defined(OPENNURBS_EXPORTS) || defined(OPENNURBS_IMPORTS) + // When the Microsoft CRT(s) is/are used, this is the best + // way to prevent crashes that happen when a hatch loop is + // allocated with new in one DLL and deallocated with + // delete in another DLL. + + // new/delete + void* operator new(size_t); + void operator delete(void*); + + // array new/delete + void* operator new[] (size_t); + void operator delete[] (void*); + + // in place new/delete + void* operator new(size_t,void*); + void operator delete(void*,void*); +#endif + + enum eLoopType + { + ltOuter = 0, + ltInner = 1, + }; + + ON_HatchLoop(); + ON_HatchLoop( ON_Curve* pCurve2d, eLoopType type = ltOuter); + ON_HatchLoop( const ON_HatchLoop& src); + ~ON_HatchLoop(); + + ON_HatchLoop& operator=( const ON_HatchLoop& src); + + bool IsValid( ON_TextLog* text_log = nullptr ) const; + void Dump( ON_TextLog& ) const; // for debugging + bool Write( ON_BinaryArchive&) const; + bool Read( ON_BinaryArchive&); + + // Interface + ///////////////////////////////////////////////////////////////// + + /* + Description: + Get a closed 2d curve boundary loop + Parameters: + Return: + Pointer to loop's 2d curve + */ + const ON_Curve* Curve() const; + + /* + Description: + Specify the 2d loop curve in the hatch's plane coordinates + Parameters: + curve - [in] 2d input curve + Return: + true: success, false, curve couldn't be duplicated + Remarks: + The curve is copied + */ + bool SetCurve( const ON_Curve& curve); + + /* + Description: + Get the type flag of the loop + Returns: + eLoopType::ltInner or eLoopType::ltOuter + */ + eLoopType Type() const; + + /* + Description: + Specify the type flag of the loop + Parameters: + type - [in] ltInner or ltOuter + */ + void SetType( eLoopType type); + +protected: + friend class ON_Hatch; + eLoopType m_type; // loop type flag - inner or outer + ON_Curve* m_p2dCurve; // 2d closed curve bounding the hatch + // This is really a 3d curve with z coordinates = 0 +}; + + +/* + class ON_HatchLine + ///////////////////////////////////////////////////////////////// + Represents one line of a hatch pattern + Similar to AutoCAD's .pat file definition + ON_HatchLine's are used by ON_HatchPattern + to specify the dashes and offset patterns of the lines. + + Each line has the following information: + Angle is the direction of the line CCW from the x axis + The first line origin is at base + Each line repetition is offset by offset from the previous line + offset.x is parallel to the line and + offset.y is perpendicular to the line + The base and offset values are rotated by the line's angle to + produce a location in the hatch pattern's coordinate system + There can be gaps and dashes specified for drawing the line + + If there are no dashes, the line is solid + Negative length dashes are gaps + Positive length dashes are drawn as line segments +*/ + +class ON_CLASS ON_HatchLine +{ +public: + // Default constructor creates ON_HatchLine::SolidHorizontal + ON_HatchLine() = default; + ~ON_HatchLine() = default; + ON_HatchLine(const ON_HatchLine&) = default; + ON_HatchLine& operator=(const ON_HatchLine&) = default; + + static const ON_HatchLine Unset; // angle = unset + static const ON_HatchLine SolidHorizontal; // angle = 0 + static const ON_HatchLine SolidVertical; // angle = pi/2 + + static int Compare( + const ON_HatchLine& a, + const ON_HatchLine& b + ); + + ON_HatchLine( + double angle_in_radians, + ON_2dPoint base, + ON_2dVector offset, + const ON_SimpleArray& dashes + ); + + // constructs solid line + ON_HatchLine( + double angle_in_radians + ); + + bool operator==( const ON_HatchLine&) const; + bool operator!=( const ON_HatchLine&) const; + + bool IsValid( ON_TextLog* text_log = nullptr ) const; + void Dump( ON_TextLog& ) const; // for debugging + +public: + bool Write( ON_BinaryArchive&) const; // serialize definition to binary archive + bool Read( ON_BinaryArchive&); // restore definition from binary archive + +private: + bool WriteV5(ON_BinaryArchive&) const; // serialize definition to binary archive + bool ReadV5(ON_BinaryArchive&); // restore definition from binary archive + +public: + ///////////////////////////////////////////////////////////////// + // + // Interface + // + + /* + Description: + Get angle of the hatch line. + CCW from x-axis + Parameters: + Return: + The angle in radians + */ + double AngleRadians() const; + + double AngleDegrees() const; + + /* + Description: + Set angle of the hatch line. + CCW from x-axis + Parameters: + angle - [in] angle in radians + Return: + */ + void SetAngleRadians( + double angle_in_radians + ); + + void SetAngleDegrees( + double angle_in_degrees + ); + + /* + Description: + Get this line's 2d basepoint + Parameters: + Return: + the base point + */ + ON_2dPoint Base() const; + /* + Description: + Set this line's 2d basepoint + Parameters: + base - [in] the basepoint + Return: + */ + void SetBase( const ON_2dPoint& base); + + /* + Description: + Get this line's 2d offset for line repetitions + Offset().x is shift parallel to line + Offset().y is spacing perpendicular to line + Parameters: + Return: + the offset + */ + ON_2dVector Offset() const; + + /* + Description: + Get this line's 2d offset for line repetitions + Offset().x is shift parallel to line + Offset().y is spacing perpendicular to line + Parameters: + offset - [in] the shift,spacing for repeated lines + Return: + */ + void SetOffset( const ON_2dVector& offset); + + /* + Description: + Get the number of gaps + dashes in the line + Parameters: + Return: + nummber of dashes in the line + */ + int DashCount() const; + + /* + Description: + Get the dash length at index + Parameters: + index - [in] the dash to get + Return: + the length of the dash ( gap if negative) + */ + double Dash( int) const; + + /* + Description: + Add a dash to the pattern + Parameters: + dash - [in] length to append - < 0 for a gap + */ + void AppendDash( double dash); + + /* + Description: + Specify a new dash array + Parameters: + dashes - [in] array of dash lengths + */ + void SetDashes( const ON_SimpleArray& dashes); + + const ON_SimpleArray& Dashes() const; + + /* + Description: + Get the line's angle, base, offset and dashes + in one function call + Parameters: + angle_radians - [out] angle in radians CCW from x-axis + base - [out] origin of the master line + offset - [out] offset for line replications + dashes - [out] the dash array for the line + Return: + */ + void GetLineData( + double& angle_radians, + ON_2dPoint& base, + ON_2dVector& offset, + ON_SimpleArray& dashes) const; + + /* + Description: + Get the total length of a pattern repeat + Parameters: + Return: + Pattern length + */ + double GetPatternLength() const; + +private: + double m_angle_radians = 0.0; + ON_2dPoint m_base = ON_2dPoint::Origin; + ON_2dVector m_offset = ON_2dVector::ZeroVector; + ON_SimpleArray< double> m_dashes; +}; + + + + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray; +#endif + + +/* + class ON_HatchPattern + ///////////////////////////////////////////////////////////////// + Fill definition for a hatch + + The hatch will be one of + ON_Hatch::ON_HatchPattern::HatchFillType::Lines - pat file style definition + ON_Hatch::ON_HatchPattern::HatchFillType::Gradient - uses a color function + ON_Hatch::ON_HatchPattern::HatchFillType::Solid - uses entity color + +*/ +class ON_CLASS ON_HatchPattern : public ON_ModelComponent +{ + ON_OBJECT_DECLARE( ON_HatchPattern); + +public: + ON_HatchPattern() ON_NOEXCEPT; + ~ON_HatchPattern() = default; + ON_HatchPattern(const ON_HatchPattern&); + ON_HatchPattern& operator=(const ON_HatchPattern&) = default; + +public: + static const ON_HatchPattern Unset; // index = ON_UNSET_INT_INDEX, id = nil + static const ON_HatchPattern Solid; // index = -1, id set, unique and persistent + static const ON_HatchPattern Hatch1; // index = -2, id set, unique and persistent + static const ON_HatchPattern Hatch2; // index = -3, id set, unique and persistent + static const ON_HatchPattern Hatch3; // index = -4, id set, unique and persistent + static const ON_HatchPattern HatchDash; // index = -5, id set, unique and persistent + static const ON_HatchPattern Grid; // index = -6, id set, unique and persistent + static const ON_HatchPattern Grid60; // index = -7, id set, unique and persistent + static const ON_HatchPattern Plus; // index = -8, id set, unique and persistent + static const ON_HatchPattern Squares; // index = -9, id set, unique and persistent + + // compare everything except Index() value. + static int Compare( + const ON_HatchPattern& a, + const ON_HatchPattern& b + ); + + // Compare all settings (type, lines, ...) that effect the appearance. + // Ignore Index(), Id(), Name() + static int CompareAppearance( + const ON_HatchPattern& a, + const ON_HatchPattern& b + ); + +public: + /* + Parameters: + model_component_reference - [in] + none_return_value - [in] + value to return if ON_Layer::Cast(model_component_ref.ModelComponent()) + is nullptr + Returns: + If ON_Layer::Cast(model_component_ref.ModelComponent()) is not nullptr, + that pointer is returned. Otherwise, none_return_value is returned. + */ + static const ON_HatchPattern* FromModelComponentRef( + const class ON_ModelComponentReference& model_component_reference, + const ON_HatchPattern* none_return_value + ); + +public: + + enum class HatchFillType : unsigned int + { + Solid = 0, // uses entity color + Lines = 1, // pat file definition + //Gradient = 2, // uses a fill color function + }; + + static ON_HatchPattern::HatchFillType HatchFillTypeFromUnsigned( + unsigned hatch_fill_type_as_unsigned + ); + + + ///////////////////////////////////////////////////////////////// + // ON_Object overrides + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + void Dump( ON_TextLog& ) const override; // for debugging + bool Write( ON_BinaryArchive&) const override; + bool Read( ON_BinaryArchive&) override; +private: + bool WriteV5(ON_BinaryArchive&) const; + bool ReadV5(ON_BinaryArchive&); +public: + + ////////////////////////////////////////////////////////////////////// + // Interface + + /* + Description: + Return the pattern's fill type + Parameters: + */ + ON_HatchPattern::HatchFillType FillType() const; + + /* + Description: + Set the pattern's fill type + Parameters: + type - [in] the new filltype + */ + void SetFillType( + ON_HatchPattern::HatchFillType fill_type + ); + + /* + Description: + Set the name of the pattern + Parameters: + pDescription - [in] the new description + Returns: + */ + void SetDescription( + const wchar_t* pDescription + ); + + /* + Description: + Get a short description of the pattern + Parameters: + string - [out] The string is returned here + */ + const ON_wString& Description() const; + + + // Interface functions for line hatches + ///////////////////////////////////////////////////////////////// + /* + Description: + Get the number of ON_HatchLines in the pattern + Parameters: + Return: + number of lines + */ + int HatchLineCount() const; + + /* + Description: + Add an ON_HatchLine to the pattern + Parameters: + line - [in] the line to add + Return: + >= 0 index of the new line + -1 on failure + */ + int AddHatchLine( + const ON_HatchLine& line + ); + + /* + Description: + Get the ON_HatchLine at index + Parameters: + index - [in] Index of the line to get + Return: + the hatch line + nullptr if index is out of range + */ + const ON_HatchLine* HatchLine( + int index + ) const; + + /* + Description: + Remove a hatch line from the pattern + Parameters: + index - [in] Index of the line to remove + Return: + true - success + false - index out of range + */ + bool RemoveHatchLine( + int index + ); + + /* + Description: + Remove all of the hatch line from the pattern + Parameters: + + Return: + true - success + false - index out of range + */ + void RemoveAllHatchLines(); + + /* + Description: + Set all of the hatch lines at once. + Existing hatchlines are deleted. + Parameters: + lines - [in] Array of lines to add. Lines are copied + Return: + number of lines added + */ + int SetHatchLines( + const ON_ClassArray& lines + ); + + int SetHatchLines( + size_t count, + const ON_HatchLine* lines + ); + + const ON_ClassArray& HatchLines() const; + +private: + ON_HatchPattern::HatchFillType m_type = ON_HatchPattern::HatchFillType::Solid; + + ON_wString m_description = ON_wString::EmptyString; // String description of the pattern + + // Represents a collection of ON_HatchLine's to make a complete pattern + // This is the definition of a hatch pattern. + // Simple solid line hatches with fixed angle and spacing are also + // represented with this type of hatch + ON_ClassArray m_lines; // used by line hatches +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray; +#endif + +/* + class ON_Hatch + ///////////////////////////////////////////////////////////////// + Represents a hatch in planar boundary loop or loops + This is a 2d entity with a plane defining a local coordinate system + The loops, patterns, angles, etc are all in this local coordinate system + + The ON_Hatch object manages the plane and loop array + Fill definitions are in the ON_HatchPattern or class derived from ON_HatchPattern + ON_Hatch has an index to get the pattern definition from the pattern table + +*/ +class ON_CLASS ON_Hatch : public ON_Geometry +{ + ON_OBJECT_DECLARE( ON_Hatch); + +public: + // Default constructor + ON_Hatch() = default; + ~ON_Hatch(); + ON_Hatch( const ON_Hatch&); + ON_Hatch& operator=(const ON_Hatch&); + + static ON_Hatch* HatchFromBrep( + ON_Hatch* use_this_hatch, + const ON_Brep* brep, + int face_index, + int pattern_index, + double pattern_rotation_radians, + double pattern_scale, + ON_3dPoint basepoint); + +private: + void Internal_Destroy(); + void Internal_CopyFrom(const ON_Hatch& src); +public: + + virtual ON_Hatch* DuplicateHatch() const; + + // ON_Object overrides + ///////////////////////////////////////////////////////////////// + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + void Dump( ON_TextLog& ) const override; + bool Write( ON_BinaryArchive&) const override; + bool Read( ON_BinaryArchive&) override; + ON::object_type ObjectType() const override; + + // ON_Geometry overrides + ///////////////////////////////////////////////////////////////// + /* + Returns the geometric dimension of the object ( usually 3) + */ + int Dimension() const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + // virtual ON_Geometry GetTightBoundingBox override + bool GetTightBoundingBox( class ON_BoundingBox& tight_bbox, bool bGrowBox = false, const class ON_Xform* xform = nullptr ) const override; + + /* + Description: + Transform the object by a 4x4 xform matrix + + Parameters: + [in] xform - An ON_Xform with the transformation information + Returns: + true = Success + false = Failure + Remarks: + The object has been transformed when the function returns. + */ + bool Transform( const ON_Xform&) override; + + /* + Description: + Scales the hatch's pattern by a 4x4 xform matrix + Parameters: + [in] xform - An ON_Xform with the transformation information + Returns: + true = Success + false = Failure + Remarks: + The hatch pattern scale is multiplied by the change in length of a + unit vector in the hatch plane x direction when that vector is + scaled by the input xform + */ + bool ScalePattern(ON_Xform xform); + + /* + Description: + If possible, BrepForm() creates a brep form of the + ON_Geometry. + Parameters: + brep - [in] if not nullptr, brep is used to store the brep + form of the geometry. + Result: + Returns a pointer to on ON_Brep or nullptr. If the brep + parameter is not nullptr, then brep is returned if the + geometry has a brep form and nullptr is returned if the + geometry does not have a brep form. + Remarks: + The caller is responsible for managing the brep memory. + See Also + ON_Geometry::HasBrepForm + */ + class ON_Brep* BrepForm( + class ON_Brep* brep = nullptr + ) const override; + + + + // Interface + ///////////////////////////////////////////////////////////////// + + /* + Description: + Create a hatch from input geometry and parameters + Parameters: + plane [I] - ON_Plane to make the hatch on + loops [I] - Array of boundary loops with the outer one first + pattern_index [I] - Index into the hatch table + pattern_rotation [I] - ccw in radians about plane origin + pattern_scale [I] - Scale factor for pattern definition + Returns: + true = success, false = failure + */ + bool Create( const ON_Plane& plane, + const ON_SimpleArray loops, + int pattern_index, + double pattern_rotation, + double pattern_scale); + + /* + Description: + Get the plane defining the hatch's coordinate system + Parameters: + Returns: + the plane + */ + const ON_Plane& Plane() const; + + /* + Description: + Set the plane defining the hatch's coordinate system + Parameters: + plane - [in] the plane to set + Returns: + */ + void SetPlane( const ON_Plane& plane); + + /* + Description: + Gets the rotation applied to the hatch pattern + when it is mapped to the hatch's plane + Returns: + The rotation in radians + Remarks: + The pattern is rotated counter-clockwise around + the hatch's plane origin by this value + */ + double PatternRotation() const; + +/* + Description: + Sets the rotation applied to the hatch pattern + when it is mapped to the hatch's plane + Parameters: + rotation - [in] The rotation in radians + Remarks: + The pattern is rotated counter-clockwise around + the hatch's plane origin by this value + */ + void SetPatternRotation( double rotation); + + /* + Description: + Gets the scale applied to the hatch pattern + when it is mapped to the hatch's plane + Returns: + The scale + Remarks: + The pattern is scaled around + the hatch's plane origin by this value + */ + double PatternScale() const; + +/* + Description: + Sets the scale applied to the hatch pattern + when it is mapped to the hatch's plane + Parameters: + scale - [in] The scale + Remarks: + The pattern is scaled around + the hatch's plane origin by this value + */ + void SetPatternScale( double scale); + + /* + Description: + Get the number of loops used by this hatch + Parameters: + Returns: + the number of loops + */ + int LoopCount() const; + + /* + Description: + Add a loop to the hatch + Parameters: + loop - [in] the loop to add. Memory management for the loop is managed + by this class. + Returns: + */ + void AddLoop( ON_HatchLoop* loop); + + /* + Description: + Insert a loop to the hatch at the specified index + Parameters: + index - [in] zero based index of the position where insert the loop to. + loop - [in] the loop to insert. Memory management for the loop is managed + by this class on success. + Returns: + true if success + false if index is lower than 0 or greater than current loop count. + */ + bool InsertLoop( int index, + ON_HatchLoop* loop); + + /* + Description: + Remove a loop in the hatch + Parameters: + loop - [in] zero based index of the loop to remove. + Returns: + true if success + */ + bool RemoveLoop( int index); + + /* + Description: + Get the loop at index + Parameters: + index - [in] which loop to get + Returns: + pointer to loop at index + nullptr if index is out of range + */ + const ON_HatchLoop* Loop( int index) const; + + /* + Description: + Get the 3d curve corresponding to loop[index] + Parameters: + index - [in] which loop to get + Returns: + pointer to 3d curve of loop at index + nullptr if index is out of range or curve can't be made + Caller deletes the returned curve + */ + ON_Curve* LoopCurve3d( int index) const; + + /* + Description: + Get the index of the hatch's pattern + Parameters: + Returns: + index of the pattern + */ + int PatternIndex() const; + +/* + Description: + Set the index of the hatch's pattern + Parameters: + index - [in] pattern index to set + Returns: + */ + void SetPatternIndex( int index); + + // Basepoint functions added March 23, 2008 -LW + /* + Description: + Set 2d Base point for hatch pattern alignment. + Parameters: + basepoint - 2d point in hatch's ECS + */ + void SetBasePoint(ON_2dPoint basepoint); + + /* + Description: + Set 3d Base point for hatch pattern alignment. + Parameters: + point - 3d WCS point + Remarks: + Projects point to hatch's plane and sets 2d point + */ + void SetBasePoint(ON_3dPoint point); + + /* + Description: + Return 3d WCS point that lies on hatch's plane used for pattern origin. + */ + ON_3dPoint BasePoint() const; + + /* + Description: + Return 2d ECS point used for pattern origin. + */ + ON_2dPoint BasePoint2d() const; + + /* + Function added June 12 2008 LW + Description: + Remove all of the loops on the hatch and add the curves in 'loops' as new loops + Parameters: + loops - [in] An array of pointers to 2d or 3d curves + If the curves are 2d, add them to the hatch directly + If they are 3d, project them to the hatch's plane first + Returns: + true - success + false - no loops in input array or an error adding them + */ + bool ReplaceLoops(ON_SimpleArray& loops); + +#if defined(OPENNURBS_GRADIENT_WIP) + /* + Description: + Returns gradient fill type for this hatch + */ + ON_GradientType GetGradientType() const; + + /* + Description: + Set the gradient fill type for this hatch + */ + void SetGradientType(ON_GradientType gt); + + /* + Description: + Get list of color stops used for gradient drawing. + */ + void GetGradientColors(ON_SimpleArray& colors) const; + + /* + Description: + Set list of color stops used for gradient drawing. + */ + bool SetGradientColors(const ON_SimpleArray& colors); + + /* + Description: + Get gradient repeat factor for gradient drawing. + > 1 repeat reflected number of times between start and end point + < -1 repeat wrap number of times between start and end point + any other value does not affect repeat on a gradient + */ + double GetGradientRepeat() const; + + /* + Description: + Set gradient repeat factor for gradient drawing + > 1 repeat reflected number of times between start and end point + < -1 repeat wrap number of times between start and end point + any other value does not affect repeat on a gradient + Returns: + True if the repeat factor was successfully set + */ + bool SetGradientRepeat(double repeat); + + /* + Description: + Get the start and end points for gradient drawing in 3d + */ + void GetGradientEndPoints(ON_3dPoint& startPoint, ON_3dPoint& endPoint) const; + + /* + Description: + Set the start and end points for gradient drawing + */ + bool SetGradientEndPoints(ON_3dPoint startpoint, ON_3dPoint endPoint); +#endif + +private: + ON_Plane m_plane; + double m_pattern_scale = 1.0; + double m_pattern_rotation = 0.0; + ON_2dPoint m_basepoint = ON_2dPoint::Origin; + ON_SimpleArray m_loops; + int m_pattern_index = -1; +}; + +//Part of a boundary. An element has a curve subdomain and a flag to say +//whether that piece of curve should be reversed +class ON_CLASS ON_CurveRegionBoundaryElement +{ +public : + ON_CurveRegionBoundaryElement(); + ON_CurveRegionBoundaryElement(const ON_CurveRegionBoundaryElement& src); + ~ON_CurveRegionBoundaryElement(); + ON_CurveRegionBoundaryElement& operator=(const ON_CurveRegionBoundaryElement& src); + int m_curve_id; + ON_Interval m_subdomain; + bool m_bReversed; +}; + +//A list of curve subdomains that form a closed boundary with active space on the left. +typedef ON_ClassArray ON_CurveRegionBoundary; + +//A list of region boundaries that bound a single connected region of the plane. +//The first boundary is always the outer boundary. +typedef ON_ClassArray ON_CurveRegion; + + +#endif diff --git a/opennurbs/Include/opennurbs_hsort_template.h b/opennurbs/Include/opennurbs_hsort_template.h new file mode 100644 index 0000000..b032cdf --- /dev/null +++ b/opennurbs/Include/opennurbs_hsort_template.h @@ -0,0 +1,106 @@ +#if !defined(ON_COMPILING_OPENNURBS_HSORT_FUNCTIONS) +/* +See opennurbs_sort.cpp for examples of using openurbs_hsort_template.c +to define type specific heap sort functions. +*/ +#error Do not compile openurbs_hsort_template.c directly. +#endif + +// ON_SORT_TEMPLATE_TYPE -> double, int, .... +#if !defined(ON_SORT_TEMPLATE_TYPE) +#error Define ON_SORT_TEMPLATE_TYPE macro before including opennurbs_qsort_template.c +#endif + +#if !defined(ON_HSORT_FNAME) +#error Define ON_HSORT_FNAME macro before including opennurbs_qsort_template.c +#endif + +#if defined(ON_SORT_TEMPLATE_COMPARE) +// use a compare function like strcmp for char* strings +#define ON_HSORT_GT(A,B) ON_SORT_TEMPLATE_COMPARE(A,B) > 0 +#define ON_HSORT_GT_TMP(A) ON_SORT_TEMPLATE_COMPARE(A,&tmp) > 0 +#else +// use type compares +#define ON_HSORT_GT(A,B) *A > *B +#define ON_HSORT_GT_TMP(A) *A > tmp +#endif + +#if defined(ON_SORT_TEMPLATE_USE_MEMCPY) +#define ON_HSORT_TO_TMP(A) memcpy(&tmp,A,sizeof(tmp)) +#define ON_HSORT_FROM_TMP(A) memcpy(A,&tmp,sizeof(tmp)) +#define ON_HSORT_COPY(dst,src) memcpy(dst,src,sizeof(tmp)) +#else +#define ON_HSORT_TO_TMP(A) tmp = *A +#define ON_HSORT_FROM_TMP(A) *A = tmp +#define ON_HSORT_COPY(dst,src) *dst = *src +#endif + +#if defined(ON_SORT_TEMPLATE_STATIC_FUNCTION) +static +#endif +void +ON_HSORT_FNAME( ON_SORT_TEMPLATE_TYPE* base, size_t nel ) +{ + size_t i_end,k,i,j; + ON_SORT_TEMPLATE_TYPE* e_end; + ON_SORT_TEMPLATE_TYPE* e_i; + ON_SORT_TEMPLATE_TYPE* e_j; + ON_SORT_TEMPLATE_TYPE tmp; + + if (0 == base || nel < 2) + return; + + k = nel >> 1; + i_end = nel-1; + e_end = base + i_end; + for (;;) + { + if (k) + { + --k; + ON_HSORT_TO_TMP((base+k)); /* e_tmp = e[k]; */ + } + else + { + ON_HSORT_TO_TMP(e_end); /* e_tmp = e[i_end]; */ + ON_HSORT_COPY(e_end,base); /* e[i_end] = e[0]; */ + if (!(--i_end)) + { + ON_HSORT_FROM_TMP(base); /* e[0] = e_tmp; */ + break; + } + e_end--; + } + + i = k; + j = (k<<1) + 1; + e_i = base + i; + while (j <= i_end) + { + e_j = base + j; + if (j < i_end && ON_HSORT_GT((e_j+1),e_j) /*e[j] < e[j + 1] */) + { + j++; + e_j++; + } + if (ON_HSORT_GT_TMP(e_j) /* tmp < e[j] */) + { + ON_HSORT_COPY(e_i,e_j); /* e[i] = e[j]; */ + i = j; + e_i = e_j; + j = (j<<1) + 1; + } + else + j = i_end + 1; + } + + ON_HSORT_FROM_TMP(e_i); /* e[i] = e_tmp; */ + } +} + +#undef ON_HSORT_GT +#undef ON_HSORT_GT_TMP +#undef ON_HSORT_TO_TMP +#undef ON_HSORT_FROM_TMP +#undef ON_HSORT_COPY +#undef ON_HSORT_FROM_TMP diff --git a/opennurbs/Include/opennurbs_input_libsdir.h b/opennurbs/Include/opennurbs_input_libsdir.h new file mode 100644 index 0000000..ed21966 --- /dev/null +++ b/opennurbs/Include/opennurbs_input_libsdir.h @@ -0,0 +1,43 @@ +/* +// +// Copyright (c) 1993-2016 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_INPUT_LIBSDIR_INC_) +#define OPENNURBS_INPUT_LIBSDIR_INC_ + +#if defined(ON_COMPILER_MSC) && !defined(OPENNURBS_INPUT_LIBS_DIR) + +// This header file insures OPENNURBS_INPUT_LIBS_DIR is defined to be +// the path to were the libraries opennurbs.dll links with are located. +// Examples of these libaries are zlib and freetype. + +#if defined(OPENNURBS_OUTPUT_DIR) +// Typically, OPENNURBS_OUTPUT_DIR is defined in the +// MSBuild property sheet opennurbs_msbuild.Cpp.props. +#define OPENNURBS_INPUT_LIBS_DIR OPENNURBS_OUTPUT_DIR +#elif defined(RHINO_LIB_DIR) +// Typically, RHINO_LIB_DIR is defined in a Rhino module property sheet. +#define OPENNURBS_INPUT_LIBS_DIR RHINO_LIB_DIR +#else + +// Please define OPENNURBS_INPUT_LIBS_DIR in your build environment +// Please do not modify the opennurbs vcxproj files. Instead use +// a property sheet (.props file), .sln file, or define it here. +#error You must define OPENNURBS_INPUT_LIBS_DIR + +#endif + +#endif + +#endif diff --git a/opennurbs/Include/opennurbs_instance.h b/opennurbs/Include/opennurbs_instance.h new file mode 100644 index 0000000..02d5722 --- /dev/null +++ b/opennurbs/Include/opennurbs_instance.h @@ -0,0 +1,790 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_INSTANCE_INC_) +#define OPENNURBS_INSTANCE_INC_ + +class ON_CLASS ON_ReferencedComponentSettings +{ +public: + ON_ReferencedComponentSettings() = default; + ~ON_ReferencedComponentSettings(); + ON_ReferencedComponentSettings(const ON_ReferencedComponentSettings& src); + ON_ReferencedComponentSettings& operator=(const ON_ReferencedComponentSettings& src); + + bool Read( + ON_BinaryArchive& archive + ); + + bool Write( + ON_BinaryArchive& archive + ) const; + + bool IsEmpty() const; + bool IsNotEmpty() const; + + bool HasLayerInformation() const; + bool HasLayerTableInformation() const; + bool HasParentLayerInformation() const; + + /* + Description: + Update runtime layer color visibility, locked, ... settings in the + layer table read from a refence file to the values to use in the + runtime model. + This is typically done right after the reference file layer table is + read and before the layers are added to the runtime model. + Parameters: + source_archive_manifest - [in] + manifest of archive being read (may partially read) + model_manifest - [in] + manifest of runtime model (may partially created) + layer_count - [in] + length of layers[] array; + layers - [in/out] + The input values should be the layer table read from the referenced file. + The output values have color, visibility, locked, ... settings updated + to the state they had the last time the model file (not the referenced file) + was saved. + linked_definition_parent_layer - [in/out] + If linked_definition_parent_layer is not nullptr, its color, visibility, ... + settings are updated to the state they had the last time the model file + (not the referenced file) was saved. + Remarks: + The layer idenitification information (name, index, id) are not changed by + this function. + */ + void AfterReferenceLayerTableRead( + const class ON_ComponentManifest& source_archive_manifest, + const class ON_ComponentManifest& model_manifest, + const class ON_ManifestMap& archive_to_model_map, + ON_Layer* linked_definition_parent_layer, + unsigned int layer_count, + ON_Layer** layers + ); + + /* + Description: + Update the mapping from from reference file layer id to runtime model layer id. + Typically this is done immediately after the reference file layers are added + to the runtime model. + Parameters: + source_archive_manifest - [in] + manifest of archive being read (may partially read) + model_manifest - [in] + manifest of runtime model (may partially created) + archive_to_model_map - [in] + Manifest map from reference file settings to runtime model settings. + This map typically exists while the archive is being read and is + destroyed after reading is complete. That's why the mapping has + to be saved. + */ + void AfterLayerTableAddedToModel( + const class ON_ComponentManifest& source_archive_manifest, + const class ON_ComponentManifest& model_manifest, + const class ON_ManifestMap& archive_to_model_map + ); + + /* + Description: + Save the current runtime layer color, visibility, ... states. + Typically this is done immediately before a linked instance definition + or worksession reference information is written. Calling the Write() + function destroys the information created by BeforeWrite() because + it is generally out-of-date if modeling resumes after writing. + Parameters: + model_manifest - [in] + manifest of runtime model + destination_archive_manifest - [in] + manifest of archive being written (may partially written) + model_to_archive_map - [in] + Manifest map from model to destination_archive_manifest. + linked_definition_parent_layer - [in] + nullptr or the parent layer + context - [in] + first parameter passed to ModelLayerFromIdFunc + ModelLayerFromIdFunc - [in] + Function to get model layers from id + */ + void BeforeLinkedDefinitionWrite( + const class ON_ComponentManifest& model_manifest, + const class ON_ComponentManifest& destination_archive_manifest, + const class ON_ManifestMap& model_to_archive_map, + const ON_Layer* linked_definition_parent_layer, + void* context, + const ON_Layer*(*ModelLayerFromIdFunc)(void* context, const ON_UUID&) + ); + +private: + class ON_ReferencedComponentSettingsImpl* Impl( + bool bCreateIfNull + ); + + class ON_ReferencedComponentSettingsImpl* m_impl = nullptr; +}; + +/* +Description: + An ON_InstanceDefinition defines the geometry used by + instance references. +See Also: + ON_InstanceRef +*/ +class ON_CLASS ON_InstanceDefinition : public ON_ModelComponent +{ + ON_OBJECT_DECLARE(ON_InstanceDefinition); + +public: + + // IDEF_UPDATE_TYPE lists the possible relationships between + // the instance definition geometry and the archive + // (m_source_archive) containing the original defition. + enum class IDEF_UPDATE_TYPE : unsigned int + { + Unset = 0, + Static = 1, + LinkedAndEmbedded = 2, + Linked = 3 + + + //static_def = 0, + //embedded_def = 1, + // // As of 7 February, "static_def" and "embedded_def" + // // and shall be treated the same. Using "static_def" + // // is prefered and "embedded_def" is obsolete. + // // The geometry for the instance definition + // // is saved in archives, is fixed and has no + // // connection to a source archive. + // // All source archive information should be + // // empty strings and m_source_archive_checksum + // // shoule be "zero". + //linked_and_embedded_def = 2, + // // The geometry for the instance definition + // // is saved in archives. Complete source + // // archive and checksum information will be + // // present. The document setting + // // ON_3dmIOSettings.m_idef_link_update + // // determines if, when and how the instance + // // definition geometry is updated by reading the + // // source archive. + //linked_def = 3, + // // The geometry for this instance definition + // // is not saved in the archive that contains + // // this instance definition. This instance + // // definition geometry is imported from a + // // "source archive" The "source archive" file + // // name and checksum information are saved + // // in m_source_archive and m_source_archive_checksum. + // // If file named in m_source_archive is not available, + // // then this instance definition is not valid and any + // // references to it are not valid. + }; + + // Converts and integer into an IDEF_UPDATE_TYPE enum. + static ON_InstanceDefinition::IDEF_UPDATE_TYPE InstanceDefinitionTypeFromUnsigned( + unsigned int idef_type_as_unsigned + ); + + // Bits that identify subsets of the instance defintion + // fields. These bits are used to determine which fields to + // set when an ON_InstanceDefinition class is used to + // modify an existing instance definition. + enum + { + no_idef_settings = 0, + idef_name_setting = 1, // m_name + idef_description_setting = 2, // m_description + idef_url_setting = 4, // all m_url_* fields + idef_units_setting = 8, // m_us and m_unit_scale + idef_source_archive_setting = 0x10, // all m_source_*, layer style, update depth fields + idef_userdata_setting = 0x20, + all_idef_settings = 0xFFFFFFFF + }; + +public: + ON_InstanceDefinition() ON_NOEXCEPT; + ~ON_InstanceDefinition(); + ON_InstanceDefinition(const ON_InstanceDefinition&); + ON_InstanceDefinition& operator=(const ON_InstanceDefinition&); + +private: + void Internal_Destroy(); + void Internal_Copy(const ON_InstanceDefinition& src); + +public: + + static const ON_InstanceDefinition Unset; + + /* + Parameters: + model_component_reference - [in] + none_return_value - [in] + value to return if ON_InstanceDefinition::Cast(model_component_ref.ModelComponent()) + is nullptr + Returns: + If ON_InstanceDefinition::Cast(model_component_ref.ModelComponent()) is not nullptr, + that pointer is returned. Otherwise, none_return_value is returned. + */ + static const ON_InstanceDefinition* FromModelComponentRef( + const class ON_ModelComponentReference& model_component_reference, + const ON_InstanceDefinition* none_return_value + ); + + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + // virtual ON_Object::Dump override + void Dump( + ON_TextLog& text_log + ) const override; + +public: + bool Write( + ON_BinaryArchive& archive + ) const override; + +private: + bool Internal_WriteV5( + ON_BinaryArchive& archive + ) const; + bool Internal_WriteV6( + ON_BinaryArchive& archive + ) const; + +public: + bool Read( + ON_BinaryArchive& archive + ) override; + +private: + bool Internal_ReadV5( + ON_BinaryArchive& archive + ); + bool Internal_ReadV6( + ON_BinaryArchive& archive + ); + +public: + ON::object_type ObjectType() const override; + + // virtual ON_Object:: override + unsigned int SizeOf() const override; + + const ON_BoundingBox BoundingBox() const; + + void SetBoundingBox( ON_BoundingBox bbox ); + + void ClearBoundingBox(); + + const ON_wString Description() const; + void SetDescription( const wchar_t* description ); + + const ON_wString URL() const; + void SetURL( const wchar_t* url ); + + const ON_wString URL_Tag() const; + void SetURL_Tag( const wchar_t* url_tag ); + + /* + Returns: + A list of object ids in the instance geometry table sorted by id. + */ + const ON_SimpleArray& InstanceGeometryIdList() const; + + /* + Parameters: + instance_geometry_id_list - [in] + A list of object ids in the instance geometry table. + */ + void SetInstanceGeometryIdList( + const ON_SimpleArray& instance_geometry_id_list + ); + + /* + Description: + Remove all ids from the InstanceGeometryIdList(). + */ + void ClearInstanceGeometryIdList(); + + /* + Description: + Remove id from the InstanceGeometryIdList(). + */ + bool RemoveInstanceGeometryId( + ON_UUID id + ); + + /* + Description: + Remove InstanceGeometryIdList()[id_index] from the InstanceGeometryIdList() array. + */ + bool RemoveInstanceGeometryId( + int id_index + ); + + /* + Description: + Add id to the InstanceGeometryIdList(). + Parameters: + id - [in] + non-nil id to add. + Returns: + True if id is not nil and was added to the InstanceGeometryIdList(). + */ + bool AddInstanceGeometryId( + ON_UUID id + ); + + /* + Returns: + True if id is in the InstanceGeometryIdList(). + */ + bool IsInstanceGeometryId( + ON_UUID id + ) const; + +private: + int Internal_InstanceGeometryIdIndex( + ON_UUID id + ) const; + +public: + /* + Parameters: + instance_definition_type - [in] + ON_InstanceDefinition::IDEF_UPDATE_TYPE::Unset - change the type to Unset + and remove all linked file information. + ON_InstanceDefinition::IDEF_UPDATE_TYPE::Static - change the type to Static + and remove all linked file information. + ON_InstanceDefinition::IDEF_UPDATE_TYPE::LinkedAndEmbedded - change + the type to from Linked to LinkedAndEmbedded. If the current type + is not Linked, then no changes are made. + ON_InstanceDefinition::IDEF_UPDATE_TYPE::Linked - change + the type to from LinkedAndEmbedded to Linked. If the current type + is not LinkedAndEmbedded, then no changes are made. + */ + bool SetInstanceDefinitionType( + const ON_InstanceDefinition::IDEF_UPDATE_TYPE instance_definition_type + ); + + /* + Parameters: + linked_definition_type - [in] + Either ON_InstanceDefinition::IDEF_UPDATE_TYPE::LinkedAndEmbedded + or ON_InstanceDefinition::IDEF_UPDATE_TYPE::Linked. + linked_file_reference - [in] + */ + bool SetLinkedFileReference( + ON_InstanceDefinition::IDEF_UPDATE_TYPE linked_definition_type, + ON_FileReference linked_file_reference + ); + + bool SetLinkedFileReference( + ON_InstanceDefinition::IDEF_UPDATE_TYPE linked_definition_type, + const wchar_t* linked_file_full_path + ); + + const ON_FileReference LinkedFileReference() const; + + /* + Destroy all linked file path information and convert the type to Static. + */ + void ClearLinkedFileReference(); + + void ClearLinkedFileContentHash(); + + void ClearLinkedFileRelativePath(); + + const ON_wString& LinkedFilePath() const; + + const ON_UnitSystem& UnitSystem() const; + +public: + /* + Description: + Sets m_us and m_unit_scale. + */ + void SetUnitSystem( ON::LengthUnitSystem us ); + void SetUnitSystem( const ON_UnitSystem& us ); + + /* + Returns: + True if this is a linked instance definition with + layer settings information. + */ + bool HasLinkedIdefReferenceComponentSettings() const; + + void ClearLinkedIdefReferenceComponentSettings(); + + /* + Parameters: + bCreateIfNonePresent - [in] + When bCreateIfNonePresent is true and the idef type is ON_InstanceDefinition::IDEF_UPDATE_TYPE::Linked, + then ON_ReferencedComponentSettings will be created if none are present. + Return: + ON_ReferencedComponentSettings pointer or nullptr. + */ + const ON_ReferencedComponentSettings* LinkedIdefReferenceComponentSettings() const; + + /* + Parameters: + bCreateIfNonePresent - [in] + When bCreateIfNonePresent is true and the idef type is ON_InstanceDefinition::IDEF_UPDATE_TYPE::Linked, + then ON_ReferencedComponentSettings will be created if none are present. + Return: + ON_ReferencedComponentSettings pointer or nullptr. + */ + ON_ReferencedComponentSettings* LinkedIdefReferenceComponentSettings( + bool bCreateIfNonePresent + ); + +public: + + // OBSOLETE - change IdefUpdateType() to InstanceDefinitionType() + ON_InstanceDefinition::IDEF_UPDATE_TYPE IdefUpdateType() const; + + ON_InstanceDefinition::IDEF_UPDATE_TYPE InstanceDefinitionType() const; + + /* + Returns: + true if InstanceDefinitionType() = ON_InstanceDefinition::IDEF_UPDATE_TYPE::Linked or ON_InstanceDefinition::IDEF_UPDATE_TYPE::LinkedAndEmbedded. + */ + bool IsLinkedType() const; + + /* + Description: + This property applies when an instance definiton is linked. + Returns: + true: + When reading the file that defines the content of the linked instance definition, + skip any linked instance definitions found in that file. + false: + When reading the file that defines the content of the linked instance definition, + recursively load linked instance definitions found in that file. + */ + bool SkipNestedLinkedDefinitions() const; + + void SetSkipNestedLinkedDefinitions( + bool bSkipNestedLinkedDefinitions + ); + +private: + // list of object ids in the instance geometry table. + ON_SimpleArray m_object_uuid; + +private: + ON_wString m_description; + ON_wString m_url; + ON_wString m_url_tag; // UI link text for m_url + +private: + ON_BoundingBox m_bbox = ON_BoundingBox::EmptyBoundingBox; + +private: + ON_UnitSystem m_us = ON_UnitSystem::None; + +private: + // Note: the embedded_def type is obsolete. + // To avoid having to deal with this obsolete type in + // your code, using ON_InstanceDefintion::IdefUpdateType() + // to get this value. The IdefUpdateType() function + // with convert the obsolte value to the correct + // value. + ON_InstanceDefinition::IDEF_UPDATE_TYPE m_idef_update_type = ON_InstanceDefinition::IDEF_UPDATE_TYPE::Static; + +private: + bool m_bSkipNestedLinkedDefinitions = false; + +private: + ///////////////////////////////////////////////////////////// + // + // linked instance definition internals + // +private: + ON_FileReference m_linked_file_reference; + + // For V5 3dm archive compatibility. + // Set as needed by the Write() function for new idefs and saved if the idef is read from a V5 file. +private: + mutable ON_CheckSum m_linked_file_V5_checksum = ON_CheckSum::UnsetCheckSum; +private: + bool Internal_SetLinkedFileReference( + ON_InstanceDefinition::IDEF_UPDATE_TYPE linked_definition_type, + const ON_FileReference& linked_file_reference, + ON_CheckSum V5_checksum + ); + + // See comment for Internal_ReferencedComponentSettings() function. +private: + mutable class ON_ReferencedComponentSettings* m_linked_idef_component_settings = nullptr; + +public: + + /// + /// ON_InstanceDefinition::LinkedComponentStates specifies how model components + /// (layers, materials, dimension styles, ...) from linked instance defintion files + /// are appear in the active model. + /// + enum class eLinkedComponentAppearance : unsigned char + { + /// + /// This is the only valid layer style when the instance definition type is + /// ON_InstanceDefinition::IDEF_UPDATE_TYPE::Static or + /// ON_InstanceDefinition::IDEF_UPDATE_TYPE::LinkedAndEmbedded. + /// This style is not valid when the instance definition type + /// ON_InstanceDefinition::IDEF_UPDATE_TYPE::Linked. + /// + Unset = 0, + + /// + /// Model components (layers, materials, dimension styles, ...) from + /// linked instance definition files are embedded as ordinary components + /// in the active model. + /// This layer style may be used when the instance definition type is + /// ON_InstanceDefinition::IDEF_UPDATE_TYPE::Linked. + /// + Active = 1, + + /// + /// Layers from the linked instance definition are reference components in the model. + /// This is the default layer style when the instance definition type is + /// ON_InstanceDefinition::IDEF_UPDATE_TYPE::Linked. + /// This layer style may be used when the instance definition type is + /// ON_InstanceDefinition::IDEF_UPDATE_TYPE::Linked. + /// + Reference = 2 + }; + + static ON_InstanceDefinition::eLinkedComponentAppearance LinkedComponentAppearanceFromUnsigned( + unsigned int linked_component_appearance_as_unsigned + ); + + ON_InstanceDefinition::eLinkedComponentAppearance LinkedComponentAppearance() const; + + bool SetLinkedComponentAppearance( + ON_InstanceDefinition::eLinkedComponentAppearance linked_component_appearance + ); + +private: + ON_InstanceDefinition::eLinkedComponentAppearance m_linked_component_appearance = ON_InstanceDefinition::eLinkedComponentAppearance::Unset; + +public: + + /* + Returns: + A SHA-1 hash of these instance defintions properties: + + InstanceGeometryIdList() + BoundingBox() + UnitSystem() + InstanceDefinitionType() + LinkedFileReference() + LinkedComponentAppearance() + */ + const ON_SHA1_Hash GeometryContentHash() const; + + /* + Returns: + A SHA-1 hash of these instance defintions properties + Description() + URL() + URL_Tag() + and all the properties that contribute to the GeometryContentHash(). + */ + const ON_SHA1_Hash ContentHash() const; + +private: + void Internal_AccumulateHash() const; + +private: + // Internal_AccumulateHash() uses lazy evaluation to set m_geometry_content_hash when needed. + mutable ON_SHA1_Hash m_geometry_content_hash = ON_SHA1_Hash::ZeroDigest; + + // Internal_AccumulateHash() uses lazy evaluation to set m_content_hash when needed. + mutable ON_SHA1_Hash m_content_hash = ON_SHA1_Hash::ZeroDigest; + +private: + // Increments content version number and sets hashes to ON_SHA1_Hash::ZeroDigest. + void Internal_ContentChanged(); + +private: + unsigned char m_reserved2A = 0; + unsigned char m_reserved2B = 0; + unsigned char m_reserved2C = 0; + +private: + unsigned int m_reserved1 = 0; + +private: + ON__UINT_PTR m_reserved_ptr = 0; +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray; +#endif + +/* +Description: + An ON_InstanceRef is a reference to an instance definition + along with transformation to apply to the definition. +See Also: + ON_InstanceRef +*/ +class ON_CLASS ON_InstanceRef : public ON_Geometry +{ + ON_OBJECT_DECLARE(ON_InstanceRef); + +public: + ON_InstanceRef() = default; + ~ON_InstanceRef() = default; + ON_InstanceRef(const ON_InstanceRef&) = default; + ON_InstanceRef& operator=(const ON_InstanceRef&) = default; + +public: + ///////////////////////////////////////////////////////////// + // + // virtual ON_Object overrides + // + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + bool Write( + ON_BinaryArchive& binary_archive + ) const override; + bool Read( + ON_BinaryArchive& binary_archive + ) override; + ON::object_type ObjectType() const override; + + ///////////////////////////////////////////////////////////// + // + // virtual ON_Geometry overrides + // + int Dimension() const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + bool Transform( + const ON_Xform& xform + ) override; + + // virtual ON_Geometry::IsDeformable() override + bool IsDeformable() const override; + + // virtual ON_Geometry::MakeDeformable() override + bool MakeDeformable() override; + + ///////////////////////////////////////////////////////////// + // + + // Unique id of the instance definition (ON_InstanceDefinition) + // in the instance definition table that defines the geometry + // used by this reference. + ON_UUID m_instance_definition_uuid = ON_nil_uuid; + + // Transformation for this reference. + ON_Xform m_xform = ON_Xform::IdentityTransformation; + + // Bounding box for this reference. + ON_BoundingBox m_bbox; + +#if 0 +public: + /* + Remove all reference to the nested linked idef information. + */ + void ClearReferenceToNestedLinkedIdef(); + + /* + Returns: + true + if input was valid and the reference to the nested linked idef was set. + false + if reference to the nested linked idef was not set. + */ + bool SetReferenceToNestedLinkedIdef( + const ON_UUID& parent_idef_uuid, + const ON_FileReference& parent_reference_file, + const ON_FileReference& nested_reference_file + ); + + /* + Parameters: + parent_idef_uuid - [in] + The persistent id of the parent idef that contains the (possibly deeply nested) + instance definion this reference refers to. + parent_reference_file - [in] + the file for the parent idef. + nested_reference_file - [in] + if the referenced idef is itself linked, nested_reference_file identifies + the file. + + Returns: + True if this is a reference to a nested linked idef. + */ + bool GetReferenceToNestedLinkedIdef( + ON_UUID& parent_idef_uuid, + ON_FileReference& parent_reference_file, + ON_FileReference& nested_reference_file + ) const; + + /* + Returns: + True if this is a reference to a nested linked idef. + */ + bool ContainsReferenceToNestedLinkedIdef() const; + +private: + ///////////////////////////////////////////////////////////// + // + // Additional information used when this reference is to + // an instance definition that is nested inside an ordinary + // linked instance definition. + // + // For example, if + // idefA = linked instance defintion referencing file A. + // idefX = any type of instance definition found in idefA. + // + // iref = model geometry reference to idefX. + // + // When A is not a 3dm file or the 3dm id of idefX is + // in use in the current model, the id of idefX will change + // every time A is read. This means saving the value of + // iref.m_instance_definition_uuid is not sufficient to identify + // idefX. In this case, the additional information + // + // iref.m_bReferenceToNestedLinkedIdef = true + // iref.m_parent_idef_uuid = idefA.Id() + // iref.m_parent_reference_file = idefA.FileReference(). + // iref.m_nested_reference_file = idefX.FileReference(). + // + // is used to identify idefX in a persistent way. + // + bool m_bReferenceToNestedLinkedIdef = false; + ON_UUID m_parent_idef_uuid = ON_nil_uuid; // persistent id + ON_FileReference m_parent_reference_file = ON_FileReference::Unset; + ON_FileReference m_nested_reference_file = ON_FileReference::Unset; +#endif + +public: + // Tolerance to use for flagging instance xforms + // as singular. + // A valid ON_InstanceRef.m_xform satisfies: + // true == (m_xform.Inverse()*m_xform).IsIdentity(ON_InstanceRef::SingularTransformationTolerance) + static const double SingularTransformationTolerance; +}; + +#endif diff --git a/opennurbs/Include/opennurbs_internal_V2_annotation.h b/opennurbs/Include/opennurbs_internal_V2_annotation.h new file mode 100644 index 0000000..cfe238d --- /dev/null +++ b/opennurbs/Include/opennurbs_internal_V2_annotation.h @@ -0,0 +1,377 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_INTERNAL_V2_ANNOTATION_H_INC) +#define OPENNURBS_INTERNAL_V2_ANNOTATION_H_INC + +#if defined(ON_COMPILING_OPENNURBS) + +#include "opennurbs_internal_defines.h" + +// Annotation classes used in version 2 .3dm archives and Rhino version 2. +// All classes in this file are obsolete. They exist so that old files can be read. + +// Legacy annotation arrow is in some old .3dm files. +// Gets converted to an ON_Line with ON_3dmObjectAttributes arrow head +// ON_3dmObjectAttributes.m_object_decoration = (ON::end_arrowhead | other bits) +class ON_OBSOLETE_V2_AnnotationArrow : public ON_Geometry +{ + // 3d annotation arrow + ON_OBJECT_DECLARE(ON_OBSOLETE_V2_AnnotationArrow); +public: + ON_OBSOLETE_V2_AnnotationArrow(); + ~ON_OBSOLETE_V2_AnnotationArrow(); + ON_OBSOLETE_V2_AnnotationArrow(const ON_OBSOLETE_V2_AnnotationArrow&); + ON_OBSOLETE_V2_AnnotationArrow& operator=(const ON_OBSOLETE_V2_AnnotationArrow&); + + ///////////////////////////////////////////////////////////////// + // + // ON_Object overrides + // + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + void Dump( ON_TextLog& ) const override; // for debugging + + bool Write( + ON_BinaryArchive& // serialize definition to binary archive + ) const override; + + bool Read( + ON_BinaryArchive& // restore definition from binary archive + ) override; + + ON::object_type ObjectType() const override; + + ///////////////////////////////////////////////////////////////// + // + // ON_Geometry overrides + // + + int Dimension() const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + bool Transform( + const ON_Xform& + ) override; + + ///////////////////////////////////////////////////////////////// + // + // Interface + // + ON_3dVector Vector() const; + ON_3dPoint Head() const; + ON_3dPoint Tail() const; + + ON_3dPoint m_tail; + ON_3dPoint m_head; +}; + +class ON_OBSOLETE_V2_TextDot : public ON_Point +{ + // 3d annotation dot with text + ON_OBJECT_DECLARE(ON_OBSOLETE_V2_TextDot); +public: + ON_OBSOLETE_V2_TextDot(); + ~ON_OBSOLETE_V2_TextDot(); + ON_OBSOLETE_V2_TextDot(const ON_OBSOLETE_V2_TextDot&); + ON_OBSOLETE_V2_TextDot& operator=(const ON_OBSOLETE_V2_TextDot&); + + ///////////////////////////////////////////////////////////////// + // + // ON_Object overrides + // + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + void Dump( ON_TextLog& ) const override; // for debugging + + bool Write( + ON_BinaryArchive& // serialize definition to binary archive + ) const override; + + bool Read( + ON_BinaryArchive& // restore definition from binary archive + ) override; + + ON_wString m_text; +}; + + +//////////////////////////////////////////////////////////////// +// +// ON_OBSOLETE_V2_Annotation - used to serialize definitions of annotation +// objects (dimensions, text blocks, etc.). +// + +class ON_OBSOLETE_V2_Annotation : public ON_Geometry +{ + ON_OBJECT_DECLARE(ON_OBSOLETE_V2_Annotation); + +protected: + ON_OBSOLETE_V2_Annotation() = default; + ON_OBSOLETE_V2_Annotation(const ON_OBSOLETE_V2_Annotation&) = default; + ON_OBSOLETE_V2_Annotation& operator=(const ON_OBSOLETE_V2_Annotation&) = default; + +public: + virtual ~ON_OBSOLETE_V2_Annotation() = default; + +protected: + void Internal_Initialize(); // initialize class's fields assuming + // memory is uninitialized + +public: + static ON_OBSOLETE_V2_Annotation* CreateFromV5Annotation( + const class ON_OBSOLETE_V5_Annotation& V5_annotation, + const class ON_3dmAnnotationContext* annotation_context + ); + + static ON_OBSOLETE_V2_Annotation* CreateFromV6Annotation( + const class ON_Annotation& V6_annotation, + const class ON_3dmAnnotationContext* annotation_context + ); + +protected: + void Internal_InitializeFromV5Annotation( + const ON_OBSOLETE_V5_Annotation& V5_annotation, + const class ON_3dmAnnotationContext* annotation_context + ); + +public: + void Destroy(); + void EmergencyDestroy(); + + ///////////////////////////////////////////////////////////////// + // + // ON_Object overrides + // + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + void Dump( ON_TextLog& ) const override; // for debugging + + bool Write( + ON_BinaryArchive& // serialize definition to binary archive + ) const override; + + bool Read( + ON_BinaryArchive& // restore definition from binary archive + ) override; + + ON::object_type ObjectType() const override; + + ///////////////////////////////////////////////////////////////// + // + // ON_Geometry overrides + // + + int Dimension() const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + bool Transform( + const ON_Xform& + ) override; + + ///////////////////////////////////////////////////////////////// + // + // ON_OBSOLETE_V2_Annotation interface + // + + // use these to get/set the current annotation settings + static const ON_3dmAnnotationSettings& AnnotationSettings(); + static void SetAnnotationSettings( const ON_3dmAnnotationSettings* ); + + bool IsText() const; + bool IsLeader() const; + bool IsDimension() const; + + virtual double NumericValue() const; + virtual void SetTextToDefault(); + + void SetType( ON_INTERNAL_OBSOLETE::V5_eAnnotationType type ); + ON_INTERNAL_OBSOLETE::V5_eAnnotationType Type() const; + void SetTextDisplayMode( ON_INTERNAL_OBSOLETE::V5_TextDisplayMode mode); + ON_INTERNAL_OBSOLETE::V5_TextDisplayMode TextDisplayMode() const; + + void SetPlane( const ON_Plane& plane ); + ON_Plane Plane() const; + int PointCount() const; + void SetPoints( const ON_SimpleArray& points ); + const ON_SimpleArray& Points() const; + void SetPoint( int idx, ON_3dPoint point ); + ON_2dPoint Point( int idx ) const; + void SetUserText( const wchar_t* string ); + const ON_wString& UserText() const; + void SetDefaultText( const wchar_t* string ); + const ON_wString& DefaultText() const; + void SetUserPositionedText( int bUserPositionedText ); + bool UserPositionedText() const; + + // to convert world 3d points to and from annotation 2d points + bool GetECStoWCSXform( ON_Xform& xform ) const; + bool GeWCStoECSXform( ON_Xform& xform ) const; + + ON_INTERNAL_OBSOLETE::V5_eAnnotationType m_type = ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtNothing; // enum for type of annotation + // DimLinear, DimRadius, etc. + + ON_INTERNAL_OBSOLETE::V5_TextDisplayMode m_textdisplaymode = ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kNormal; // how the text is displayed + // Horizontal, InLine, AboveLine + + ON_Plane m_plane = ON_Plane::World_xy; // ECS reference plane in WCS coordinates + ON_SimpleArray m_points; // Definition points for the dimension + + ON_wString m_usertext; // "<>", or user override + ON_wString m_defaulttext; // The displayed text string + + bool m_userpositionedtext = false; // true: User has positioned text + // false: use default location +}; + +class ON_OBSOLETE_V2_DimLinear : public ON_OBSOLETE_V2_Annotation +{ + ON_OBJECT_DECLARE(ON_OBSOLETE_V2_DimLinear); + +public: + ON_OBSOLETE_V2_DimLinear(); + ON_OBSOLETE_V2_DimLinear(const ON_OBSOLETE_V2_DimLinear&); + ~ON_OBSOLETE_V2_DimLinear(); + ON_OBSOLETE_V2_DimLinear& operator=(const ON_OBSOLETE_V2_DimLinear&); + + double NumericValue() const override; + void SetTextToDefault() override; + void EmergencyDestroy(); + + static ON_OBSOLETE_V2_DimLinear* CreateFromV5LinearDimension( + const class ON_OBSOLETE_V5_DimLinear& V5_linear_dimension, + const class ON_3dmAnnotationContext* annotation_context, + ON_OBSOLETE_V2_DimLinear* destination + ); +}; + +class ON_OBSOLETE_V2_DimRadial : public ON_OBSOLETE_V2_Annotation +{ + ON_OBJECT_DECLARE(ON_OBSOLETE_V2_DimRadial); + +public: + ON_OBSOLETE_V2_DimRadial(); + ON_OBSOLETE_V2_DimRadial(const ON_OBSOLETE_V2_DimRadial&); + ~ON_OBSOLETE_V2_DimRadial(); + ON_OBSOLETE_V2_DimRadial& operator=(const ON_OBSOLETE_V2_DimRadial&); + + double NumericValue() const override; + void SetTextToDefault() override; + + void EmergencyDestroy(); + + static ON_OBSOLETE_V2_DimRadial* CreateFromV5RadialDimension( + const class ON_OBSOLETE_V5_DimRadial& V5_linear_dimension, + const class ON_3dmAnnotationContext* annotation_context, + ON_OBSOLETE_V2_DimRadial* destination + ); +}; + +class ON_OBSOLETE_V2_DimAngular : public ON_OBSOLETE_V2_Annotation +{ + ON_OBJECT_DECLARE(ON_OBSOLETE_V2_DimAngular); + +public: + ON_OBSOLETE_V2_DimAngular(); + ON_OBSOLETE_V2_DimAngular(const ON_OBSOLETE_V2_DimAngular&); + ~ON_OBSOLETE_V2_DimAngular(); + ON_OBSOLETE_V2_DimAngular& operator=(const ON_OBSOLETE_V2_DimAngular&); + + static ON_OBSOLETE_V2_DimAngular* CreateFromV5AngularDimension( + const class ON_OBSOLETE_V5_DimAngular& V5_angular_dimension, + const class ON_3dmAnnotationContext* annotation_context, + ON_OBSOLETE_V2_DimAngular* destination + ); + + void EmergencyDestroy(); + + bool Write( ON_BinaryArchive& file ) const override; + bool Read( ON_BinaryArchive& file ) override; + + void SetAngle( double angle ) { m_angle = angle; } + double Angle() const { return m_angle; } + void SetRadius( double radius ) { m_radius = radius; } + double Radius() const { return m_radius; } + + double NumericValue() const override; + void SetTextToDefault() override; + +private: + double m_angle; // angle being dimensioned + double m_radius; // radius for dimension arc +}; + +class ON_OBSOLETE_V2_TextObject : public ON_OBSOLETE_V2_Annotation +{ + ON_OBJECT_DECLARE(ON_OBSOLETE_V2_TextObject); + +public: + ON_OBSOLETE_V2_TextObject(); + ON_OBSOLETE_V2_TextObject(const ON_OBSOLETE_V2_TextObject&); + ~ON_OBSOLETE_V2_TextObject(); + ON_OBSOLETE_V2_TextObject& operator=(const ON_OBSOLETE_V2_TextObject&); + + static ON_OBSOLETE_V2_TextObject* CreateFromV5TextObject( + const class ON_OBSOLETE_V5_TextObject& V5_text_object, + const class ON_3dmAnnotationContext* annotation_context, + ON_OBSOLETE_V2_TextObject* destination + ); + + void EmergencyDestroy(); + + bool Write( ON_BinaryArchive& file ) const override; + bool Read( ON_BinaryArchive& file ) override; + + void SetFaceName( ON_wString string ) { m_facename = string; } + ON_wString FaceName() const { return m_facename; } + void SetFontWeight( int weight ) { m_fontweight = weight; } + int FontWeight() const { return m_fontweight; } + void SetHeight( double height ) { m_height = height; } + double Height() const { return m_height; } + + +private: + ON_wString m_facename; + int m_fontweight; // windows - 400 = NORMAL ) + double m_height; // gets multiplied by dimscale +}; + +class ON_OBSOLETE_V2_Leader : public ON_OBSOLETE_V2_Annotation +{ + ON_OBJECT_DECLARE(ON_OBSOLETE_V2_Leader); + +public: + ON_OBSOLETE_V2_Leader(); + ON_OBSOLETE_V2_Leader(const ON_OBSOLETE_V2_Leader&); + ~ON_OBSOLETE_V2_Leader(); + ON_OBSOLETE_V2_Leader& operator=(const ON_OBSOLETE_V2_Leader&); + + static ON_OBSOLETE_V2_Leader* CreateFromV5Leader( + const class ON_OBSOLETE_V5_Leader& V5_leader, + const class ON_3dmAnnotationContext* annotation_context, + ON_OBSOLETE_V2_Leader* destination + ); + + void EmergencyDestroy(); +}; + +#endif +#endif + diff --git a/opennurbs/Include/opennurbs_internal_V5_annotation.h b/opennurbs/Include/opennurbs_internal_V5_annotation.h new file mode 100644 index 0000000..fb07fd2 --- /dev/null +++ b/opennurbs/Include/opennurbs_internal_V5_annotation.h @@ -0,0 +1,2117 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#ifndef OPENNURBS_INTERNAL_V5_ANNOTATION_H_INC +#define OPENNURBS_INTERNAL_V5_ANNOTATION_H_INC + +#if defined(ON_COMPILING_OPENNURBS) +// V5 annotation classes are internal to opennurbs and are used exclusively +// to support reading and writing V5 3dm archives. + +#if defined(ON_OS_WINDOWS_GDI) +#define ON_OBSOLETE_V5_RECT RECT +#else +typedef struct tagON_RECT +{ + int left; + int top; + int right; + int bottom; +} ON_OBSOLETE_V5_RECT; +#endif + +class ON_OBSOLETE_V5_AnnotationText : public ON_wString +{ +public: + ON_OBSOLETE_V5_AnnotationText(); + ~ON_OBSOLETE_V5_AnnotationText(); + + + ON_OBSOLETE_V5_AnnotationText& operator=(const char*); + ON_OBSOLETE_V5_AnnotationText& operator=(const wchar_t*); + + void SetText( const char* s ); + void SetText( const wchar_t* s ); + + // m_rect is a Windows gdi RECT that bounds text + // ("x" increases to the right and "y" increases downwards). + // If all fields are 0, then m_rect is not set. + // If left < right and top < bottom, then the rect bounds + // the text when it is drawn with its font's + // lfHeight=ON_Font::Constants::AnnotationFontCellHeight and (0,0) left baseline + // point of the leftmost character on the first line + // of text. If (x,y) is a point on the drawn text, then + // left <= x < right and top <= y < bottom. + ON_OBSOLETE_V5_RECT m_rect; +}; + +// Extension to ON_OBSOLETE_V2_TextObject added 12/10/2009 for Text background drawing +class ON_OBSOLETE_V5_TextExtra : public ON_UserData +{ + ON_OBJECT_DECLARE(ON_OBSOLETE_V5_TextExtra); +public: + + ON_OBSOLETE_V5_TextExtra(); + ~ON_OBSOLETE_V5_TextExtra(); + + static + ON_OBSOLETE_V5_TextExtra* TextExtension(class ON_OBSOLETE_V5_TextObject* pDim, bool bCreate); + static const + ON_OBSOLETE_V5_TextExtra* TextExtension(const class ON_OBSOLETE_V5_TextObject* pDim, bool bCreate); + + void SetDefaults(); + + // override virtual ON_Object::Dump function + void Dump( ON_TextLog& text_log ) const override; + + // override virtual ON_Object::Dump function + unsigned int SizeOf() const override; + + // override virtual ON_Object::Write function + bool Write(ON_BinaryArchive& binary_archive) const override; + + // override virtual ON_Object::Read function + bool Read(ON_BinaryArchive& binary_archive) override; + + // override virtual ON_UserData::GetDescription function + bool GetDescription( ON_wString& description ) override; + + // override virtual ON_UserData::Archive function + bool Archive() const override; + + ON_UUID ParentUUID() const; + void SetParentUUID( ON_UUID parent_uuid); + + bool DrawTextMask() const; + void SetDrawTextMask(bool bDraw); + + int MaskColorSource() const; + void SetMaskColorSource(int source); + + ON_Color MaskColor() const; // Only works right if MaskColorSource returns 2. + // Does not return viewport background color + void SetMaskColor(ON_Color color); + + double MaskOffsetFactor() const; + void SetMaskOffsetFactor(double offset); + + ON_UUID m_parent_uuid; // uuid of the text using this extension + + bool m_bDrawMask; // do or don't draw a mask + + int m_color_source; // 0: Use background color from viewport + // 1: Use specific color from m_mask_color + + ON_Color m_mask_color; // Color to use for mask if m_color_source is 2 + + double m_border_offset; // Offset for the border around text to the rectangle used to draw the mask + // This number * HeightOfI for the text is the offset on each side of the + // tight rectangle around the text characters to the mask rectangle. +}; + + +class ON_OBSOLETE_V5_DimExtra : public ON_UserData +{ + ON_OBJECT_DECLARE(ON_OBSOLETE_V5_DimExtra); +public: + + ON_OBSOLETE_V5_DimExtra(); + ~ON_OBSOLETE_V5_DimExtra(); + + static + ON_OBSOLETE_V5_DimExtra* DimensionExtension(class ON_OBSOLETE_V5_DimLinear* pDim, bool bCreate); + static const + ON_OBSOLETE_V5_DimExtra* DimensionExtension(const class ON_OBSOLETE_V5_DimLinear* pDim, bool bCreate); + static + ON_OBSOLETE_V5_DimExtra* DimensionExtension(class ON_OBSOLETE_V5_DimRadial* pDim, bool bCreate); + static const + ON_OBSOLETE_V5_DimExtra* DimensionExtension(const class ON_OBSOLETE_V5_DimRadial* pDim, bool bCreate); + static + ON_OBSOLETE_V5_DimExtra* DimensionExtension(class ON_OBSOLETE_V5_DimOrdinate* pDim, bool bCreate); + static const + ON_OBSOLETE_V5_DimExtra* DimensionExtension(const class ON_OBSOLETE_V5_DimOrdinate* pDim, bool bCreate); + + void SetDefaults(); + + // override virtual ON_Object::Dump function + void Dump( ON_TextLog& text_log ) const override; + + // override virtual ON_Object::Dump function + unsigned int SizeOf() const override; + + // override virtual ON_Object::Write function + bool Write(ON_BinaryArchive& binary_archive) const override; + + // override virtual ON_Object::Read function + bool Read(ON_BinaryArchive& binary_archive) override; + + // override virtual ON_UserData::GetDescription function + bool GetDescription( ON_wString& description ) override; + + // override virtual ON_UserData::Archive function + bool Archive() const override; + + ON_UUID ParentUUID() const; + void SetParentUUID( ON_UUID parent_uuid); + + // 0: default position + // 1: force inside + // -1: force outside + int ArrowPosition() const; + void SetArrowPosition( int position); + + // For a dimension in page space that measures between points in model space + // of a detail view, this is the ratio of the page distance / model distance. + // When the dimension text is displayed, the distance measured in model space + // is multiplied by this number to get the value to display. + double DistanceScale() const; + void SetDistanceScale(double s); + + // Basepont in modelspace coordinates for ordinate dimensions + void SetModelSpaceBasePoint(ON_3dPoint basepoint); + ON_3dPoint ModelSpaceBasePoint() const; + + // If this dimension measures objects in the model space of a detail view + // this is the detail view, otherwise, nil_uuid + ON_UUID DetailMeasured() const; + void SetDetailMeasured(ON_UUID detail_id); + + //const wchar_t* ToleranceUpperString() const; + //ON_wString& ToleranceUpperString(); + //void SetToleranceUpperString( const wchar_t* upper_string); + //void SetToleranceUpperString( ON_wString& upper_string); + + //const wchar_t* ToleranceLowerString() const; + //ON_wString& ToleranceLowerString(); + //void SetToleranceLowerString( const wchar_t* lower_string); + //void SetToleranceLowerString( ON_wString& lower_string); + + //const wchar_t* AlternateString() const; + //ON_wString& AlternateString(); + //void SetAlternateString( const wchar_t* alt_string); + //void SetAlternateString( ON_wString& alt_string); + + //const wchar_t* AlternateToleranceUpperString() const; + //ON_wString& AlternateToleranceUpperString(); + //void SetAlternateToleranceUpperString( const wchar_t* upper_string); + //void SetAlternateToleranceUpperString( ON_wString& upper_string); + + //const wchar_t* AlternateToleranceLowerString() const; + //ON_wString& AlternateToleranceLowerString(); + //void SetAlternateToleranceLowerString( const wchar_t* lower_string); + //void SetAlternateToleranceLowerString( ON_wString& lower_string); + + ON_UUID m_partent_uuid; // the dimension using this extension + + int m_arrow_position; + + // This is either nullptr or an array of GDI rects for the substrings + // that make up the dimension string. + // If the dimension text is all on the same line, there is just one + // rectangle needed to bound the text and that is the same as the + // m_rect on the ON_OBSOLETE_V5_AnnotationText. + // If the dimension has tolerances or for some other reason has more + // than one line of text, m_text_rects is an array of 7 rects, one + // each for the substrings that might be needed to display the dimension. + // If some of the rects aren't used, they are empty at 0,0 + // The strings that correspond to these rectangles are generated from + // info in the dimstyle + ON_OBSOLETE_V5_RECT* m_text_rects; + + double m_distance_scale; + ON_3dPoint m_modelspace_basepoint; + + // If this dimension measures objects in the model space of a detail view + // this is the detail view + // 27 Aug, 2014, v6 + ON_UUID m_detail_measured; +}; + + +/* + class ON_OBSOLETE_V5_Annotation + + Description: + Used to serialize definitions of annotation objects (dimensions, text, leaders, etc.). + Virtual base class for annotation objects + Replaces ON_OBSOLETE_V2_Annotation +*/ +class ON_OBSOLETE_V5_Annotation : public ON_Geometry +{ + ON_OBJECT_DECLARE(ON_OBSOLETE_V5_Annotation); + +protected: + ON_OBSOLETE_V5_Annotation(); + ON_OBSOLETE_V5_Annotation(const ON_OBSOLETE_V5_Annotation&) = default; + ON_OBSOLETE_V5_Annotation& operator=(const ON_OBSOLETE_V5_Annotation&) = default; + +public: + virtual ~ON_OBSOLETE_V5_Annotation(); + +protected: + void Internal_InitializeFromV2Annotation( + const class ON_OBSOLETE_V2_Annotation& V2_annotation, + const class ON_3dmAnnotationContext* annotation_context + ); + +public: + static ON_OBSOLETE_V5_Annotation* CreateFromV2Annotation( + const class ON_OBSOLETE_V2_Annotation& V2_annotation, + const class ON_3dmAnnotationContext* annotation_context + ); + +public: + static ON_OBSOLETE_V5_Annotation* CreateFromV6Annotation( + const class ON_Annotation& V6_annotation, + const class ON_3dmAnnotationContext* annotation_context + ); + +protected: + ////void Internal_SetDimStyleFromV6Annotation( + //// const class ON_Annotation& V6_annotation, + //// const class ON_3dmAnnotationContext* annotation_context + ////); + +public: + + // Description: + // Sets initial defaults + void Create(); + + void Destroy(); + + void EmergencyDestroy(); + + ///////////////////////////////////////////////////////////////// + // + // ON_Object overrides + // + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + + /* + Description: Writes the object to a file + + Returns: + @untitled Table + true Success + false Failure + */ + bool Write( + ON_BinaryArchive& + ) const override; + + /* + Description: Reads the object from a file + + Returns: + @untitled Table + true Success + false Failure + */ + bool Read( + ON_BinaryArchive& + ) override; + + /* + Returns: The Object Type of this object + */ + ON::object_type ObjectType() const override; + + ///////////////////////////////////////////////////////////////// + // + // ON_Geometry overrides + // + + /* + Returns the geometric dimension of the object ( usually 3) + */ + int Dimension() const override; + + // overrides virtual ON_Geometry::Transform() + bool Transform( const ON_Xform& xform ) override; + + // virtual ON_Geometry override + bool EvaluatePoint( const class ON_ObjRef& objref, ON_3dPoint& P ) const override; + + ///////////////////////////////////////////////////////////////// + // + // ON_OBSOLETE_V5_Annotation interface + // + + // Definitions of text justification + // Not implemented on all annotation objects + enum eTextJustification + { + tjUndefined = 0, + tjLeft = 1<<0, + tjCenter = 1<<1, + tjRight = 1<<2, + tjBottom = 1<<16, + tjMiddle = 1<<17, + tjTop = 1<<18, + tjBottomLeft = tjBottom | tjLeft, + tjBottomCenter = tjBottom | tjCenter, + tjBottomRight = tjBottom | tjRight, + tjMiddleLeft = tjMiddle | tjLeft, + tjMiddleCenter = tjMiddle | tjCenter, + tjMiddleRight = tjMiddle | tjRight, + tjTopLeft = tjTop | tjLeft, + tjTopCenter = tjTop | tjCenter, + tjTopRight = tjTop | tjRight, + }; + + /* + Description: + Query if the annotation object is a text object + Parameters: + none + Returns: + @untitled table + true It is text + false Its not text + */ + bool IsText() const; + + /* + Description: + Query if the annotation object is a leader + Parameters: + none + Returns: + @untitled table + true It is a leader + false Its not a leader + */ + bool IsLeader() const; + + /* + Description: + Query if the annotation object is a dimension + Parameters: + none + Returns: + @untitled table + true It is a dimension + false Its not a dimension + */ + bool IsDimension() const; + +public: + int V5_3dmArchiveDimStyleIndex() const; + + /* + Description: + If IsText() is false, the dimension style is set. + */ + void SetV5_3dmArchiveDimStyleIndex( + int V5_dim_style_index + ); + + ////ON_UUID V6_DimStyleId() const; + + + + /////* + ////Description: + //// If IsText() is false, the dimension style is set. + ////*/ + ////void SetV6_DimStyleId( + //// ON_UUID dim_style_id, + //// int V5_dim_style_index + //// ); + + ////const ON_DimStyle* V6_DimStyleOverride() const; + + /////* + ////Description: + //// If IsText() is false, the dimension style is set. + ////*/ + ////void SetV6_DimStyleOverride( + //// const ON_DimStyle* dim_style_override, + //// int V5_dim_style_index + //// ); + +public: + + /* + Returns: + Dimension type + Linear dim: distance between arrow tips + Radial dim: radius or diameter depending on m_type value + Angular dim: angle in degrees + Leader: ON_UNSET_VALUE + Text: ON_UNSET_VALUE + */ + virtual + double NumericValue() const; + + /* + Description: + Set or Get the height of the text in this annotation + Parameters: + [in] double new text height to set + Returns: + double Height of the text + Remarks: + Height is in model units + */ + void SetHeight( double); + double Height() const; + + /* + Description: + Sets or gets the object type member to a specific annotation type: + dtDimLinear, dtDimAligned, dtDimAngular, etc. + Parameters: + [in] ON_INTERNAL_OBSOLETE::V5_eAnnotationType type - dtDimLinear, dtDimAligned, dtDimAngular, etc. + Returns: + ON_INTERNAL_OBSOLETE::V5_eAnnotationType of the object + */ + void SetType( ON_INTERNAL_OBSOLETE::V5_eAnnotationType); + ON_INTERNAL_OBSOLETE::V5_eAnnotationType Type() const; + + /* + Description: + Set or get the plane for the object's ECS + Parameters: + [in] ON_Plane& plane in WCS + Returns: + const ON_Plane& - the object's ECS plane in WCS coords + */ + void SetPlane( const ON_Plane&); + const ON_Plane& Plane() const; + + /* + Description: + Returns the number of definition points this object has + Parameters: + none + Returns: + @untitled table + int the object's point count + */ + int PointCount() const; + void SetPointCount( int count); + + /* + Description: + Set or get the object's whole points array at once + Parameters: + [in] ON_2dPointArray& pts + Returns: + const ON_2dPointArray& - ref to the object's point array + */ + void SetPoints( const ON_2dPointArray&); + const ON_2dPointArray& Points() const; + + /* + Description: + Set individual definition points for the annotation + Parameters: + @untitled table + [in] int index index of the point to set in ECS 2d coordinates + [in] const ON_2dPoint& pt the new point value + Returns: + ON_2dPoint the point coordinates in ECS + */ + void SetPoint( int, const ON_2dPoint&); + ON_2dPoint Point( int) const; + + /* + Description: + + Set or get the string value of the user text, with no substitution for "<>" + Parameters: + [in] const wchar_t* string the new value for UserText + Returns: + const ON_wString& The object's UserText + Remarks: + UserText is the string that gets printed when the dimensoin is drawn. + If it contains the token "<>", that token is replaced with the measured + value for the dimension, formatted according to the DimStyle settings. + "<>" is the default for linear dimensions. + Other dimensions include "<>" in their default string + */ + + ON_DEPRECATED_MSG("use SetTextValue function") + void SetUserText( const wchar_t* text_value ); + + ON_DEPRECATED_MSG("use TextValue function") + const ON_wString& UserText() const; + + + /* + Description: + Gets the value of the annotation text. + Returns: + Value of the annotation text. + See Also: + ON_OBSOLETE_V5_AnnotationText::SetTextValue() + ON_OBSOLETE_V5_AnnotationText::SetTextFormula() + ON_OBSOLETE_V5_AnnotationText::TextFormula() + Remarks: + This gets the literal value of the text, there is no + substitution for any "<>" substrings. When a dimension + is drawn, any occurance of "<>" will be replaced + with the measured value for the dimension and formatted + according to the DimStyle settings. + + Annotation text values can be constant or the result + of evaluating text formula containing %<...>% + expressions. The ...TextValue() functions set + and get the text's value. The ...TextFormula() + functions get and set the text's formula. + */ + const wchar_t* TextValue() const; + + /* + Description: + Sets the value of the annotation text. No changes + are made to the text_value string. + Parameters: + text_value - [in] + Returns: + Value of the annotation text. + See Also: + ON_OBSOLETE_V5_AnnotationText::SetTextFormula() + ON_OBSOLETE_V5_AnnotationText::TextValue() + ON_OBSOLETE_V5_AnnotationText::TextFormula() + Remarks: + Annotation text values can be constant or the result + of evaluating text formula containing %<...>% + expressions. The ...TextValue() functions set + and get the text's value. The ...TextFormula() + functions get and set the text's formula. + */ + void SetTextValue( const wchar_t* text_value ); + + /* + Description: + Gets the formula for the annotation text. + Parameters: + text_value - [in] + Returns: + Value of the annotation text. + See Also: + ON_OBSOLETE_V5_AnnotationText::SetTextValue() + ON_OBSOLETE_V5_AnnotationText::TextValue() + ON_OBSOLETE_V5_AnnotationText::TextFormula() + Remarks: + Annotation text values can be constant or the result + of evaluating text formula containing %<...>% + expressions. The ...TextValue() functions set + and get the text's value. The ...TextFormula() + functions get and set the text's formula. + */ + const wchar_t* TextFormula() const; + + /* + Description: + Sets the formula for the annotation text. + Parameters: + text_value - [in] + Returns: + Value of the annotation text. + See Also: + ON_OBSOLETE_V5_AnnotationText::SetTextValue() + ON_OBSOLETE_V5_AnnotationText::Value() + ON_OBSOLETE_V5_AnnotationText::Formula() + Remarks: + Annotation text values can be constant or the result + of evaluating text formula containing %<...>% + expressions. The ...TextValue() functions set + and get the text's value. The ...TextFormula() + functions get and set the text's formula. + */ + void SetTextFormula( const wchar_t* s ); + + /* + Description: + Set or get a flag indication that the dimension text has been moved + from the default location. + Parameters: + bUserPositionedText - [in] + true to indicate that the text has been placed by the user. + false to indicate that it hasn't + Returns: + @untitled table + true The text has been moved + false The text is in the default location + Remarks: + If the text is in the default location, it should be repositioned + automatically when the dimension is adjusted. + If it has been moved, it should not be automatically positioned. + */ + void SetUserPositionedText( int bUserPositionedText ); + bool UserPositionedText() const; + + /* + Description: + Set or get the text display mode for the annotation + Parameters: + [in] ON::eTextDisplayMode mode - new mode to set + Returns: + ON::eTextDisplayMode - current mode + Remarks: + This is the way the text is oriented with respect to the dimension line or screen: + Above line, In LIne, Horizontal + */ + void SetTextDisplayMode( ON_INTERNAL_OBSOLETE::V5_TextDisplayMode); + ON_INTERNAL_OBSOLETE::V5_TextDisplayMode TextDisplayMode() const; + + + /* + Description: + Gets a transform matrix to change from the object's 2d ECS to 3d WCS + Parameters: + [out] xform set to produce the ECS to WCS transform + Returns: + @untitled table + true Success + false Failure + */ + bool GetECStoWCSXform( ON_Xform&) const; + + /* + Description: + Gets a transform matrix to change from to 3d WCS to the object's 2d ECS + Parameters: + [out] xform - set to produce the WCS to ECS transform + Returns: + @untitled table + true Success + false Failure + */ + bool GetWCStoECSXform( ON_Xform& xform) const; + + /* + Description: + Set the object's point array to a specified length + Parameters: + [in] length - the new size of the array + Returns: + void + */ + void ReservePoints( int); + + + /* + Description: + static function to provide the default UserText string for the object + Returns: + const wchar_t* - the default string to use + */ + static const wchar_t* DefaultText(); + + /* + Description: + Set or Get the text justification + Parameters: + justification [in] See enum eJustification for meanings + Returns: + The justification for the text in this object + Comments: + This is not implemented on all annotation objects. + The default SetJustification() does nothing + The default Justification() always returns 0 + + */ + virtual + void SetJustification( unsigned int justification); + + virtual unsigned int Justification() const; + + /* + Description: + Get the transformation that maps the annotation's + text to world coordinates. + Added Oct 30, 07 LW + Parameters: + gdi_text_rect - [in] + Windows gdi rect of text when it is drawn with + LOGFONT lfHeight = ON_Font::Constants::AnnotationFontCellHeight. + gdi_height_of_I - [in] + Value returned by ON_Font::HeightOfI(). + dimstyle_textheight - [in] + Height of text in world units. If the annotation is + an ON_OBSOLETE_V5_TextObject, this is the m_textheight value. + If the annotation is not an ON_OBSOLETE_V5_TextObject, pass in + the value returned by the dimension style's + ON_DimStyle::TextHeight() + dimstyle_textgap - [in] + The value of the annotation's dimension style's + ON_DimStyle::TextGap(). + dimstyle_textalignment - [in] + ON_INTERNAL_OBSOLETE::V5_TextDisplayMode(ON_DimStyle::TextAlignment()). + dimscale - [in] + Global dimension scaling value. If you are using the + Rhino SDK, this value is returned by + CRhinoDoc::Properties().AnnotationSettings().DimScale(). + If you are using the OpenNURBS IO toolkit, this value + is on ON_3dmSettings::m_AnnotationSettings.m_dimscale. + cameraX - [in] + zero or the view's unit camera right vector + cameraY - [in] + zero or the view's unit camera up vector + model_xform - [in] transforms the text's parent entity + to world coordinates in case its instance geometry + nullptr == Identity + text_xform - [out] + Returns: + True if text_xform is set. + */ + bool GetTextXform( + ON_OBSOLETE_V5_RECT gdi_text_rect, + int gdi_height_of_I, + double dimstyle_textheight, + double dimstyle_textgap, + ON_INTERNAL_OBSOLETE::V5_TextDisplayMode dimstyle_textalignment, + double dimscale, + ON_3dVector cameraX, + ON_3dVector cameraY, + const ON_Xform* model_xform, + ON_Xform& text_xform // output + ) const; + + /* + Description: + + This function has been replaced with a version that + takes a model transform to transform block instance + geometry to world coordinates Oct 30, 07 LW + + Get the transformation that maps the annotation's + text to world coordinates. + Parameters: + gdi_text_rect - [in] + Windows gdi rect of text when it is drawn with + LOGFONT lfHeight = ON_Font::Constants::AnnotationFontCellHeight. + gdi_height_of_I - [in] + Value returned by ON_Font::HeightOfI(). + dimstyle_textheight - [in] + Height of text in world units. If the annotation is + an ON_OBSOLETE_V5_TextObject, this is the m_textheight value. + If the annotation is not an ON_OBSOLETE_V5_TextObject, pass in + the value returned by the dimension style's + ON_DimStyle::TextHeight() + dimstyle_textgap - [in] + The value of the annotation's dimension style's + ON_DimStyle::TextGap(). + dimstyle_textalignment - [in] + ON_INTERNAL_OBSOLETE::V5_TextDisplayMode(ON_DimStyle::TextAlignment()). + dimscale - [in] + Global dimension scaling value. If you are using the + Rhino SDK, this value is returned by + CRhinoDoc::Properties().AnnotationSettings().DimScale(). + If you are using the OpenNURBS IO toolkit, this value + is on ON_3dmSettings::m_AnnotationSettings.m_dimscale. + cameraX - [in] + zero or the view's unit camera right vector + cameraY - [in] + zero or the view's unit camera up vector + xform - [out] + Returns: + True if xform is set. + */ + bool GetTextXform( + ON_OBSOLETE_V5_RECT gdi_text_rect, + int gdi_height_of_I, + double dimstyle_textheight, + double dimstyle_textgap, + ON_INTERNAL_OBSOLETE::V5_TextDisplayMode dimstyle_textalignment, + double dimscale, + ON_3dVector cameraX, + ON_3dVector cameraY, + ON_Xform& xform + ) const; + + /* + Description: + Get the transformation that maps the annotation's + text to world coordinates. + Oct 30, 07 LW + Parameters: + gdi_text_rect - [in] + Windows gdi rect of text when it is drawn with + LOGFONT lfHeight = ON_Font::Constants::AnnotationFontCellHeight. + font - [in] + dimstyle - [in] + dimscale - [in] + Global dimension scaling value. If you are using the + Rhino SDK, this value is returned by + CRhinoDoc::Properties().AnnotationSettings().DimScale(). + If you are using the OpenNURBS IO toolkit, this value + is on ON_3dmSettings::m_AnnotationSettings.m_dimscale. + vp - [in] + model_xform - [in] transforms the text's parent entity + to world coordinates in case its instance geometry + nullptr == Identity + text_xform - [out] + Returns: + True if text_xform is set. + */ + bool GetTextXform( + const ON_OBSOLETE_V5_RECT gdi_text_rect, + const ON_Font& font, + const ON_DimStyle* dimstyle, + double dimscale, + const ON_Viewport* vp, + const ON_Xform* model_xform, + ON_Xform& text_xform // output + ) const; + + /* + Description: + Get the annotation plane coordinates (ECS) of the point + that is used to position the text. The relative position + of the text to this points depends on the type of + annotation, the dimstyle's text alignment flag, and the + view projection. + This point is not the same as the base point of the text. + Parameters: + text_point - [out]; + Returns: + True if text_point is set. + */ + bool GetTextPoint( ON_2dPoint& text_2d_point ) const; + + // enum for tyoe of annotation DimLinear, DimRadius, etc. + ON_INTERNAL_OBSOLETE::V5_eAnnotationType m_type; + + // m_textdisplaymode controls the orientation + // of the text. + // If m_textdisplaymode = dtHorizontal, then + // the text is always horizontal and in the + // view plane. Otherwise it lies in m_plane. + ON_INTERNAL_OBSOLETE::V5_TextDisplayMode m_textdisplaymode; + + // m_plane is the plane containing the annotation. + // All parts of the annotation that are not + // text lie in this plane. If + // m_textdisplaymode != dtHorizontal, then + // the text lies in the plane too. + // (ECS reference plane in WCS coordinates.) + ON_Plane m_plane; + + // Definition points for the dimension. + // These are 2d coordinates in m_plane. + // The location of these points depends on the + // type of annotation class. There is a comment + // at the start of the definions for + // ON_OBSOLETE_V5_DimLinear, ON_OBSOLETE_V5_DimRadial, + // ON_OBSOLETE_V5_DimAngular, ON_OBSOLETE_V5_TextObject, and + // ON_OBSOLETE_V5_Leader that explains how the points are used. + ON_2dPointArray m_points; + + // With the addition of tolerances and therefore multi-line + // text, the ON_wString in m_usertext will hold multiple + // strings with NULLs between them. + // The strings will be in this order: + // Result of expanding "<>", or user override + // Alternate dimension + // Tolerance upper + // Tolerance lower + // Alt tolerance upper + // Alt tolerance lower + // Prefix + // Suffix + // Alt prefix + // Alt suffix + // + ON_OBSOLETE_V5_AnnotationText m_usertext; + + // true: User has positioned text + // false: use default location + bool m_userpositionedtext; + // Added 13 Aug, 2010 - Lowell + // This determines whether the object will be scaled according to detail + // scale factor or by 1.0 in paperspace rather than by + // dimscale or text scale. + // For the first try this will only be used on text and its + // here on the base class because it would fit and in case + // its needed later on dimensions. + bool m_annotative_scale; +private: + bool m_reserved_b1; + bool m_reserved_b2; +public: + +private: + // At this point, the ON_OBSOLETE_V5_Annotation and derived classes + // exists for a single purpose - to support reading and writing + // V5 (4,3,2) 3dm archives. + // In V5 archives all dimension styles, including per opbject overrrides + // were in the archive dimstyle table. In V6 and later, override dimstyles + // are managed by the object that uses them. + // + // This class used to have a single dimstyle table index. + // That index has been removed and replaced with the following + // information that is parallel to the information on ON_Annotation. + + // Dimstyle index to use when writing a V5 archive. + int m_v5_3dm_archive_dimstyle_index = ON_UNSET_INT_INDEX; + +public: + // Text height in model units + // This is used by text, but not by dimensions + // Dimensions get their height from dimension styles + double m_textheight; + + // Left, Center, Right / Bottom, Middle, Top text justification + // See eTextJustification above + unsigned int m_justification; +}; + + +// Subclass of ON_OBSOLETE_V5_Annotation to provide linear dimensions +class ON_OBSOLETE_V5_DimLinear : public ON_OBSOLETE_V5_Annotation +{ + ON_OBJECT_DECLARE(ON_OBSOLETE_V5_DimLinear); + +public: + + /* + The annotation's dimstyle controls the position of TEXT, + the size of the arrowheads, and the amount the ends of + linear dimension's extension lines extend beyond the + dimension lines. + + In the picture below, [n] means ON_OBSOLETE_V5_Annotation::m_points[n]. + + [2] + | + | | + [1]-------------------------------------------[3] + | | + | TEXT + | [4] + [0] + + The "x" and "y" coordinates of [0] must be (0.0, 0.0). + + The "x" coordinate of [1] = "x" of [0] + The "y" coordinate of [1] can be any value. + + The "x" and "y" coordinates of [2] can be any value. + + The "x" coordinate of [3] = "x" coordinate of [2]. + The "y" coordinate of [3] = "y" coordinate of [1]. + */ + + enum POINT_INDEX + { + // Do not change these enum values. They are saved in files as the + // ON_COMPONENT_INDEX.m_index value. + // + // Indices of linear dimension definition points in + // the m_points[] array + ext0_pt_index = 0, // end of first extension line + arrow0_pt_index = 1, // arrowhead tip on first extension line + ext1_pt_index = 2, // end of second extension line + arrow1_pt_index = 3, // arrowhead tip on second extension line + userpositionedtext_pt_index = 4, + dim_pt_count = 5, // number of m_points[] in an angular dim + + // Points calculated from values in m_points[] + text_pivot_pt = 10000, // center of dimension text + dim_mid_pt = 10001 // midpoint of dimension line + }; + +public: + ON_OBSOLETE_V5_DimLinear(); + ~ON_OBSOLETE_V5_DimLinear(); + ON_OBSOLETE_V5_DimLinear( const ON_OBSOLETE_V5_DimLinear& ) = default; + ON_OBSOLETE_V5_DimLinear& operator=(const ON_OBSOLETE_V5_DimLinear&) = default; + + /* + Description: + Create a V5 linear dimension from a V6 linear dimension. + The function is used when writing V5 files. + Parameters: + V6_dim_linear -[in] + annotation_context - [in] + Dimstyle and other informtion referenced by V6_dim_linear or nullptr if not available. + destination - [in] + If destination is not nullptr, then the V5 linear dimension is constructed + in destination. If destination is nullptr, then the new V5 linear dimension + is allocated with a call to new ON_OBSOLETE_V5_DimLinear(). + */ + static ON_OBSOLETE_V5_DimLinear* CreateFromV6DimLinear( + const class ON_DimLinear& V6_dim_linear, + const class ON_3dmAnnotationContext* annotation_context, + ON_OBSOLETE_V5_DimLinear* destination + ); + + static ON_OBSOLETE_V5_DimLinear* CreateFromV2LinearDimension( + const class ON_OBSOLETE_V2_DimLinear& V2_linear_dimension, + const class ON_3dmAnnotationContext* annotation_context, + ON_OBSOLETE_V5_DimLinear* destination + ); + + // overrides virtual ON_Geometry::Transform() + bool Transform( const ON_Xform& xform ) override; + + /* + Description: + Checks the linear dimension and repairs any point locations or flags + that are not set correctly. + Returns: + 0: linear dimension is damaged beyond repair + 1: linear dimension was perfect and nothing needed to be repaired. + 2: linear dimension had flaws that were repaired. + */ + int Repair(); + + /* + Description: + Get the m_plane coordinates of the dimension point. + Parameters: + point_index - [in] One of the POINT_INDEX enum values + Returns: + 2d point or ON_3dPoint::UnsetPoint if point_index or m_points[] + array is not valid. + */ + ON_2dPoint Dim2dPoint( + int point_index + ) const; + + /* + Description: + Get the m_plane coordinates of the dimension point. + Parameters: + point_index - [in] One of the POINT_INDEX enum values + Returns: + 2d point or ON_3dPoint::UnsetPoint if point_index or m_points[] + array is not valid. + */ + ON_3dPoint Dim3dPoint( + int point_index + ) const; + + // overrides virual ON_Object::IsValid + bool IsValid( ON_TextLog* text_log = nullptr ) const override; + + // overrides virual ON_Object::Write + bool Write(ON_BinaryArchive&) const override; + + // overrides virual ON_Object::Read + bool Read(ON_BinaryArchive&) override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + // virtual ON_Geometry GetTightBoundingBox override + bool GetTightBoundingBox( class ON_BoundingBox& tight_bbox, bool bGrowBox = false, const class ON_Xform* xform = nullptr ) const override; + + /* + Description: + Overrides virtual ON_OBSOLETE_V5_Annotation::NumericValue(); + Returns: + distance between arrow tips + */ + double NumericValue() const override; + + /* + Description: + Get or set the DimStyle index in the dimstyle table for the dimension + Parameters: + [in] int the new index (Set) + Returns: + int - The current index (Get) + */ + int StyleIndex() const; + void SetStyleIndex( int); + + /* + Description: + static function to provide the default UserText string for the object + Returns: + const wchar_t* - the default string to use + */ + static const wchar_t* DefaultText(); + + + /* + Description: + Get the annotation plane x coordinates of the dimension + line. The y coordinate of the dimension line is m_ponts[1].y. + Parameters: + gdi_text_rect - [in] + Windows rect (left < right, top < bottom) that bounds text. + The baseline of the text should be at y=0 in the rect coordinates. + gdi_height_of_I - [in] + Height of an I in the text in the same. + gdi_to_world - [in] + transform returned by ON_OBSOLETE_V5_Annotation::GetTextXform(). + dimstyle - [in] + dimscale - [in] + vp - [in] + x - [out] plane x coordinates of the dimension line. + The y coordinate = m_points[arrow0_pt_index].y + bInside - [out] true if arrowheads go inside extension lines, + false if they go outside + Returns: + 0: the input or class is not valid + 1: A single line from x[0] to x[1] with arrow heads at both ends. + Arrowtips at x[4] & x[5] + 2: Two lines from x[0] to x[1] and from x[1] to x[2]. The + Arrowtips at x[4] & x[5] + + */ + int GetDimensionLineSegments( + ON_OBSOLETE_V5_RECT gdi_text_rect, + int gdi_height_of_I, + ON_Xform gdi_to_world, + const ON_DimStyle& dimstyle, + double dimscale, + const ON_Viewport* vp, + double a[6], + bool& bInside + ) const; + + + // Added for V5. 4/24/07 LW + // Get the userdata extension for this dimension + ON_OBSOLETE_V5_DimExtra* DimensionExtension(); + const ON_OBSOLETE_V5_DimExtra* DimensionExtension() const; +}; + +////////// +// class ON_OBSOLETE_V5_DimRadial +class ON_OBSOLETE_V5_DimRadial : public ON_OBSOLETE_V5_Annotation +{ + ON_OBJECT_DECLARE(ON_OBSOLETE_V5_DimRadial); + +public: + + /* + The annotation's dimstyle controls the position of TEXT, + and the size of the arrowheads. + + In the picture below, [n] means ON_OBSOLETE_V5_Annotation::m_points[n]. + + Radial dimensions do not permit user positioned text + + + knee + [3]--------[2] TEXT + / (tail) + / + / + [1] (arrow head here) + + + + [0] = (usually at (0,0) = center of circle) + */ + + enum POINT_INDEX + { + // Do not change these enum values. They are saved in files as the + // ON_COMPONENT_INDEX.m_index value. + // + // Indices of radial dimension definition points in + // the m_points[] array + center_pt_index = 0, // location of + (usually at center of circle) + arrow_pt_index = 1, // arrow tip + tail_pt_index = 2, // end of radial dimension + knee_pt_index = 3, // number of m_points[] in a radial dim + dim_pt_count = 4, // number of m_points[] in a radial dim + + // Points calculated from values in m_points[] + text_pivot_pt = 10000, // start/end of dimension text at tail + }; + + ON_OBSOLETE_V5_DimRadial(); + ~ON_OBSOLETE_V5_DimRadial() = default; + ON_OBSOLETE_V5_DimRadial(const ON_OBSOLETE_V5_DimRadial&) = default; + ON_OBSOLETE_V5_DimRadial& operator=(const ON_OBSOLETE_V5_DimRadial&) = default; + + + static ON_OBSOLETE_V5_DimRadial* CreateFromV6DimRadial( + const class ON_DimRadial& V6_dim_radial, + const class ON_3dmAnnotationContext* annotation_context, + ON_OBSOLETE_V5_DimRadial* destination + ); + + static ON_OBSOLETE_V5_DimRadial* CreateFromV2RadialDimension( + const class ON_OBSOLETE_V2_DimRadial& V2_radial_dimension, + const class ON_3dmAnnotationContext* annotation_context, + ON_OBSOLETE_V5_DimRadial* destination + ); + + // overrides virtual ON_Geometry::Transform() + bool Transform( const ON_Xform& xform ) override; + + /* + Description: + Get the m_plane coordinates of the dimension point. + Parameters: + point_index - [in] One of the POINT_INDEX enum values + Returns: + 2d point or ON_3dPoint::UnsetPoint if point_index or m_points[] + array is not valid. + */ + ON_2dPoint Dim2dPoint( + int point_index + ) const; + + /* + Description: + Get the m_plane coordinates of the dimension point. + Parameters: + point_index - [in] One of the POINT_INDEX enum values + Returns: + 2d point or ON_3dPoint::UnsetPoint if point_index or m_points[] + array is not valid. + */ + ON_3dPoint Dim3dPoint( + int point_index + ) const; + + + // overrides virual ON_Object::IsValid + bool IsValid( ON_TextLog* text_log = nullptr ) const override; + + // overrides virual ON_Object::Write + bool Write(ON_BinaryArchive&) const override; + + // overrides virual ON_Object::Read + bool Read(ON_BinaryArchive&) override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + // virtual ON_Geometry GetTightBoundingBox override + bool GetTightBoundingBox( class ON_BoundingBox& tight_bbox, bool bGrowBox = false, const class ON_Xform* xform = nullptr ) const override; + + /* + Description: + Set the plane and definition points from WCS 3d input + Parameters: + center - [in] center of circle + arrowtip - [in] 3d point on the circle at the dimension arrow tip + xaxis - [in] x axis of the dimension's plane + normal - [in] normal to the dimension's plane + offset_distance - [in] distance from arrow tip to knee point + Returns: + @untitled table + true Success + false Failure + */ + bool CreateFromPoints( + ON_3dPoint center, + ON_3dPoint arrowtip, + ON_3dVector xaxis, + ON_3dVector normal, + double offset_distance + ); + + /* + Description: + Overrides virtual ON_OBSOLETE_V5_Annotation::NumericValue(); + Returns: + If m_type is ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter, then the diameter + is returned, othewise the radius is returned. + */ + double NumericValue() const override; + + /* + Description: + Get or set the DimStyle index in the dimstyle table for the dimension + Parameters: + [in] int the new index (Set) + Returns: + int - The current index (Get) + */ + int StyleIndex() const; + void SetStyleIndex( int); + + /* + Description: + static function to provide the default UserText string for the object + Returns: + const wchar_t* - the default string to use + */ + static const wchar_t* DefaultDiameterText(); + static const wchar_t* DefaultRadiusText(); + + bool CreateFromV2( + const class ON_OBSOLETE_V2_Annotation& v2_ann, + const class ON_3dmAnnotationSettings& settings, + int dimstyle_index + ); + + bool GetArrowHeadDirection( ON_2dVector& arrowhead_dir ) const; + bool GetArrowHeadTip( ON_2dPoint& arrowhead_tip ) const; +}; + + +////////// +// class ON_OBSOLETE_V5_DimAngular +class ON_OBSOLETE_V5_DimAngular : public ON_OBSOLETE_V5_Annotation +{ + ON_OBJECT_DECLARE(ON_OBSOLETE_V5_DimAngular); + +public: + + /* + The annotation's dimstyle controls the position of TEXT, + the size of the arrowheads, and the amount the ends of + linear dimension's extension lines extend beyond the + dimension lines. + + In the picture below, [n] means ON_OBSOLETE_V5_Annotation::m_points[n]. + + [0] = if m_userpositionedtext=true, this is the center of text. + If m_userpositionedtext=false, this point is not used and + the center of the text is at the arc's midpoint. + + Always counter clockwise arc in m_plane with center = (0,0) + [1] = a point somewhere on the line from the center through the start point. + The distance from center to [1] can be any value. + [2] = a point somewhere on the line from the center through the end point. + The distance from center to [2] can be any value. + [3] = a point on the interior of the arc. The distance + from (0,0) to [3] is the radius of the arc. + + + / + [2] + / + / [0]TEXT + / + / [3] + -----(0,0)----------[1]--- + / + / + / + + */ + + enum POINT_INDEX + { + // Do not change these enum values. They are saved in files as the + // ON_COMPONENT_INDEX.m_index value. + // + // Indices of angular dimension definition points in + // the m_points[] array + userpositionedtext_pt_index = 0, // + start_pt_index = 1, // point on the start ray (not necessarily on arc) + end_pt_index = 2, // point on the end ray (not necessarily on arc) + arc_pt_index = 3, // point on the interior of dimension arc + dim_pt_count = 4, // number of m_points[] in an angular dim + + // Points calculated from values in m_points[] + text_pivot_pt = 10000, // center of dimension text + arcstart_pt = 10001, + arcend_pt = 10002, + arcmid_pt = 10003, + arccenter_pt = 10004, // center of circle arc lies on + extension0_pt = 10005, // point where first extension line starts + extension1_pt = 10006 // point where second extension line starts + }; + +public: + ON_OBSOLETE_V5_DimAngular(); + ~ON_OBSOLETE_V5_DimAngular() = default; + ON_OBSOLETE_V5_DimAngular(const ON_OBSOLETE_V5_DimAngular&) = default; + ON_OBSOLETE_V5_DimAngular& operator=(const ON_OBSOLETE_V5_DimAngular&) = default; + + static ON_OBSOLETE_V5_DimAngular* CreateFromV6DimAngular( + const class ON_DimAngular& V6_dim_angular, + const class ON_3dmAnnotationContext* annotation_context, + ON_OBSOLETE_V5_DimAngular* destination + ); + + static ON_OBSOLETE_V5_DimAngular* CreateFromV2AngularDimension( + const class ON_OBSOLETE_V2_DimAngular& V2_angular_dimension, + const class ON_3dmAnnotationContext* annotation_context, + ON_OBSOLETE_V5_DimAngular* destination + ); + + + // overrides virtual ON_Geometry::Transform() + bool Transform( const ON_Xform& xform ) override; + + /* + Description: + Get the m_plane coordinates of the dimension point. + Parameters: + point_index - [in] One of the POINT_INDEX enum values + Returns: + 2d point or ON_3dPoint::UnsetPoint if point_index or m_points[] + array is not valid. + */ + ON_2dPoint Dim2dPoint( + int point_index + ) const; + + /* + Description: + Get the m_plane coordinates of the dimension point. + Parameters: + point_index - [in] One of the POINT_INDEX enum values + Returns: + 2d point or ON_3dPoint::UnsetPoint if point_index or m_points[] + array is not valid. + */ + ON_3dPoint Dim3dPoint( + int point_index + ) const; + + + // overrides virual ON_Object::IsValid + bool IsValid( ON_TextLog* text_log = nullptr ) const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + // virtual ON_Geometry GetTightBoundingBox override + bool GetTightBoundingBox( class ON_BoundingBox& tight_bbox, bool bGrowBox = false, const class ON_Xform* xform = nullptr ) const override; + + /* + Description: + Read from or write to a file + Returns: + @untitled Table + true Success + false Failure + */ + bool Write( ON_BinaryArchive& file ) const override; + bool Read( ON_BinaryArchive& file ) override; + + /* + Description: + Set the plane and definition points from 3d points + in world coordinates. + Parameters: + apex - [in] 3d apex of the dimension + (center of arc) + p0 - [in] 3d point on first line + p1 - [in] 3d point on second line + arcpt - [in] 3d point on dimension arc + (determines radius of arc) + Normal - [in] normal of the plane on which to make the dimension + (must be perpendicular to p0-apex and p1-apex) + Returns: + @untitled table + true Success + false Failure + */ + bool CreateFromPoints( + const ON_3dPoint& apex, + const ON_3dPoint& p0, + const ON_3dPoint& p1, + ON_3dPoint& arcpt, + ON_3dVector& Normal + ); + + /* + Description: + Set the plane and definition points from a 3d arc. + Parameters: + arc - [in] + Returns: + @untitled table + true Success + false Failure + */ + bool CreateFromArc( + const ON_Arc& arc + ); + + bool GetArc( ON_Arc& arc ) const; + + bool GetExtensionLines(ON_Line extensions[2]) const; + + // Set or get the measured angle in radians + void SetAngle( double angle); + double Angle() const; + void SetRadius( double radius); + double Radius() const; + + /* + Description: + Overrides virtual ON_OBSOLETE_V5_Annotation::NumericValue(); + Returns: + Angle in degrees + */ + double NumericValue() const override; + + /* + Description: + Get or set the DimStyle index in the dimstyle table for the dimension + Parameters: + [in] int the new index (Set) + Returns: + int - The current index (Get) + */ + int StyleIndex() const; + void SetStyleIndex( int); + + /* + Description: + static function to provide the default UserText string for the object + Returns: + const wchar_t* - the default string to use + */ + static const wchar_t* DefaultText(); + + double m_angle = 0.0; // angle being dimensioned + double m_radius = 1.0; // radius for dimension arc + + /* + Description: + Get the annotation plane angles of the dimension arc. + Parameters: + gdi_text_rect - [in] Windows rect (left < right, top < bottom) + that bounds text. + gdi_height_of_I - [in] + Height of an I in the text. + gdi_to_world - [in] + transform returned by ON_OBSOLETE_V5_Annotation::GetTextXform(). + dimstyle - [in] + dimscale - [in] + vp - [in] + a - [out] + angles at the ends of the arc segment(s) and the arrow tips + bInside - [out] true if arrowheads go inside, false if they go outside + Returns: + number of arc segments to draw + 0: the input or class is not valid + 1: A single arc from a[0] to a[1] with arrow heads at a[4] & a[5]. + 2: Two arcs from a[0] to a[1] & from a[2] to a[3]. + Arrowheads are at a[4] & a[5]. + */ + int GetDimensionArcSegments( + ON_OBSOLETE_V5_RECT gdi_text_rect, + int gdi_height_of_I, + ON_Xform gdi_to_world, + const ON_DimStyle& dimstyle, + double dimscale, + const ON_Viewport* vp, + double a[6], + bool& bInside + ) const; + + + /* + Description: + Get distance from dimension apex to extension line offset points + Parameters: + index - [in] which distance to get + Returns: + Distance to offset point [index] + */ + double DimpointOffset( + int index) const; + + /* + Description: + Set distance from dimension apex to extension line offset points + Parameters: + index - [in] which distance to set + offset - [in] Value to set + */ + void SetDimpointOffset( + int index, + double offset); +}; + + +/* + class ON_OBSOLETE_V5_DimLinear + + Description: + Override od ON_OBSOLETE_V5_Annotation to provide linear dimensions +*/ +class ON_OBSOLETE_V5_DimOrdinate : public ON_OBSOLETE_V5_Annotation +{ + ON_OBJECT_DECLARE(ON_OBSOLETE_V5_DimOrdinate); + +public: + + /* + In the picture below, [n] means ON_OBSOLETE_V5_Annotation::m_points[n]. + + Measures in X direction + + [1] + | + | + | + | + | + [0] + + + [plane origin] [plane origin] + + + + or - Measures in Y direction *---[1] + / + / + [0]--------------------[1] [0]---------------* + + + * = calculated, not stored + + + + + [plane origin] + + + The reference point of for the dimension is at the entity plane origin + The "x" and "y" coordinates of [1] can be any value. + The "x" and "y" coordinates of [2] can be any value. + If Direction is "x", the dimension measures along the "x" axis + If Direction is "y", the dimension measures along the "y" axis + If Direction is "x" and [1][x] <> [0][x], an offset segment is drawn + If Direction is "y" and [1][y] <> [0][y], an offset segment is drawn + The dimension lines are always drawn in the X or Y directions of the entity plane + The distance represented by the dimension is measured from the + plane origin to point [0], parallel to the appropriate axis. + The points of the offset segment are calculated rather than stored + */ + + enum POINT_INDEX + { + // Do not change these enum values. They are saved in files as the + // ON_COMPONENT_INDEX.m_index value. + // + // Indices of linear dimension definition points in + // the m_points[] array + definition_pt_index = 0, // First end of the dimension line + leader_end_pt_index = 1, // Other end of the leader (near the text) + dim_pt_count = 2, // Number of m_points[] in an ordinate dim + + // Points calculated from values in m_points[] + text_pivot_pt = 10000, // Center of dimension text + offset_pt_0 = 10001, // First offset point (nearest text) + offset_pt_1 = 10002 // Second offset point + }; + + enum DIRECTION + { + x = 0, // measures horizontally + y = 1, // measures vertically + }; + + ON_OBSOLETE_V5_DimOrdinate(); + ~ON_OBSOLETE_V5_DimOrdinate(); + + static ON_OBSOLETE_V5_DimOrdinate* CreateFromV6DimOrdinate( + const class ON_DimOrdinate& V6_dim_ordinate, + const class ON_3dmAnnotationContext* annotation_context, + ON_OBSOLETE_V5_DimOrdinate* destination + ); + + + // overrides virtual ON_Geometry::Transform() + bool Transform( const ON_Xform& xform ) override; + + /* + Description: + Get the m_plane coordinates of the dimension point. + Parameters: + point_index - [in] One of the POINT_INDEX enum values + default_offset [in] - kink offset to use if m_kink_offset_0 + or m_kink_offset_1 are ON_UNSET_VALUE + Returns: + 2d point or ON_3dPoint::UnsetPoint if point_index or m_points[] + array is not valid. + */ + ON_2dPoint Dim2dPoint( + int point_index, + double default_offset = 1.0 + ) const; + + /* + Description: + Get the m_plane coordinates of the dimension point. + Parameters: + point_index - [in] One of the POINT_INDEX enum values + default_offset [in] - kink offset to use if m_kink_offset_0 + or m_kink_offset_1 are ON_UNSET_VALUE + Returns: + 2d point or ON_3dPoint::UnsetPoint if point_index or m_points[] + array is not valid. + */ + ON_3dPoint Dim3dPoint( + int point_index, + double default_offset = 1.0 + ) const; + + // overrides virual ON_Object::IsValid + bool IsValid( ON_TextLog* text_log = nullptr ) const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + // virtual ON_Geometry GetTightBoundingBox override + bool GetTightBoundingBox( class ON_BoundingBox& tight_bbox, bool bGrowBox = false, const class ON_Xform* xform = nullptr ) const override; + + /* + Description: + Read from or write to a file + Returns: + @untitled Table + true Success + false Failure + */ + bool Write( ON_BinaryArchive& file ) const override; + bool Read( ON_BinaryArchive& file ) override; + + /* + Description: + Overrides virtual ON_OBSOLETE_V5_Annotation::NumericValue(); + Returns: + If Direction is 'X', x coordinate of point[1] + If Direction is 'Y', y coordinate of point[1] + */ + double NumericValue() const override; + + /* + Description: + Get or set the DimStyle index in the dimstyle table for the dimension + Parameters: + [in] int the new index (Set) + Returns: + int - The current index (Get) + */ + int StyleIndex() const; + void SetStyleIndex( int); + + /* + Description: + Gets the direction ( X or Y) that the ordinate dimension measures + based on the relative location of the defining point and leader endpoint + Returns: + 0: measures parallel to the entity plane x axis + 1: measures parallel to the entity plane y axis + Remarks: + This does not consider the dimension's explicit Direction setting + */ + int ImpliedDirection() const; + + /* + Description: + Gets or sets the direction ( X or Y) that the ordinate dimension measures + Returns: + -1: direction determined by dim point and leader point + 0: measures parallel to the entity plane x axis + 1: measures parallel to the entity plane y axis + */ + int Direction() const; + void SetDirection( int direction); + + /* + Description: + Get the height of the text in this dimension + by asking the dimension's dimstyle + Returns: + double Height of the text + Remarks: + Height is in model units + double Height() const; + */ + + /* + Description: + static function to provide the default UserText string for the object + Returns: + const wchar_t* - the default string to use + */ + static const wchar_t* DefaultText(); + + /* + Description: + Returns or sets the offset distance parallel to the dimension + line direction of from the text end of the dimension line to + the offset point + If the offset point hasn't been explicitly defined, returns + ON_UNSET_VALUE and a default should be used to find the point. + Parameters: + index [in] - which offset distance to return + (0 is closer to the text) + offset [in] - the offset distance to set + */ + double KinkOffset( int index) const; + void SetKinkOffset( int index, double offset); + + + int m_direction; // -1 == underermined + // 0 == x direction + // 1 == y direction + + // kink offsets added 2-4-06 - LW + double m_kink_offset_0; // from leader_end_point to first break point + double m_kink_offset_1; // from first break point to second break point + + /* + Description: + Calculates the 2d point locations of the dimension line kinks + + Parameters: + p0, p1 [in] - End points of the dimension line + direction [in] - orientation of the dimension + default_offset [in] - Use this if offsets are ON_UNSET_VALUE + k0, k1 [out] - The kink points + Remarks: + The offsets must be set to the right values before calling this, or + If they are ON_UNSET_VALUE, they will be set to the defaults + */ + void CalcKinkPoints( ON_2dPoint p0, ON_2dPoint p1, + int direction, double default_offset, + ON_2dPoint& k0, ON_2dPoint& k1) const; + +}; + + +////////// +// class ON_OBSOLETE_V5_TextObject +class ON_OBSOLETE_V5_TextObject : public ON_OBSOLETE_V5_Annotation +{ + ON_OBJECT_DECLARE(ON_OBSOLETE_V5_TextObject); + +public: + ON_OBSOLETE_V5_TextObject(); + ~ON_OBSOLETE_V5_TextObject(); + + /* + Description: + Create a V6 text object from a V5 text object. + The function is used when writing V5 files. + Parameters: + v6_text_object -[in] + dimstyle - [in] + Dimstyle referenced by v6_text_object or nullptr if not available. + destination - [in] + If destination is not nullptr, then the V5 text object is constructed + in destination. If destination is nullptr, then the new V5 text object + is allocated with a call to new ON_OBSOLETE_V5_TextObject(). + */ + static ON_OBSOLETE_V5_TextObject* CreateFromV6TextObject( + const class ON_Text& V6_text_object, + const class ON_3dmAnnotationContext* annotation_context, + ON_OBSOLETE_V5_TextObject* destination + ); + + static ON_OBSOLETE_V5_TextObject* CreateFromV2TextObject( + const class ON_OBSOLETE_V2_TextObject& V2_text_object, + const class ON_3dmAnnotationContext* annotation_context, + ON_OBSOLETE_V5_TextObject* destination + ); + + // overrides virual ON_Object::IsValid + // Text entities with strings that contain no "printable" characters + // are considered to be NOT valid. + bool IsValid( ON_TextLog* text_log = nullptr ) const override; + + // overrides virual ON_Object::Write + bool Write(ON_BinaryArchive&) const override; + + // overrides virual ON_Object::Read + bool Read(ON_BinaryArchive&) override; + + // overrides virtual ON_Geometry::Transform() + bool Transform( const ON_Xform& xform ) override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + // virtual ON_Geometry GetTightBoundingBox override + bool GetTightBoundingBox( class ON_BoundingBox& tight_bbox, bool bGrowBox = false, const class ON_Xform* xform = nullptr ) const override; + + void SetJustification( unsigned int justification) override; + + unsigned int Justification() const override; + + // Determines whether or not to draw a Text Mask + bool DrawTextMask() const; + void SetDrawTextMask(bool bDraw); + + // Determines where to get the color to draw a Text Mask + // 0: Use background color of the viewport. Initially, gradient backgrounds will not be supported + // 1: Use the ON_Color returned by MaskColor() + int MaskColorSource() const; + void SetMaskColorSource(int source); + + ON_Color MaskColor() const; // Only works right if MaskColorSource returns 1. + // Does not return viewport background color + void SetMaskColor(ON_Color color); + + // Offset for the border around text to the rectangle used to draw the mask + // This number * CRhinoAnnotation::TextHeight() for the text is the offset + // on each side of the tight rectangle around the text characters to the mask rectangle. + double MaskOffsetFactor() const; + void SetMaskOffsetFactor(double offset); + + // Scale annotation according to detail scale factor in paperspace + // or by 1.0 in paperspace and not in a detail + // Otherwise, dimscale or text scale is used + bool AnnotativeScaling() const; + void SetAnnotativeScaling(bool b); +}; + +////////// +// class ON_OBSOLETE_V5_Leader +class ON_OBSOLETE_V5_Leader : public ON_OBSOLETE_V5_Annotation +{ + ON_OBJECT_DECLARE(ON_OBSOLETE_V5_Leader); + +public: + + /* + The annotation's dimstyle controls the position of TEXT, + the size of the arrowheads, and the amount the ends of + linear dimension's extension lines extend beyond the + dimension lines. + + Leaders: + + Polyline with N=m_points.Count() points (N >= 2). + + [N-2] ----- [N-1] TEXT + / (tail) + / + / + [1]------[2] + / + / + / + [0] (arrow) + + Leaders ignore the m_userpositionedtext setting. If the + default leader text handling is not adequate, then use + a leader with no text and an ON_OBSOLETE_V5_TextObject. + */ + + enum POINT_INDEX + { + // Do not change these enum values. They are saved in files as the + // ON_COMPONENT_INDEX.m_index value. + // + // Indices of leader definition points in + // the m_points[] array + arrow_pt_index = 0, // arrow tip + + // Points calculated from values in m_points[] + text_pivot_pt = 10000, // start/end of dimension text at tail + tail_pt = 10001 + }; + + // Constructors + ON_OBSOLETE_V5_Leader(); + ~ON_OBSOLETE_V5_Leader(); + // C++ automatically provides the correct copy constructor and operator= . + //ON_OBSOLETE_V5_Leader(const ON_OBSOLETE_V5_Leader&); + //ON_OBSOLETE_V5_Leader& operator=(const ON_OBSOLETE_V5_Leader&); + + /* + Description: + Create a V5 leader from a V6 leader. + The function is used when writing V5 files. + Parameters: + v6_leader -[in] + dimstyle - [in] + Dimstyle referenced by v6_leader or nullptr if not available. + destination - [in] + If destination is not nullptr, then the V5 leader is constructed + in destination. If destination is nullptr, then the new V5 leader + is allocated with a call to new ON_V5_Leader(). + */ + static ON_OBSOLETE_V5_Leader* CreateFromV6Leader( + const class ON_Leader& V6_leader, + const class ON_3dmAnnotationContext* annotation_context, + ON_OBSOLETE_V5_Leader* destination + ); + + + static ON_OBSOLETE_V5_Leader* CreateFromV2Leader( + const class ON_OBSOLETE_V2_Leader& V2_leader, + const class ON_3dmAnnotationContext* annotation_context, + ON_OBSOLETE_V5_Leader* destination + ); + + // overrides virtual ON_Geometry::Transform() + bool Transform( const ON_Xform& xform ) override; + + /* + Description: + Get the m_plane coordinates of the dimension point. + Parameters: + point_index - [in] One of the POINT_INDEX enum values + Returns: + 2d point or ON_3dPoint::UnsetPoint if point_index or m_points[] + array is not valid. + */ + ON_2dPoint Dim2dPoint( + int point_index + ) const; + + /* + Description: + Get the m_plane coordinates of the dimension point. + Parameters: + point_index - [in] One of the POINT_INDEX enum values + Returns: + 2d point or ON_3dPoint::UnsetPoint if point_index or m_points[] + array is not valid. + */ + ON_3dPoint Dim3dPoint( + int point_index + ) const; + + // overrides virual ON_Object::IsValid + bool IsValid( ON_TextLog* text_log = nullptr ) const override; + + // overrides virual ON_Object::Write + bool Write(ON_BinaryArchive&) const override; + + // overrides virual ON_Object::Read + bool Read(ON_BinaryArchive&) override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + // virtual ON_Geometry GetTightBoundingBox override + bool GetTightBoundingBox( class ON_BoundingBox& tight_bbox, bool bGrowBox = false, const class ON_Xform* xform = nullptr ) const override; + + /* + Description: + Add or delete points to the leader + Parameters: + index [in] the point to delete + point [in] The point to add + Returns: + @untitled table + true Success + False Failure + */ + void AddPoint( const ON_2dPoint& point); + bool RemovePoint( int index = -1); + +// April 22, 2010 Lowell - Added to support right justified text on left pointing leader tails rr64292 + bool GetTextDirection( ON_2dVector& text_dir ) const; + bool GetArrowHeadDirection( ON_2dVector& arrowhead_dir ) const; + bool GetArrowHeadTip( ON_2dPoint& arrowhead_tip ) const; +}; + +#endif + +#endif diff --git a/opennurbs/Include/opennurbs_internal_V5_dimstyle.h b/opennurbs/Include/opennurbs_internal_V5_dimstyle.h new file mode 100644 index 0000000..d94b31f --- /dev/null +++ b/opennurbs/Include/opennurbs_internal_V5_dimstyle.h @@ -0,0 +1,731 @@ +/* +// +// Copyright (c) 1993-2017 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_INTERNAL_V5_DIMSTYLE_INC_) +#define OPENNURBS_INTERNAL_V5_DIMSTYLE_INC_ + +#include "opennurbs_internal_defines.h" + +#if defined(ON_COMPILING_OPENNURBS) + +// ON_V5x_DimStyle is used to read and write version 5 and earlier archives. +// ON_DimStyle is the class for runtime dimension style. +class ON_V5x_DimStyle : public ON_ModelComponent +{ + ON_OBJECT_DECLARE(ON_V5x_DimStyle); + +private: + friend class ON_DimStyle; + +public: + enum eArrowType + { + // eArrowType is used for V5 and earlier dimensions + // V6 dimensions (ON_Dimension) use ON_Arrowhead::arrow_type + solidtriangle = 0, // 2:1 + dot = 1, + tick = 2, + shorttriangle = 3, // 1:1 + arrow = 4, + rectangle = 5, + longtriangle = 6, // 4:1 + longertriangle = 7, // 6:1 + }; + +public: + ON_V5x_DimStyle(); + ~ON_V5x_DimStyle(); + ON_V5x_DimStyle(const ON_V5x_DimStyle&) = default; + ON_V5x_DimStyle& operator=(const ON_V5x_DimStyle&) = default; + +public: + ON_V5x_DimStyle( const class ON_3dmAnnotationSettings& src); + ON_V5x_DimStyle( + ON::LengthUnitSystem model_length_unit_system, + const class ON_DimStyle& src + ); + +public: + bool CompareDimstyle(const ON_V5x_DimStyle& src) const; + bool CompareValidFields(const ON_V5x_DimStyle& src) const; + + ////////////////////////////////////////////////////////////////////// + // + // ON_Object overrides + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + // virtual + void Dump( ON_TextLog& ) const override; // for debugging + + // virtual + bool Write( + ON_BinaryArchive& // serialize definition to binary archive + ) const override; + + // virtual + bool Read( + ON_BinaryArchive& // restore definition from binary archive + ) override; + + // When a V5 file is being read into v6 + // Copy the fields that were in DimstyleExtra in v5 into the v6 dimstyle + // that now contains the fields that were in DimstyleExtra + ///void ConsolidateDimstyleExtra(); + + bool AttachDimstyleExtra(); + + + bool Write_v5( + ON_BinaryArchive& // serialize definition to binary archive + ) const; + +private: + bool Internal_Read_v5( + ON_BinaryArchive& // restore definition from binary archive + ); + + //bool Write_v6( + // ON_BinaryArchive& // serialize definition to binary archive + // ) const; + + bool Internal_Read_v6( + ON_BinaryArchive& // restore definition from binary archive + ); + +public: + void EmergencyDestroy(); + + ////////////////////////////////////////////////////////////////////// + // + // Interface + + void SetDefaultsNoExtension(); + + double ExtExtension() const; + void SetExtExtension( const double); + + double ExtOffset() const; + void SetExtOffset( const double); + + double ArrowSize() const; + void SetArrowSize( const double); + + double LeaderArrowSize() const; + void SetLeaderArrowSize( const double); + + double CenterMark() const; + void SetCenterMark( const double); + + ON_INTERNAL_OBSOLETE::V5_TextDisplayMode TextAlignment() const; + void SetTextAlignment( ON_INTERNAL_OBSOLETE::V5_TextDisplayMode); + + int ArrowType() const; // For ON_OBSOLETE_V2_Annotation & ON_OBSOLETE_V5_Annotation derived dimensions + void SetArrowType( eArrowType); // ON_Dimension derived dimensions use ArrowType1() and ArrowType2() + + int LeaderArrowType() const; + void SetLeaderArrowType( eArrowType); + + int AngularUnits() const; + void SetAngularUnits( int); + + int LengthFormat() const; + void SetLengthFormat( int); + + int AngleFormat() const; + void SetAngleFormat( int); + + int LengthResolution() const; + void SetLengthResolution( int); + + int AngleResolution() const; + void SetAngleResolution( int); + + const class ON_TextStyle& V5TextStyle() const; + void SetV5TextStyle( + const class ON_TextStyle& v5_text_style + ); + + double TextGap() const; + void SetTextGap( double gap); + + double TextHeight() const; + void SetTextHeight( double height); + + double LengthFactor() const; + void SetLengthFactor( double); + + bool Alternate() const; + void SetAlternate( bool); + + double AlternateLengthFactor() const; + void SetAlternateLengthFactor( double); + + int AlternateLengthFormat() const; + void SetAlternateLengthFormat( int); + + int AlternateLengthResolution() const; + void SetAlternateLengthResolution( int); + + int AlternateAngleFormat() const; + void SetAlternateAngleFormat( int); + + int AlternateAngleResolution() const; + void SetAlternateAngleResolution( int); + + void GetPrefix( ON_wString& ) const; + const wchar_t* Prefix() const; + void SetPrefix( const wchar_t*); + void SetPrefix( wchar_t*); + + void GetSuffix( ON_wString& ) const; + const wchar_t* Suffix() const; + void SetSuffix( const wchar_t*); + void SetSuffix( wchar_t*); + + void GetAlternatePrefix( ON_wString& ) const; + const wchar_t* AlternatePrefix() const; + void SetAlternatePrefix( const wchar_t*); + void SetAlternatePrefix( wchar_t*); + + void GetAlternateSuffix( ON_wString& ) const; + const wchar_t* AlternateSuffix() const; + void SetAlternateSuffix( const wchar_t*); + void SetAlternateSuffix( wchar_t*); + + bool SuppressExtension1() const; + void SetSuppressExtension1( bool); + + bool SuppressExtension2() const; + void SetSuppressExtension2( bool); + + // Don't change these enum values + // They are used in file reading & writing + enum class Field : unsigned int + { + fn_name = 0, + fn_index = 1, + fn_extextension = 2, + fn_extoffset = 3, + fn_arrowsize = 4, + fn_centermark = 5, + fn_textgap = 6, + fn_textheight = 7, + fn_textalign = 8, + fn_arrowtype = 9, // For v5 and previous ON_OBSOLETE_V2_Annotation and ON_OBSOLETE_V5_Annotation dimensions + fn_angularunits = 10, + fn_lengthformat = 11, + fn_angleformat = 12, + fn_angleresolution = 13, + fn_lengthresolution = 14, + fn_fontindex = 15, + fn_lengthfactor = 16, + fn_bAlternate = 17, + fn_alternate_lengthfactor = 18, + fn_alternate_lengthformat = 19, + fn_alternate_lengthresolution = 20, + fn_alternate_angleformat = 21, + fn_alternate_angleresolution = 22, + fn_prefix = 23, + fn_suffix = 24, + fn_alternate_prefix = 25, + fn_alternate_suffix = 26, + fn_dimextension = 27, + fn_leaderarrowsize = 28, + fn_leaderarrowtype = 29, + fn_suppressextension1 = 30, + fn_suppressextension2 = 31, + fn_last = 32, // not used - left here for sdk + + // Added for v5 - 5/01/07 LW + // version 1.6 + fn_overall_scale = 33, + fn_ext_line_color_source = 34, + fn_dim_line_color_source = 35, + fn_arrow_color_source = 36, + fn_text_color_source = 37, + fn_ext_line_color = 38, + fn_dim_line_color = 39, + fn_arrow_color = 40, + fn_text_color = 41, + fn_ext_line_plot_color_source = 42, + fn_dim_line_plot_color_source = 43, + fn_arrow_plot_color_source = 44, + fn_text_plot_color_source = 45, + fn_ext_line_plot_color = 46, + fn_dim_line_plot_color = 47, + fn_arrow_plot_color = 48, + fn_text_plot_color = 49, + fn_ext_line_plot_weight_source = 50, + fn_dim_line_plot_weight_source = 51, + fn_ext_line_plot_weight_mm = 52, + fn_dim_line_plot_weight_mm = 53, + fn_tolerance_style = 54, + fn_tolerance_resolution = 55, + fn_tolerance_upper_value = 56, + fn_tolerance_lower_value = 57, + fn_tolerance_height_scale = 58, + fn_baseline_spacing = 59, + + // Added for v5 - 12/15/09 LW + // version 1.7 + fn_draw_mask = 60, + fn_mask_color_source = 61, + fn_mask_color = 62, + fn_mask_border = 63, + + // Added for v5 - 12/17/09 LW + // version 1.8 + fn_dimscale = 64, + fn_dimscale_source = 65, + + // Added for V6 - + // version 2.0 + fn_fixed_extension_len = 66, + fn_fixed_extension_on = 67, + fn_text_rotation = 68, + fn_tolerance_alt_resolution = 69, + fn_tolerance_textheight_fraction = 70, + fn_suppress_arrow1 = 71, + fn_suppress_arrow2 = 72, + fn_textmove_leader = 73, + fn_arclength_sym = 74, + fn_stack_textheight_fraction = 75, + fn_stack_format = 76, + fn_alt_round = 77, + fn_round = 78, + fn_alt_zero_suppress = 79, + fn_tol_zero_suppress = 80, + fn_ang_zero_suppress = 81, + fn_zero_suppress = 82, + fn_alt_below = 83, + + fn_dim_arrow_type1 = 84, // For ON_Dimension derived dimensions + fn_dim_arrow_type2 = 85, + fn_dim_arrow_blockname1 = 86, + fn_dim_arrow_blockname2 = 87, + + FieldCount, + fn_unset = 0xFFFE, + fn_really_last = 0xFFFF + }; + + enum : unsigned int + { + // must be 1 + the maximum value of an ON_V5x_DimStyle::Field enum value. + FieldCount = 88 + }; + + + // Combines a field id and a field value + // Dimensions will have an array of DimstyleField's to record + // dimension style overrides for individual dimensions + class DimstyleField + { + public: + DimstyleField() + : m_next(nullptr) + , m_field_id(ON_V5x_DimStyle::Field::fn_unset) + { + m_val.s_val = nullptr; + } + ~DimstyleField() + { + if (nullptr != m_next) + { + delete m_next; + m_next = nullptr; + } + if (nullptr != m_val.s_val) + { + delete m_val.s_val; + m_val.s_val = nullptr; + } + } + + DimstyleField* m_next; + ON_V5x_DimStyle::Field m_field_id; + union + { + bool b_val; + int i_val; + unsigned char uc_val; + double d_val; + unsigned int c_val; + const ON_wString* s_val; + } m_val; + }; + + // added version 1.3 + double DimExtension() const; + void SetDimExtension( const double); + + // This section Added for v5 - 4-24-07 LW + // version 1.6 + + // Test if a specific field has been set in this dimstyle + // and not inherited from its parent. + bool IsFieldOverride(ON_V5x_DimStyle::Field field_id) const; + // Set a field to be overridden or not + // Fields that aren't overrides inherit from their parent dimstyle + void SetFieldOverride(ON_V5x_DimStyle::Field field_id, bool bOverride); + + + /* + Clear all field overrides + */ + void ClearAllFieldOverrides(); + + // Test if the dimstyle has any field override flags set + bool HasOverrides() const; + + // Change the fields in this dimstyle to match the fields of the + // source dimstyle for all of the fields that are marked overridden in the source + // and to match the parent for all of the fields not marked overriden. + // Returns true if any overrides were set. + bool OverrideFields( const ON_V5x_DimStyle& source, const ON_V5x_DimStyle& parent); + + // + // Change the fields in this dimstyle to match the fields of the + // parent dimstyle for all of the fields that are not marked overridden in the + // target dimstyle. + // This is the complement of OverrideFields() + bool InheritFields( const ON_V5x_DimStyle& parent); + + // Test if this dimstyle is the child of any other dimstyle + bool IsChildDimstyle() const; + + // Test if this dimstyle is the child of a given dimstyle + // A dimstyle may have several child dimstyles, but only one parent + bool IsChildOf(const ON_UUID& parent_uuid) const; + + // use ON_ModelComponent parent id - // ON_UUID ParentId() const; + + // Set the parent of this dimstyle + // use ON_ModelComponent parent id - //void SetParentId(ON_UUID parent_uuid); + + // Tolerances + // Tolerance style + // 0: None + // 1: Symmetrical + // 2: Deviation + // 3: Limits + // 4: Basic + enum eToleranceStyle + { + tsMin = 0, + tsNone = 0, + tsSymmetrical = 1, + tsDeviation = 2, + tsLimits = 3, + tsBasic = 4, + tsMax = 4 + }; + int ToleranceStyle() const; + int ToleranceResolution() const; + double ToleranceUpperValue() const; + double ToleranceLowerValue() const; + double ToleranceHeightScale() const; + + double BaselineSpacing() const; + + void SetToleranceStyle( int style); + void SetToleranceResolution( int resolution); + void SetToleranceUpperValue( double upper_value); + void SetToleranceLowerValue( double lower_value); + void SetToleranceHeightScale( double scale); + + void SetBaselineSpacing( double spacing = false); + + // Determines whether or not to draw a Text Mask + bool DrawTextMask() const; + void SetDrawTextMask(bool bDraw); + + // Determines where to get the color to draw a Text Mask + // 0: Use background color of the viewport. Initially, gradient backgrounds will not be supported + // 1: Use the ON_Color returned by MaskColor() + int MaskColorSource() const; + void SetMaskColorSource(int source); + + ON_Color MaskColor() const; // Only works right if MaskColorSource returns 1. + // Does not return viewport background color + void SetMaskColor(ON_Color color); + + // Per DimStyle DimScale + void SetDimScaleSource(int source); + int DimScaleSource() const; // 0: Global DimScale, 1: DimStyle DimScale + void SetDimScale(double scale); + double DimScale() const; + + // Offset for the border around text to the rectangle used to draw the mask + // This number * CRhinoAnnotation::TextHeight() for the text is the offset + // on each side of the tight rectangle around the text characters to the mask rectangle. + double MaskOffsetFactor() const; + + void Scale( double scale); + + // UUID of the dimstyle this was originally copied from + // so Restore Defaults has some place to look + void SetSourceDimstyle(ON_UUID source_uuid); + ON_UUID SourceDimstyle() const; + + // ver 2.0 V6 + + void SetExtensionLineColorSource(const ON::object_color_source src); + ON::object_color_source ExtensionLineColorSource() const; + void SetDimensionLineColorSource(const ON::object_color_source src); + ON::object_color_source DimensionLineColorSource() const; + void SetArrowColorSource(const ON::object_color_source src); + ON::object_color_source ArrowColorSource() const; + void SetExtensionLineColor(ON_Color c); + ON_Color ExtensionLineColor() const; + void SetDimensionLineColor(ON_Color c); + ON_Color DimensionLineColor() const; + void SetArrowColor(ON_Color c); + ON_Color ArrowColor() const; + void SetTextColor(ON_Color c); + ON_Color TextColor() const; + + void SetExtensionLinePlotColorSource(const ON::plot_color_source src); + ON::plot_color_source ExtensionLinePlotColorSource() const; + void SetDimensionLinePlotColorSource(const ON::plot_color_source src); + ON::plot_color_source DimensionLinePlotColorSource() const; + void SetArrowPlotColorSource(const ON::plot_color_source src); + ON::plot_color_source ArrowPlotColorSource() const; + void SetExtensionLinePlotColor(ON_Color c); + ON_Color ExtensionLinePlotColor() const; + void SetDimensionLinePlotColor(ON_Color c); + ON_Color DimensionLinePlotColor() const; + void SetArrowPlotColor(ON_Color c); + ON_Color ArrowPlotColor() const; + void SetTextPlotColor(ON_Color c); + ON_Color TextPlotColor() const; + + void SetExtensionLinePlotWeightSource(const ON::plot_weight_source src); + ON::plot_weight_source ExtensionLinePlotWeightSource() const; + void SetDimensionLinePlotWeightSource(const ON::plot_weight_source src); + ON::plot_weight_source DimensionLinePlotWeightSource() const; + void SetExtensionLinePlotWeight(double w); + double ExtensionLinePlotWeight() const; + void SetDimensionLinePlotWeight(double w); + double DimensionLinePlotWeight() const; + + void SetFixedExtensionLen(double l); + double FixedExtensionLen() const; + void SetFixedExtensionLenOn(bool on); + bool FixedExtensionLenOn() const; + void SetTextRotation(double r); + double TextRotation() const; + void SetAlternateToleranceResolution(int r); + int AlternateToleranceResolution() const; + //void SetAlternateTolHeightFraction(double f); + //double AltTolHeightFraction() const; + void SetSuppressArrow1(bool s); + bool SuppressArrow1() const; + void SetSuppressArrow2(bool s); + bool SuppressArrow2() const; + void SetTextMoveLeader(int m); + int TextMoveLeader() const; + void SetArcLengthSymbol(int m); + int ArcLengthSymbol() const; + void SetStackFractionFormat(int f); + int StackFractionFormat() const; + void SetStackHeightFraction(double f); + double StackHeightFraction() const; + void SetRoundOff(double r); + double RoundOff() const; + void SetAlternateRoundOff(double r); + double AlternateRoundOff() const; + void SetZeroSuppress(int s); + int ZeroSuppress() const; + void SetAlternateZeroSuppress(int s); + int AlternateZeroSuppress() const; + void SetToleranceZeroSuppress(int s); + int ToleranceZeroSuppress() const; + void SetAngleZeroSuppress(int s); + int AngleZeroSuppress() const; + void SetAlternateBelow(bool below); + bool AlternateBelow() const; + void SetArrowType1(ON_Arrowhead::arrow_type); // ON_Dimension derived dimensions + ON_Arrowhead::arrow_type ArrowType1() const; + void SetArrowBlockId1(ON_UUID id); + ON_UUID ArrowBlockId1() const; + void SetArrowType2(ON_Arrowhead::arrow_type); + ON_Arrowhead::arrow_type ArrowType2() const; + void SetArrowBlockId2(ON_UUID id); + ON_UUID ArrowBlockId2() const; + const ON_Arrowhead& Arrowhead1() const; + const ON_Arrowhead& Arrowhead2() const; + + + + // Defaults for values stored in Userdata extension - needed to read and write pre-v6 files + static int DefaultToleranceStyle(); + static int DefaultToleranceResolution(); + static double DefaultToleranceUpperValue(); + static double DefaultToleranceLowerValue(); + static double DefaultToleranceHeightScale(); + static double DefaultBaselineSpacing(); + static bool DefaultDrawTextMask(); // false + static int DefaultMaskColorSource(); // 0; + static ON_Color DefaultMaskColor(); // .SetRGB(255,255,255); + static double DefaultDimScale(); // 1.0; + static int DefaultDimScaleSource(); // 0; + + bool CompareFields(const ON_V5x_DimStyle& other) const; + +public: + double m_extextension = 0.5; // extension line extension + double m_extoffset = 0.5; // extension line offset + double m_arrowsize = 1.0; // length of an arrow - may mean different things to different arrows + double m_centermark = 0.5; // size of the + at circle centers + double m_textgap = 0.25; // gap around the text for clipping dim line + double m_textheight = 1.0; // model unit height of dimension text before applying dimscale + ON_INTERNAL_OBSOLETE::V5_TextDisplayMode m_dimstyle_textalign = ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kAboveLine; // text alignment relative to the dimension line + int m_arrowtype = 0; // 0: filled narrow triangular arrow - For ON_OBSOLETE_V2_Annotation & ON_OBSOLETE_V5_Annotation derived dimensnions + // m_arrowtype = ((ON_Arrowhead::arrow_type enum value as int) - 2) + int m_angularunits = 0; // 0: degrees, 1: radians + int m_lengthformat = 0; // 0: decimal, 1: fractional, 2: feet & inches + int m_angleformat = 0; // 0: decimal degrees, 1:DMS, ... + int m_angleresolution = 2; // for decimal degrees, digits past decimal + int m_lengthresolution = 2; // depends on m_lengthformat + // for decimal, digits past the decimal point +private: + ON_TextStyle m_v5_text_style = ON_TextStyle::Default; + +public: + // added fields version 1.2, Jan 13, 05 + double m_lengthfactor = 1.0; // (dimlfac) model units multiplier for length display + + bool m_bAlternate = false; // (dimalt) display alternate dimension string (or not) + // using m_alternate_xxx values + + double m_alternate_lengthfactor = 1.0; // (dimaltf) model units multiplier for alternate length display + int m_alternate_lengthformat = 0; // 0: decimal, 1: feet, 2: feet & inches + int m_alternate_lengthresolution = 2; // depends on m_lengthformat + // for decimal, digits past the decimal point + + int m_alternate_angleformat = 0; // 0: decimal degrees, ... + int m_alternate_angleresolution = 2; // for decimal degrees, digits past decimal + + ON_wString m_prefix; // string preceding dimension value string + ON_wString m_suffix; // string following dimension value string + ON_wString m_alternate_prefix; // string preceding alternate value string + ON_wString m_alternate_suffix; // string following alternate value string + +private: + ///unsigned int m_valid = 0; // Obsolete deprecated field to be removed - Do not use +public: + + // field added version 1.4, Dec 28, 05 + double m_dimextension = 0.0; // (dimdle) dimension line extension past the "tip" location + + // fields added version 1.5 Mar 23 06 + double m_leaderarrowsize = 1.0; // Like dimension arrow size but applies to leaders + int m_leaderarrowtype = 0; // Like dimension arrow type but applies to leaders + bool m_bSuppressExtension1 = false; // flag to not draw extension lines + bool m_bSuppressExtension2 = false; // flag to not draw extension lines + +private: + friend class ON_DimStyleExtra; + // 8 Apr, 2014 - The next few fields were transferred from ON_DimStyleExtra for V6 + /// Use ON_ModelComponent.ParentId() /// ON_UUID m_parent_dimstyle = ON_nil_uuid; // ON_nil_uuid if there is no parent dimstyle + unsigned int m_field_override_count = 0; // number of + bool m_field_override[ON_V5x_DimStyle::FieldCount]; + +public: + int m_tolerance_style = 0; + int m_tolerance_resolution = 4; + double m_tolerance_upper_value = 0.0; // or both upper and lower in symmetrical style + double m_tolerance_lower_value = 0.0; + double m_tolerance_height_scale = 1.0; // relative to the main dimension text + + double m_baseline_spacing = 1.0; + + // Text mask - added Dec 12 2009 + bool m_bDrawMask = false; + int m_mask_color_source = 0; + ON_Color m_mask_color = ON_Color::White; + + // Per dimstyle DimScale added Dec 16, 2009 + double m_dimscale = 1.0; + int m_dimscale_source = 0; + + // 19 Oct 2010 - Added uuid of source dimstyle to restore defaults + ON_UUID m_source_dimstyle = ON_nil_uuid; + // End of fields that were in ON_DimStyleExtra + + // Fields added for V6, ver 2.0 + + unsigned char m_ext_line_color_source = 0; + unsigned char m_dim_line_color_source = 0; + unsigned char m_arrow_color_source = 0; + unsigned char m_text_color_source = 0; + ON_Color m_ext_line_color = ON_Color::Black; + ON_Color m_dim_line_color = ON_Color::Black; + ON_Color m_arrow_color = ON_Color::Black; + ON_Color m_text_color = ON_Color::Black; + unsigned char m_ext_line_plot_color_source = 0; + unsigned char m_dim_line_plot_color_source = 0; + unsigned char m_arrow_plot_color_source = 0; + unsigned char m_text_plot_color_source = 0; + ON_Color m_ext_line_plot_color = ON_Color::Black; + ON_Color m_dim_line_plot_color = ON_Color::Black; + ON_Color m_arrow_plot_color = ON_Color::Black; + ON_Color m_text_plot_color = ON_Color::Black; + unsigned char m_ext_line_plot_weight_source = 0; + unsigned char m_dim_line_plot_weight_source = 0; + double m_ext_line_plot_weight_mm = 0.0; + double m_dim_line_plot_weight_mm = 0.0; + + double m_fixed_extension_len = 1.0; // Fixed extension line length if m_fixed_extension_len_on is true + bool m_fixed_extension_len_on = false; // true: use fixed_extension_len, false: don't use m_fixed_extension_len + double m_text_rotation = 0.0; // Dimension text rotation around text point (radians) + int m_alt_tol_resolution = 4; // for decimal, digits past the decimal point, fractions: 1/2^n + double m_tol_textheight_fraction = 1.0; // fraction of main text height + bool m_suppress_arrow1 = false; // false: dont suppress, true: suppress + bool m_suppress_arrow2 = false; // false: dont suppress, true: suppress + int m_textmove_leader = 0; // 0: move text anywhere, 1: add leader when moving text + int m_arclength_sym = 0; // 0: symbol before dim text, 1: symbol above dim text, no symbol + double m_stack_textheight_fraction = 1.0; // fraction of main text height + int m_stack_format = 0; // 0: no stacking, 1: horizontal, 2: diagonal + double m_alt_round = 0.0; // rounds to nearest specified value + double m_round = 0.0; + int m_alt_zero_suppress = 0; // 0: no zero suppressing + int m_tol_zero_suppress = 0; // 1: suppress zero feet + int m_zero_suppress = 0; // 2: suppress zero inches + int m_ang_zero_suppress = 0; // 3: suppress both zero feet and 0 inches + // 4: suppress leading zeros + // 8: suppress trailing zeros + // 12: suppress both leading and trailing zeros + bool m_alt_below = false; // true: display alternate text below main text + // true: display alternate text after main text + //ON_Arrowhead::arrow_type m_arrow_type_1; // Arrow types for ON_Dimension derived dimensions + //ON_Arrowhead::arrow_type m_arrow_type_2; + //ON_wString m_dim_arrow_block1; + //ON_wString m_dim_arrow_block2; + + ON_Arrowhead m_arrow_1; + ON_Arrowhead m_arrow_2; +}; + +void ON_Internal_FixBogusDimStyleLengthFactor( + const class ON_BinaryArchive& file, + double& dimstyle_length_factor +); + +#endif + +#endif diff --git a/opennurbs/Include/opennurbs_internal_defines.h b/opennurbs/Include/opennurbs_internal_defines.h new file mode 100644 index 0000000..e3d7db8 --- /dev/null +++ b/opennurbs/Include/opennurbs_internal_defines.h @@ -0,0 +1,165 @@ +/* +// Copyright (c) 1993-2017 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_INTERNAL_DEFINES_INC_) +#define OPENNURBS_INTERNAL_DEFINES_INC_ + +#if defined(ON_COMPILING_OPENNURBS) + +class ON_INTERNAL_OBSOLETE +{ +public: + + //// OBSOLETE V5 Dimension Types /////////////////////////////////////////////////////////// + enum class V5_eAnnotationType : unsigned char + { + dtNothing, + dtDimLinear, + dtDimAligned, + dtDimAngular, + dtDimDiameter, + dtDimRadius, + dtLeader, + dtTextBlock, + dtDimOrdinate, + }; + + // convert integer to eAnnotationType enum + static ON_INTERNAL_OBSOLETE::V5_eAnnotationType V5AnnotationTypeFromUnsigned( + unsigned int v5_annotation_type_as_unsigned + ); + + //// dim text locations /////////////////////////////////////////////////////////// + enum class V5_TextDisplayMode : unsigned char + { + kNormal = 0, // antique name - triggers use of current default + kHorizontalToScreen = 1, // Horizontal to the screen + kAboveLine = 2, + kInLine = 3, + kHorizontalInCplane = 4 // horizontal in the dimension's plane + }; + + static ON_INTERNAL_OBSOLETE::V5_TextDisplayMode V5TextDisplayModeFromUnsigned( + unsigned int text_display_mode_as_unsigned + ); + + static ON_INTERNAL_OBSOLETE::V5_TextDisplayMode V5TextDisplayModeFromV6DimStyle( + const ON_DimStyle& V6_dim_style + ); + + /// + /// Attachment of content + /// + enum class V5_vertical_alignment : unsigned char + { + /// + /// Text centered on dimension line (does not apply to leaders or text) + /// + Centered = 0, + /// + /// Text above dimension line (does not apply to leaders or text) + /// + Above = 1, + /// + /// Text below dimension line (does not apply to leaders or text) + /// + Below = 2, + /// + /// Leader tail at top of text (does not apply to text or dimensions) + /// + Top = 3, // = TextVerticalAlignment::Top + /// + /// Leader tail at middle of first text line (does not apply to text or dimensions) + /// + FirstLine = 4, // = MiddleOfTop + /// + /// Leader tail at middle of text or content (does not apply to text or dimensions) + /// + Middle = 5, // = Middle + /// + /// Leader tail at middle of last text line (does not apply to text or dimensions) + /// + LastLine = 6, // = MiddleOfBottom + /// + /// Leader tail at bottom of text (does not apply to text or dimensions) + /// + Bottom = 7, // = Bottom + /// + /// Leader tail at bottom of text, text underlined (does not apply to text or dimensions) + /// + Underlined = 8 // Underlined + + // nothing matched BottomOfTop + }; + + static ON_INTERNAL_OBSOLETE::V5_vertical_alignment V5VerticalAlignmentFromUnsigned( + unsigned int vertical_alignment_as_unsigned + ); + + static ON_INTERNAL_OBSOLETE::V5_vertical_alignment V5VerticalAlignmentFromV5Justification( + unsigned int v5_justification_bits + ); + + static ON_INTERNAL_OBSOLETE::V5_vertical_alignment V5VerticalAlignmentFromV6VerticalAlignment( + const ON::TextVerticalAlignment text_vertical_alignment + ); + + static ON::TextVerticalAlignment V6VerticalAlignmentFromV5VerticalAlignment( + ON_INTERNAL_OBSOLETE::V5_vertical_alignment V5_vertical_alignment + ); + + + enum class V5_horizontal_alignment : unsigned char + { + /// + /// Left aligned + /// + Left = 0, // Left + /// + /// Centered + /// + Center = 1, + /// + /// Right aligned + /// + Right = 2, + /// + /// Determined by orientation + /// Primarily for leaders to make + /// text right align when tail is to the left + /// and left align when tail is to the right + /// + Auto = 3, + }; + + static ON_INTERNAL_OBSOLETE::V5_horizontal_alignment V5HorizontalAlignmentFromUnsigned( + unsigned int horizontal_alignment_as_unsigned + ); + + static ON_INTERNAL_OBSOLETE::V5_horizontal_alignment V5HorizontalAlignmentFromV5Justification( + unsigned int v5_justification_bits + ); + + static ON_INTERNAL_OBSOLETE::V5_horizontal_alignment V5HorizontalAlignmentFromV6HorizontalAlignment( + const ON::TextHorizontalAlignment text_horizontal_alignment + ); + + static ON::TextHorizontalAlignment V6HorizontalAlignmentFromV5HorizontalAlignment( + ON_INTERNAL_OBSOLETE::V5_horizontal_alignment V5_vertical_alignment + ); +}; + +#endif + +#endif diff --git a/opennurbs/Include/opennurbs_internal_glyph.h b/opennurbs/Include/opennurbs_internal_glyph.h new file mode 100644 index 0000000..60991fa --- /dev/null +++ b/opennurbs/Include/opennurbs_internal_glyph.h @@ -0,0 +1,261 @@ +/* +// +// Copyright (c) 1993-2017 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ +#if !defined(OPENNURBS_INTERNAL_GLYPH_INC_) +#define OPENNURBS_INTERNAL_GLYPH_INC_ + +class ON_Internal_FontGlyphPool : private ON_FixedSizePool +{ +private: + friend class ON_FontGlyph; + friend class ON_GlyphMap; + ON_Internal_FontGlyphPool(); + ~ON_Internal_FontGlyphPool() = default; + ON_Internal_FontGlyphPool(const ON_Internal_FontGlyphPool&) = delete; + ON_Internal_FontGlyphPool operator=(const ON_Internal_FontGlyphPool&) = delete; + static ON_Internal_FontGlyphPool theGlyphItemPool; +}; + +class ON_ManagedFonts +{ +public: + // List is the only instance of this class. + static ON_ManagedFonts List; + + static const ON_FontList& InstalledFonts(); + + static const ON_FontList& ManagedFonts() + { + return List.m_managed_fonts; + } + + const ON_Font* GetFromFontCharacteristics( + const ON_Font& font_characteristics, + bool bCreateIfNotFound + ); + + const ON_Font* GetFromSerialNumber( + unsigned int managed_font_runtime_serial_number + ); + +#if defined(ON_OS_WINDOWS_GDI) + static void Internal_GetWindowsInstalledFonts(ON_SimpleArray&); +#endif + +#if defined (ON_RUNTIME_APPLE_CORE_TEXT_AVAILABLE) + static void Internal_GetAppleInstalledCTFonts(ON_SimpleArray& platform_font_list); +#endif + +private: + static void Internal_SetFakeWindowsLogfontNames( + ON_SimpleArray& device_list + ); + static void Internal_SetFakeWindowsLogfontName( + const ON_Font* font, + const ON_wString fake_loc_logfont_name, + const ON_wString fake_en_logfont_name + ); +public: + + // sorts nulls to end of lists + static int CompareFontPointer(ON_Font const* const* lhs, ON_Font const* const* rhs); + + /* + Returns: + 0: failure + >0: success font glyph index + */ + static unsigned int GetGlyphMetricsInFontDesignUnits( + const class ON_Font* font, + ON__UINT32 unicode_code_point, + class ON_TextBox& glyph_metrics_in_font_design_units + ); + + /* + Parameters: + font - [in] + font_metrics_in_font_design_units - [out] + Returns: + True: + font_metrics_in_font_design_units set from a font installed on the + current device. + False: + ON_FontMetrics::LastResortMetrics used or other corrections applied. + */ + + static bool GetFontMetricsInFontDesignUnits( + const ON_Font* font, + ON_FontMetrics& font_metrics_in_font_design_units + ); + +private: + // The purpose of this nondefault constructor is to create ON_ManagedFonts::List + // in opennurbs_statics.cpp in a way that Apple's CLang will actually compile. + // The only instance of ON_ManagedFonts is ON_ManagedFonts::List. + ON_ManagedFonts(ON__UINT_PTR zero); + + ~ON_ManagedFonts(); + +private: + ON_ManagedFonts() = delete; + ON_ManagedFonts(const ON_ManagedFonts&) = delete; + ON_ManagedFonts& operator=(const ON_ManagedFonts&) = delete; + +private: + /* + Parameters: + managed_font_metrics_in_font_design_units - [in] + Pass nullptr if not available. + If not nullptr, then the values are assumed to be accurate + and the units are the font design units (not normalized). + */ + const ON_Font* Internal_AddManagedFont( + const ON_Font* managed_font, + const ON_FontMetrics* managed_font_metrics_in_font_design_units // can be nullptr + ); + +private: + ON__UINT_PTR m_default_font_ptr = 0; + +private: + // Managed fonts used in annotation, etc. + // They may or may not be installed on this device + ON_FontList m_managed_fonts; + + +private: + // Fonts installed on this device + ON_FontList m_installed_fonts; +}; + +class ON_CLASS ON_GlyphMap +{ +public: + ON_GlyphMap(); + ~ON_GlyphMap() = default; + +public: + const class ON_FontGlyph* FindGlyph( + const ON__UINT32 unicode_code_point + ) const; + + // returns pointer to the persistent glyph item + const ON_FontGlyph* InsertGlyph( + const ON_FontGlyph& glyph + ); + + unsigned int GlyphCount() const; + +private: + friend class ON_Font; + friend class ON_FontGlyph; + unsigned int m_glyph_count = 0; + mutable ON_SleepLock m_sleep_lock; + ON_SimpleArray< const class ON_FontGlyph* > m_glyphs; +}; + +#if defined(ON_OS_WINDOWS_GDI) +/* +Parameters: + glyph - [in] + font_metrics - [out] + font metrics in font design units +Returns: + >0: glyph index + 0: failed +*/ +ON_DECL +void ON_WindowsDWriteGetFontMetrics( + const ON_Font* font, + ON_FontMetrics& font_metrics +); + +/* +Parameters: + glyph - [in] + glyph_metrics - [out] + Returns glyph metrics in font design units +Returns: + >0: glyph index + 0: failed +*/ +ON_DECL +unsigned int ON_WindowsDWriteGetGlyphMetrics( + const ON_FontGlyph* glyph, + ON_TextBox& glyph_metrics +); + +/* +Parameters: + glyph - [in] + bSingleStrokeFont - [in] + outline - [out] + outline and metrics in font design units +*/ +ON_DECL +bool ON_WindowsDWriteGetGlyphOutline( + const ON_FontGlyph* glyph, + ON_OutlineFigure::Type figure_type, + class ON_Outline& outline +); +#endif + +#if defined(ON_RUNTIME_APPLE_CORE_TEXT_AVAILABLE) +/* +Parameters: + glyph - [in] + font_metrics - [out] + font metrics in font design units +Returns: + >0: glyph index + 0: failed +*/ +ON_DECL +void ON_AppleFontGetFontMetrics( + const ON_Font* font, + ON_FontMetrics& font_metrics +); + +/* +Parameters: + glyph - [in] + glyph_metrics - [out] + Returns glyph metrics in font design units +Returns: + >0: glyph index + 0: failed +*/ +ON_DECL +unsigned int ON_AppleFontGetGlyphMetrics( + const ON_FontGlyph* glyph, + ON_TextBox& glyph_metrics +); + +/* +Parameters: + glyph - [in] + figure_type - [in] + Pass ON_OutlineFigure::Type::Unset if not known. + outline - [out] + outline and metrics in font design units +*/ +ON_DECL +bool ON_AppleFontGetGlyphOutline( + const ON_FontGlyph* glyph, + ON_OutlineFigure::Type figure_type, + class ON_Outline& outline +); +#endif + +#endif diff --git a/opennurbs/Include/opennurbs_internal_unicode_cp.h b/opennurbs/Include/opennurbs_internal_unicode_cp.h new file mode 100644 index 0000000..539094b --- /dev/null +++ b/opennurbs/Include/opennurbs_internal_unicode_cp.h @@ -0,0 +1,151 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_INTERNAL_UNICODE_CP_INC_) +#define OPENNURBS_INTERNAL_UNICODE_CP_INC_ + +#if !defined(ON_COMPILING_OPENNURBS) +// This check is included in all opennurbs source .c and .cpp files to insure +// ON_COMPILING_OPENNURBS is defined when opennurbs source is compiled. +// When opennurbs source is being compiled, ON_COMPILING_OPENNURBS is defined +// and the opennurbs .h files alter what is declared and how it is declared. +#error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs +#endif + +#if !defined(ON_RUNTIME_WIN) +#error Do not use for Windows builds. +#endif + +#if !defined(ON_RUNTIME_WIN) +// When we do not have access to Windows code page tools, +// we have to add in code to get convert Windows and Apple +// multibyte encodings to UNICODE encodings. +// +// In practice, the primary use of the double byte code page support +// is in parsing rich text (RTF) in ON_TextContent classes created +// on computers with Eastern European and Asian locales as the default +// locale. +// +// Many Western European and Americas locales are handled by the +// single byte code pages 1252 and 10000. Code pages for other +// locales will be added as needed because embedding the large +// double byte tables makes the resulting libraries large. +// +// At this time opennurbs does not ship the +// code page N to UNICODE translation tables as separate files +// that can be loaded on demand because of the added installation +// and runtime lookup complexities. +// +// When possible, Rhino and opennurbs replace code page +// encodings with UNICODE in RTF. All runtimes strings +// use UNICODE UTF-8, UTF-16, or UTF-32 encodings. +// Whenever posssible, the UNICODE encoding is used +// to retrieve glyph information from fonts. +#define ON_DOUBLE_BYTE_CODE_PAGE_SUPPORT +#endif + +#if defined(ON_DOUBLE_BYTE_CODE_PAGE_SUPPORT) + +///////////////////////////////////////////////////////// +// +// Code page 932 +// + +bool ON_IsPotentialWindowsCodePage932SingleByteEncoding( + ON__UINT32 x +); + +bool ON_IsPotentialWindowsCodePage932DoubleByteEncoding( + ON__UINT32 lead_byte, + ON__UINT32 trailing_byte +); + +/* +Description: + Convert a Windows code page 932 encoded value to a UNICODE code point. + This code page is often used for Japanese glpyhs. + +Parameters: + code_page_932_character_value - [in] + Valid values are 0 to 0xFDFE with some exceptions in that range. + unicode_code_point - [out] + ON_UnicodeCodePoint::ON_ReplacementCharacter is returned when code_page_932_character_value is not valid. + +Returns: + 1: if code_page_932_character_value and the corresponding UNICODE code point is returned in *unicode_code_point. + 0: otherwise and *unicode_code_point = ON_UnicodeCodePoint::ON_ReplacementCharacter. + +Remarks: + Windows code page 932: https://msdn.microsoft.com/en-us/library/cc194887.aspx + Conversions to Unicode are based on the Unicode.org mapping of Shift JIS + ftp://ftp.unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/JIS/SHIFTJIS.TXT +*/ +#if defined(ON_COMPILER_MSC) && defined(NDEBUG) + // Work around Release build optimization bug in Visual Studio 2017. +__declspec(noinline) +#endif +int ON_MapWindowsCodePage932ToUnicode( + ON__UINT32 code_page_932_character_value, + ON__UINT32* unicode_code_point +); + +///////////////////////////////////////////////////////// +// +// Code page 949 +// + +bool ON_IsPotentialWindowsCodePage949SingleByteEncoding( + ON__UINT32 x +); + +bool ON_IsPotentialWindowsCodePage949DoubleByteEncoding( + ON__UINT32 lead_byte, + ON__UINT32 trailing_byte +); + +/* +Description: + Convert a Windows code page 949 encoded value to a UNICODE code point. + This code page is often used for Korean glpyhs. + +Parameters: + code_page_949_character_value - [in] + Valid values are 0 to 0xFDFE with some exceptions in that range. + unicode_code_point - [out] + ON_UnicodeCodePoint::ON_ReplacementCharacter is returned when code_page_949_character_value is not valid. + +Returns: + 1: if code_page_949_character_value and the corresponding UNICODE code point is returned in *unicode_code_point. + 0: otherwise and *unicode_code_point = ON_UnicodeCodePoint::ON_ReplacementCharacter. + +Remarks: + Windows code page 949: https://msdn.microsoft.com/en-us/library/cc194941.aspx + Conversions to Unicode are based on the Unicode.org mapping of Windows-949 + ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP949.TXT +*/ +#if defined(ON_COMPILER_MSC) && defined(NDEBUG) + // Work around Release build optimization bug in Visual Studio 2017. +__declspec(noinline) +#endif +int ON_MapWindowsCodePage949ToUnicode( + ON__UINT32 code_page_949_character_value, + ON__UINT32* unicode_code_point +); + + +#endif + +#endif diff --git a/opennurbs/Include/opennurbs_intersect.h b/opennurbs/Include/opennurbs_intersect.h new file mode 100644 index 0000000..6436dbb --- /dev/null +++ b/opennurbs/Include/opennurbs_intersect.h @@ -0,0 +1,271 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_INTERSECT_INC_) +#define ON_INTERSECT_INC_ + +// These simple intersectors are fast and detect transverse intersections. +// If the intersection is not a simple transverse case, then they +// return false and you will have to use one of the slower but fancier +// models. + + +/* +Description: + Intersect two lines. +Parameters: + lineA - [in] + lineB - [in] + double* a - [out] + double* b - [out] The shortest distance between the lines is the + chord from lineA.PointAt(*a) to lineB.PointAt(*b). + tolerance - [in] If > 0.0, then an intersection is reported only + if the distance between the points is <= tolerance. + If <= 0.0, then the closest point between the lines + is reported. + bIntersectSegments - [in] if true, the input lines are treated + as finite segments. If false, the + input lines are treated as infinite lines. +Returns: + True if a closest point can be calculated and the result passes + the tolerance parameter test. +See Also: + ON_Intersect( const ON_Line& lineA, const ON_Line& line B) +Remarks: + If the lines are exactly parallel, meaning the system of equations + used to find a and b has no numerical solution, then false is returned. + If the lines are nearly parallel, which is often numerically true + even if you think the lines look exactly parallel, then the + closest points are found and true is returned. So, if you + care about weeding out "parallel" lines, then you need to + do something like the following. + + bool rc = ON_IntersectLineLine(lineA,lineB, + &a,&b, + tolerance, + bIntersectSegments); + if (rc) + { + double angle_tolerance_radians = 0.5*ON_PI/180.0; // or whatever + double parallel_tol = cos(angle_tolerance_radians); + if ( fabs(lineA.Tangent()*lineB.Tangent()) >= parallel_tol ) + { + ... do whatever you think is appropriate + } + } +*/ +ON_DECL +bool ON_IntersectLineLine( + const ON_Line& lineA, + const ON_Line& lineB, + double* a, + double* b, + double tolerance, + bool bIntersectSegments + ); + +/* +Description: + Find the closest point between two infinte lines. +Parameters: + lineA - [in] + lineB - [in] + double* a - [out] + double* b - [out] The shortest distance between the lines is the + chord from lineA.PointAt(*a) to lineB.PointAt(*b). +Returns: + True if points are found and false if the lines are numerically parallel. + Numerically parallel means the 2x2 matrix + + AoA -AoB + -AoB BoB + + is numerically singluar, where A = lineA.to-lineA.from + and B = lineB.to-lineB.from. +See Also: + ON_IntersectLineLine +*/ + +/* 15 Sept 2016 - Already in opennurbs_math.h +ON_DECL +bool ON_Intersect( + const ON_Line& lineA, + const ON_Line& lineB, + double* a, + double* b + ); + */ + +/* 15 Sept 2016 - Already in opennurbs_math.h + +ON_DECL +bool ON_Intersect( // Returns false unless intersection is a single point + // If returned parameter is < 0 or > 1, then the line + // segment between line.m_point[0] and line.m_point[1] + // does not intersect the plane + const ON_Line&, + const ON_Plane&, + double* // parameter on line + ); + */ + +/* +Parameters: + line - [in] + plane_equation - [in] + line_parameter - [out] + If the returned parameter is < 0 or > 1, then the + line segment between line.from and line.to + does not intersect the plane. +Returns: + true if the interesection is a singe point. + and false otherwise. + If returned parameter is < 0 or > 1, then the line + segment between line.m_point[0] and line.m_point[1] + does not intersect the plane +*/ +ON_DECL +bool ON_Intersect( + const ON_Line& line, + const ON_PlaneEquation& plane_equation, + double* line_parameter + ); +/* 15 Sept 2016 - Already in opennurbs_math.h + +ON_DECL +bool ON_Intersect( const ON_Plane&, + const ON_Plane&, + ON_Line& // intersection line is returned here + ); +*/ + +/* 15 Sept 2016 - Already in opennurbs_math.h + +ON_DECL +bool ON_Intersect( const ON_Plane&, + const ON_Plane&, + const ON_Plane&, + ON_3dPoint& // intersection point is returned here + ); + */ + +/* +Description: + Intersect a plane and a sphere. +Parameters: + plane - [in] + sphere - [in] + circle - [out] +Returns: + 0: no intersection + circle radius = 0 and circle origin = point on the plane + closest to the sphere. + 1: intersection is a single point + circle radius = 0; + 2: intersection is a circle + circle radius > 0. +*/ +/* 15 Sept 2016 - Already in opennurbs_math.h + +ON_DECL +int ON_Intersect( + const ON_Plane& plane, + const ON_Sphere& sphere, + ON_Circle& circle + ); +*/ + +/* 15 Sept 2016 - Already in opennurbs_math.h + +ON_DECL +int ON_Intersect( // returns 0 = no intersections, + // 1 = one intersection, + // 2 = 2 intersections + // If 0 is returned, first point is point + // on line closest to sphere and 2nd point is the point + // on the sphere closest to the line. + // If 1 is returned, first point is obtained by evaluating + // the line and the second point is obtained by evaluating + // the sphere. + const ON_Line&, const ON_Sphere&, + ON_3dPoint&, ON_3dPoint& // intersection point(s) returned here + ); +*/ + +/* 15 Sept 2016 - Already in opennurbs_math.h + +ON_DECL +int ON_Intersect( // returns 0 = no intersections, + // 1 = one intersection, + // 2 = 2 intersections + // 3 = line lies on cylinder + // If 0 is returned, first point is point + // on line closest to cylinder and 2nd point is the point + // on the sphere closest to the line. + // If 1 is returned, first point is obtained by evaluating + // the line and the second point is obtained by evaluating + // the sphere. + const ON_Line&, const ON_Cylinder&, + ON_3dPoint&, ON_3dPoint& // intersection point(s) returned here + ); +*/ +/* +Description: + Intersect an infinite line and an axis aligned bounding box. +Parameters: + bbox - [in] + line - [in] + tolerance - [in] If tolerance > 0.0, then the intersection is + performed against a box that has each side + moved out by tolerance. + line_parameters - [out] + Pass null if you do not need the parameters. + If true is returned and line.from != line.to, + then the chord from line.PointAt(line_parameters[0]) + to line.PointAt(line_parameters[1]) is the intersection. + If true is returned and line.from = line.to, then line.from + is in the box and the interval (0.0,0.0) is returned. + If false is returned, the input value of line_parameters + is not changed. +Returns: + True if the line intersects the box and false otherwise. +*/ +ON_DECL +bool ON_Intersect( const ON_BoundingBox& bbox, + const ON_Line& line, + double tolerance, + ON_Interval* line_parameters + ); + +/* +Description: + Intersect two spheres using exact calculations. +Parameters: + sphere0 - [in] + sphere1 - [in] + circle - [out] If intersection is a point, then that point will be the center, radius 0. +Returns: + 0 if no intersection, + 1 if a single point, + 2 if a circle, + 3 if the spheres are the same. +*/ +ON_DECL +int ON_Intersect( const ON_Sphere& sphere0, + const ON_Sphere& sphere1, + ON_Circle& circle + ); +#endif diff --git a/opennurbs/Include/opennurbs_ipoint.h b/opennurbs/Include/opennurbs_ipoint.h new file mode 100644 index 0000000..e19f13a --- /dev/null +++ b/opennurbs/Include/opennurbs_ipoint.h @@ -0,0 +1,433 @@ +// +// Copyright (c) 1993-2017 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// + + +#if !defined(OPENNURBS_IPOINT_INC_) +#define OPENNURBS_IPOINT_INC_ + +/* +A 2 dimensional point with integer coordinates. +Clear code will distinguish between situation where (x,y) is a +location (ON_2iPoint) or a direction (ON_2iVector) and use +the appropriate class. +*/ +class ON_CLASS ON_2iPoint +{ +public: + // Default construction intentionally leaves x and y uninitialized. + // Use something like + // ON_2iPoint pt(1,2); + // or + // ON_2iPoint pt = ON_2iPoint::Origin; + // when you need an initialized ON_2iPoint. + ON_2iPoint() = default; + + ~ON_2iPoint() = default; + ON_2iPoint(const ON_2iPoint& ) = default; + ON_2iPoint& operator=(const ON_2iPoint& ) = default; + + ON_2iPoint( + int x, + int y + ); + +public: + static const ON_2iPoint Origin; // (0,0) + static const ON_2iPoint Unset; // (ON_UNSET_INT_INDEX,ON_UNSET_INT_INDEX) + + /* + Dictionary order compare. + */ + static int Compare( + const ON_2iPoint& lhs, + const ON_2iPoint& rhs + ); + +public: + ON_2iPoint& operator+=(const class ON_2iVector&); + ON_2iPoint& operator-=(const class ON_2iVector&); + + // It is intentional that points are not added to points to encourage + // code that is clear about what is a location and what is diplacement. + +public: + /* + For those times when a location was incorrectly represented by a vector. + It is intentional that ther is not an ON_2iPoint constructor from an ON_2iVector. + */ + static const ON_2iPoint FromVector(const class ON_2iVector& v); + + static const ON_2iPoint From2dex(const class ON_2dex& src); + +public: + /* + Returns: + (0 == x && 0 == y) + */ + bool IsOrigin() const; + + /* + Returns: + (ON_UNSET_INT_INDEX == x || ON_UNSET_INT_INDEX ==y) + */ + bool IsSet() const; + +public: + ON__INT32 x; + ON__INT32 y; +}; + +ON_DECL +bool operator==(const ON_2iPoint&, const ON_2iPoint&); + +ON_DECL +bool operator!=(const ON_2iPoint&, const ON_2iPoint&); + + +/* +A 2 dimensional vector with integer coordinates. +Clear code will distinguish between situation where (x,y) is a +location (ON_2iPoint) or a direction (ON_2iVector) and use +the appropriate class. +*/ +class ON_CLASS ON_2iVector +{ +public: + // Default construction intentionally leaves x and y uninitialized. + // Use something like + // ON_2iVector pt(1,2); + // or + // ON_2iVector pt = ON_2iVector::Zero; + // when you need an initialized ON_2iVector. + ON_2iVector() = default; + + ~ON_2iVector() = default; + ON_2iVector(const ON_2iVector& ) = default; + ON_2iVector& operator=(const ON_2iVector& ) = default; + + ON_2iVector( + int x, + int y + ); + + /* + For those times when a direction was incorrectly represented by a point. + It is intentional that ther is not an ON_2iVector constructor from an ON_2iPoint. + */ + static const ON_2iVector FromPoint(const class ON_2iPoint& p); + + static const ON_2iVector From2dex(const class ON_2dex& src); + +public: + static const ON_2iVector Zero; // (0,0) + static const ON_2iVector UnitX; // (1,0) + static const ON_2iVector UnitY; // (0,1) + static const ON_2iVector Unset; // (ON_UNSET_INT_INDEX,ON_UNSET_INT_INDEX) + + /* + Dictionary order compare. + */ + static int Compare( + const ON_2iVector& lhs, + const ON_2iVector& rhs + ); + +public: + ON_2iVector& operator+=(const class ON_2iVector&); + ON_2iVector& operator-=(const class ON_2iVector&); + ON_2iVector& operator*=(int); + + ON_2iVector operator-() const; + +public: + /* + Returns: + (0 == x && 0 == y) + */ + bool IsZero() const; + + /* + Returns: + IsSet() && (0 != x || 0 != y) + */ + bool IsNotZero() const; + + /* + Returns: + (ON_UNSET_INT_INDEX == x || ON_UNSET_INT_INDEX ==y) + */ + bool IsSet() const; + +public: + ON__INT32 x; + ON__INT32 y; +}; + +ON_DECL +bool operator==(const ON_2iVector&, const ON_2iVector&); + +ON_DECL +bool operator!=(const ON_2iVector&, const ON_2iVector&); + +ON_DECL +ON_2iPoint operator+(const ON_2iPoint&, const ON_2iVector&); + +ON_DECL +ON_2iPoint operator-(const ON_2iPoint&, const ON_2iVector&); + +ON_DECL +ON_2iVector operator+(const ON_2iVector&, const ON_2iVector&); + +ON_DECL +ON_2iVector operator-(const ON_2iVector&, const ON_2iVector&); + +ON_DECL +ON_2iVector operator*(int, const ON_2iVector&); + +class ON_CLASS ON_2iBoundingBox +{ +public: + // Default construction intentionally leaves m_min and m_max uninitialized. + // Use something like + // ON_2iBoundingBox bbox(min_pt,max_pt); + // or + // ON_2iBoundingBox bbox = ON_2iBoundingBox::Unset; + ON_2iBoundingBox() = default; + + ~ON_2iBoundingBox() = default; + ON_2iBoundingBox(const ON_2iBoundingBox& ) = default; + ON_2iBoundingBox& operator=(const ON_2iBoundingBox& ) = default; + + ON_2iBoundingBox( + const class ON_2iPoint bbox_min, + const class ON_2iPoint bbox_max + ); + +public: + static const ON_2iBoundingBox Zero; // (ON_2iPoint::Origin,ON_2iPoint::Origin); + static const ON_2iBoundingBox Unset; // (ON_2iPoint::Unset,ON_2iPoint::Unset) + +public: + /* + Returns: + m_min.IsSet() && m_max.IsSet() && m_min.x <= m_max.x && m_min.y <= m_max.y. + */ + bool IsSet() const; + + const ON_2iPoint Min() const; + const ON_2iPoint Max() const; + +public: + ON_2iPoint m_min; + ON_2iPoint m_max; +}; + +ON_DECL +bool operator==(const ON_2iBoundingBox&, const ON_2iBoundingBox&); + +ON_DECL +bool operator!=(const ON_2iBoundingBox&, const ON_2iBoundingBox&); + +/* +Class ON_2iSize + For those situations where a Windows SDK SIZE or MFC CSize + value needs to be used in code that does not link with MFC. +*/ +class ON_CLASS ON_2iSize +{ +public: + // Default construction intentionally leaves x and y uninitialized. + // Use something like + // ON_2iSize pt(1,2); + // or + // ON_2iSize pt = ON_2iSize::Zero; + // when you need an initialized ON_2iSize. + ON_2iSize() = default; + + ~ON_2iSize() = default; + ON_2iSize(const ON_2iSize& ) = default; + ON_2iSize& operator=(const ON_2iSize& ) = default; + + ON_2iSize( + int cx, + int cy + ); + + /* + Dictionary compare. + Returns: + -1: lhs < rhs + 0: lsh == rsh + +1: lhs > rhs + */ + static int Compare( + const ON_2iSize& lhs, + const ON_2iSize& rhs + ); + + /* + Dictionary compare. + Returns: + -1: lhs < rhs + 0: lsh == rsh + +1: lhs > rhs + */ + static int ComparePointer( + const ON_2iSize* lhs, + const ON_2iSize* rhs + ); + +public: + static const ON_2iSize Zero; // (0,0) + static const ON_2iSize Unset; // (ON_UNSET_INT_INDEX,ON_UNSET_INT_INDEX) + +public: + /* + Returns: + true if both cx and cy are 0. + */ + bool IsZero() const; + + /* + Returns: + true if neither cx nor cy are ON_UNSET_INT_INDEX. + */ + bool IsSet() const; + +public: + ON__INT32 cx; + ON__INT32 cy; +}; + +ON_DECL +bool operator==( + const ON_2iSize& lhs, + const ON_2iSize& rhs + ); + +ON_DECL +bool operator!=( + const ON_2iSize& lhs, + const ON_2iSize& rhs + ); + +#if defined(ON_DLL_TEMPLATE) + +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; + +#endif + +/* +Class ON_4iRect + For those situations where a Windows SDK RECT or MFC CRect + value needs to be used in code that does not link with MFC. + If you want a traditional bounding box, use ON_2dBoundingBox. +*/ +class ON_CLASS ON_4iRect +{ +public: + // Default construction intentionally leaves x and y uninitialized. + // Use something like + // ON_4iRect pt(1,2,3,4); + // or + // ON_4iRect pt = ON_4iRect::Zero; + // when you need an initialized ON_4iRect. + ON_4iRect() = default; + + ~ON_4iRect() = default; + ON_4iRect(const ON_4iRect& ) = default; + ON_4iRect& operator=(const ON_4iRect& ) = default; + + ON_4iRect( + int left, + int top, + int right, + int bottom + ); + + ON_4iRect(const ON_2iPoint topLeft, const ON_2iPoint& bottomRight); + ON_4iRect(const ON_2iPoint& point, const ON_2iSize& size); + +public: + static const ON_4iRect Zero; // (0,0,0,0) + static const ON_4iRect Unset; // (ON_UNSET_INT_INDEX,ON_UNSET_INT_INDEX,ON_UNSET_INT_INDEX,ON_UNSET_INT_INDEX) + +public: + /* + Returns: + true if all of left, top, right, and bottom are set to 0. + */ + bool IsZero() const; + + void SetZero(); + + /* + Returns: + true if none of left, top, right, or bottom is set to ON_UNSET_INT_INDEX + */ + bool IsSet() const; + + int Width(void) const; + int Height(void) const; + + const ON_2iSize Size(void) const; + + const ON_2iPoint CenterPoint(void) const; + const ON_2iPoint TopLeft(void) const; + const ON_2iPoint BottomRight(void) const; + + bool IntersectRect(const ON_4iRect* r1, const ON_4iRect* r2); + bool IntersectRect(const ON_4iRect& r1, const ON_4iRect& r2); + + bool IsRectEmpty(void) const; + bool IsRectNull(void) const; + void SetRectEmpty(void) { *this = Zero; } + void SetRect(int l, int t, int r, int b); + + bool PtInRect(const ON_2iPoint& pt) const; + + void OffsetRect(int, int); + void OffsetRect(const ON_2iVector&); + void InflateRect(int, int); + void InflateRect(int, int, int, int); + void DeflateRect(int, int); + bool SubtractRect(const ON_4iRect* rect1, const ON_4iRect* rect2); + + void NormalizeRect(); + +public: + // NOTE WELL: + // Windows 2d integer device coordinates have a + // strong y-down bias and it is common for top < bottom. + // General 2d bounding boxes have a strong lower < upper / min < max bias. + // Take care when converting between ON_2iBoundingBox and ON_4iRect. + // It is intentional that no automatic conversion between bounding box + // and ON_4iRect is supplied because each case must be carefully considered. + ON__INT32 left; + ON__INT32 top; + ON__INT32 right; + ON__INT32 bottom; +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +#endif + + +ON_DECL +bool operator==(const ON_4iRect&, const ON_4iRect&); + +ON_DECL +bool operator!=(const ON_4iRect&, const ON_4iRect&); + +#endif diff --git a/opennurbs/Include/opennurbs_knot.h b/opennurbs/Include/opennurbs_knot.h new file mode 100644 index 0000000..a805621 --- /dev/null +++ b/opennurbs/Include/opennurbs_knot.h @@ -0,0 +1,492 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_KNOT_INC_) +#define OPENNURBS_KNOT_INC_ + +ON_DECL +double ON_DomainTolerance( + double, // start of domain + double // end of domain + ); + +ON_DECL +double ON_KnotTolerance( + int, // order (>=2) + int, // cv count + const double*, // knot[] array + int // knot index + ); + +ON_DECL +double ON_SpanTolerance( + int, // order (>=2) + int, // cv count + const double*, // knot[] array + int // span index + ); + +ON_DECL +int ON_KnotCount( // returns (order + cv_count - 2) + int, // order (>=2) + int // cv_count (>=order) + ); + +ON_DECL +int ON_KnotMultiplicity( + int, // order (>=2) + int, // cv_count (>=order) + const double*, // knot[] + int // knot_index + ); + +ON_DECL +int ON_KnotVectorSpanCount( + int, // order (>=2) + int, // cv count + const double* // knot[] array + ); + +ON_DECL +bool ON_GetKnotVectorSpanVector( + int, // order (>=2) + int, // cv count + const double*, // knot[] array + double* // s[] array + ); + +/* +Description: + Given an evaluation parameter t in the domain of a NURBS curve, + ON_NurbsSpanIndex(order,cv_count,knot,t,0,0) returns the integer + i such that (knot[i],...,knot[i+2*degree-1]), and + (cv[i],...,cv[i+degree]) are the knots and control points that + define the span of the NURBS that are used for evaluation at t. +Parameters: + order - [in] order >= 2 + cv_count - [in] cv_count >= order + knot - [in] valid knot vector + t - [in] evaluation parameter + side - [in] determines which span is used when t is at a knot + value; side = 0 for the default (from above), + side = -1 means from below, and + side = +1 means from above. + hint - [in] Search hint, or 0 if not hint is available. +Returns: + Returns the index described above. +*/ +ON_DECL +int ON_NurbsSpanIndex( + int order, + int cv_count, + const double* knot, + double t, + int side, + int hint + ); + +ON_DECL +int ON_NextNurbsSpanIndex( + // returns 0: input span_index < 0 + // cv_count-order: input span_index = cv_count-order + // -1: input span_index > cv_count-order; + // otherwise next span index + int order, + int cv_count, + const double* knot, + int // current span_index + ); + +ON_DECL +int ON_GetSpanIndices( // returns span count, which is one less than length of span_indices[] + int order, + int cv_count, + const double* knot, + int* // span_indices[cv_count-order+2]. + //Indices of knots at end of group of mult knots + //at start of span, and knot at start of group of mult knots + //at end of spline. + ); + +ON_DECL +double ON_SuperfluousKnot( + int order, + int cv_count, + const double* knot, + int // 0 = first superfluous knot + // 1 = last superfluous knot + ); + +ON_DECL +bool ON_IsKnotVectorPeriodic( + int order, + int cv_count, + const double* knot + ); + +ON_DECL +bool ON_IsKnotVectorClamped( + int order, + int cv_count, + const double* knot, + int = 2 // 0 = check left end, 1 = check right end, 2 = check both + ); + +ON_DECL +bool ON_IsKnotVectorUniform( + int order, + int cv_count, + const double* knot + ); + +////////// +// returns true if all knots have multiplicity = degree +ON_DECL +bool ON_KnotVectorHasBezierSpans( + int order, + int cv_count, + const double* knot + ); + + +ON_DECL +ON::knot_style ON_KnotVectorStyle( + int order, + int cv_count, + const double* knot + ); + +/* +Description: + Set the domain of a knot vector. +Parameters: + order - [in] order >= 2 + cv_count - [in] cv_count >= order + knot - [in/out] input existing knots and returns knots with new domain. + t0 - [in] + t1 - [in] New domain will be the interval (t0,t1). +Returns: + True if input is valid and the returned knot vector + has the requested domain. False if the input is + invalid, in which case the input knot vector is not + changed. +*/ +ON_DECL +bool ON_SetKnotVectorDomain( + int order, + int cv_count, + double* knot, + double t0, + double t1 + ); + +ON_DECL +bool ON_GetKnotVectorDomain( + int, // order (>=2) + int, // cv count + const double*, // knot[] array + double*, double* + ); + +ON_DECL +bool ON_ReverseKnotVector( + int, // order (>=2) + int, // cv count + double* // knot[] array + ); + +ON_DECL +int ON_CompareKnotVector( // returns + // -1: first < second + // 0: first == second + // +1: first > second + // first knot vector + int, // order (>=2) + int, // cv count + const double*, // knot[] array + // second knot vector + int, // order (>=2) + int, // cv count + const double* // knot[] array + ); + +ON_DECL +bool ON_IsValidKnotVector( + int order, + int cv_count, + const double* knot, + ON_TextLog* text_log = 0 + ); + +ON_DECL +bool ON_ClampKnotVector( + // Sets inital/final order-2 knots to values in + // knot[order-2]/knot[cv_count-1]. + int, // order (>=2) + int, // cv count + double*, // knot[] array + int // 0 = clamp left end, 1 = right end, 2 = clamp both ends + ); + +ON_DECL +bool ON_MakeKnotVectorPeriodic( + // Sets inital and final order-2 knots to values + // that make the knot vector periodic + int, // order (>=2) + int, // cv count + double* // knot[] array + ); + + /* + Description: + Fill in knot values for a clamped uniform knot + vector. + Parameters: + order - [in] (>=2) order (degree+1) of the NURBS + cv_count - [in] (>=order) total number of control points + in the NURBS. + knot - [in/out] Input is an array with room for + ON_KnotCount(order,cv_count) doubles. Output is + a clamped uniform knot vector with domain + (0, (1+cv_count-order)*delta). + delta - [in] (>0, default=1.0) spacing between knots. + Returns: + true if successful + See Also: + ON_NurbsCurve::MakeClampedUniformKnotVector +*/ +ON_DECL +bool ON_MakeClampedUniformKnotVector( + int order, + int cv_count, + double* knot, + double delta = 1.0 + ); + +/* + Description: + Fill in knot values for a clamped uniform knot + vector. + Parameters: + order - [in] (>=2) order (degree+1) of the NURBS + cv_count - [in] (>=order) total number of control points + in the NURBS. + knot - [in/out] Input is an array with room for + ON_KnotCount(order,cv_count) doubles. Output is + a periodic uniform knot vector with domain + (0, (1+cv_count-order)*delta). + delta - [in] (>0, default=1.0) spacing between knots. + Returns: + true if successful + See Also: + ON_NurbsCurve::MakePeriodicUniformKnotVector +*/ +ON_DECL +bool ON_MakePeriodicUniformKnotVector( + int order, + int cv_count, + double* knot, + double delta = 1.0 + ); + +ON_DECL +double ON_GrevilleAbcissa( // get Greville abcissae from knots + int, // order (>=2) + const double* // knot[] array (length = order-1) + ); + +ON_DECL +bool ON_GetGrevilleAbcissae( // get Greville abcissae from knots + int, // order (>=2) + int, // cv count + const double*, // knot[] array + bool, // true for periodic case + double* // g[] array has length cv_count in non-periodic case + // and cv_count-order+1 in periodic case + ); + +ON_DECL +bool ON_GetGrevilleKnotVector( // get knots from Greville abcissa + int, // g[] array stride (>=1) + const double*, // g[] array + // if not periodic, length = cv_count + // if periodic, length = cv_count-order+2 + bool, // true for periodic knots + int, // order (>=2) + int, // cv_count (>=order) + double* // knot[cv_count+order-2] + ); + +ON_DECL +bool ON_ClampKnotVector( + int, // cv_dim ( = dim+1 for rational cvs ) + int, // order (>=2) + int, // cv_count, + int, // cv_stride, + double*, // cv[] nullptr or array of order many cvs + double*, // knot[] array with room for at least knot_multiplicity new knots + int // end 0 = clamp start, 1 = clamp end, 2 = clamp both ends + ); + +/* +Returns: + Number of knots added. +*/ +ON_DECL +int ON_InsertKnot( + double, // knot_value, + int, // knot_multiplicity, (1 to order-1 including multiplicity of any existing knots) + int, // cv_dim ( = dim+1 for rational cvs ) + int, // order (>=2) + int, // cv_count, + int, // cv_stride (>=cv_dim) + double*, // cv[] nullptr or cv array with room for at least knot_multiplicity new cvs + double*, // knot[] knot array with room for at least knot_multiplicity new knots + int* // hint, optional hint about where to search for span to add knots to + // pass nullptr if no hint is available + ); + +/* +Description: + Reparameterize a rational Bezier curve. +Parameters: + c - [in] + reparameterization constant (generally speaking, c should be > 0). + The control points are adjusted so that + output_bezier(t) = input_bezier(lambda(t)), where + lambda(t) = c*t/( (c-1)*t + 1 ). + Note that lambda(0) = 0, lambda(1) = 1, lambda'(t) > 0, + lambda'(0) = c and lambda'(1) = 1/c. + dim - [in] + order - [in] + cvstride - [in] (>= dim+1) + cv - [in/out] homogeneous rational control points +Returns: + The cv values are changed so that + output_bezier(t) = input_bezier(lambda(t)). +*/ +ON_DECL +bool ON_ReparameterizeRationalBezierCurve( + double c, + int dim, + int order, + int cvstride, + double* cv + ); + +/* +Description: + Use a combination of scaling and reparameterization to set two rational + Bezier weights to specified values. +Parameters: + dim - [in] + order - [in] + cvstride - [in] ( >= dim+1) + cv - [in/out] homogeneous rational control points + i0 - [in] + w0 - [in] + i1 - [in] + w1 - [in] + The i0-th cv will have weight w0 and the i1-th cv will have weight w1. + If v0 and v1 are the cv's input weights, then v0, v1, w0 and w1 must + all be nonzero, and w0*v0 and w1*v1 must have the same sign. +Returns: + true if successful +Remarks: + The equations + s * r^i0 = w0/v0 + s * r^i1 = w1/v1 + determine the scaling and reparameterization necessary to change v0,v1 to + w0,w1. + + If the input Bezier has control vertices {B_0, ..., B_d}, then the + output Bezier has control vertices {s*B_0, ... s*r^i * B_i, ..., s*r^d * B_d}. +*/ +ON_DECL +bool ON_ChangeRationalBezierCurveWeights( + int dim, int order, int cvstride, double* cv, + int i0, double w0, + int i1, double w1 + ); + +/* +Description: + Reparameterize a rational NURBS curve. +Parameters: + c - [in] + reparameterization constant (generally speaking, c should be > 0). + The control points and knots are adjusted so that + output_nurbs(t) = input_nurbs(lambda(t)), where + lambda(t) = c*t/( (c-1)*t + 1 ). + Note that lambda(0) = 0, lambda(1) = 1, lambda'(t) > 0, + lambda'(0) = c and lambda'(1) = 1/c. + dim - [in] + order - [in] + cvstride - [in] (>=dim+1) + cv - [in/out] homogeneous rational control points + knot - [in/out] + NURBS curve knots +Returns: + The cv values are changed so that + output_bezier(t) = input_bezier(lambda(t)). +See Also: + ON_ChangeRationalNurbsCurveEndWeights +*/ +ON_DECL +bool ON_ReparameterizeRationalNurbsCurve( + double c, + int dim, + int order, + int cv_count, + int cvstride, + double* cv, + double* knot + ); + +/* +Description: + Use a combination of scaling and reparameterization to set the end + weights to the specified values. This +Parameters: + dim - [in] + order - [in] + cvstride - [in] (>=dim+1) + cv - [in/out] homogeneous rational control points + knot - [in/out] (output knot vector will be clamped and internal + knots may be shifted.) + w0 - [in] + w1 - [in] + The first cv will have weight w0 and the last cv will have weight w1. + If v0 and v1 are the cv's input weights, then v0, v1, w0 and w1 must + all be nonzero, and w0*v0 and w1*v1 must have the same sign. +Returns: + true if successful +See Also: + ON_ReparameterizeRationalNurbsCurve +*/ +ON_DECL +bool ON_ChangeRationalNurbsCurveEndWeights( + int dim, + int order, + int cv_count, + int cvstride, + double* cv, + double* knot, + double w0, + double w1 + ); + +#endif diff --git a/opennurbs/Include/opennurbs_layer.h b/opennurbs/Include/opennurbs_layer.h new file mode 100644 index 0000000..7bd8ebc --- /dev/null +++ b/opennurbs/Include/opennurbs_layer.h @@ -0,0 +1,772 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_LAYER_INC_) +#define OPENNURBS_LAYER_INC_ + +class ON_CLASS ON_Layer : public ON_ModelComponent +{ + ON_OBJECT_DECLARE(ON_Layer); + +public: + + ON_Layer() ON_NOEXCEPT; + ~ON_Layer() = default; + ON_Layer(const ON_Layer&); + ON_Layer& operator=(const ON_Layer&) = default; + + static const ON_Layer Unset; // index = ON_UNSET_INT_INDEX, id = nil + static const ON_Layer Default; // index = -1, id set, unique and persistent + + /* + Parameters: + model_component_reference - [in] + none_return_value - [in] + value to return if ON_Layer::Cast(model_component_ref.ModelComponent()) + is nullptr + Returns: + If ON_Layer::Cast(model_component_ref.ModelComponent()) is not nullptr, + that pointer is returned. Otherwise, none_return_value is returned. + */ + static const ON_Layer* FromModelComponentRef( + const class ON_ModelComponentReference& model_component_reference, + const ON_Layer* none_return_value + ); + + bool UpdateReferencedComponents( + const class ON_ComponentManifest& source_manifest, + const class ON_ComponentManifest& destination_manifest, + const class ON_ManifestMap& manifest_map + ) override; + + ////////////////////////////////////////////////////////////////////// + // + // ON_Object overrides + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + void Dump( ON_TextLog& ) const override; // for debugging + + bool Write( + ON_BinaryArchive& // serialize definition to binary archive + ) const override; + + bool Read( + ON_BinaryArchive& // restore definition from binary archive + ) override; + + ON::object_type ObjectType() const override; + + ////////////////////////////////////////////////////////////////////// + // + // Interface + + // The PER_VIEWPORT_SETTINGS enum defines + // the bits used to set masks in functions used + // to specify and query per viewport layer settings. + enum PER_VIEWPORT_SETTINGS : unsigned int + { + per_viewport_none = 0, + + per_viewport_id = 1, + per_viewport_color = 2, + per_viewport_plot_color = 4, + per_viewport_plot_weight = 8, + per_viewport_visible = 16, + per_viewport_persistent_visibility = 32, + + per_viewport_all_settings = 0xFFFFFFFF + // (Developers: these values are used in file IO and must not be changed.) + }; + + /* + Parameters: + viewport_id - [in] + If viewport_id is not nil, then checks for per viewport + settings for that specific viewport. + If viewport_id is nil, then checks for per viewport settings + in any viewport. + settings_mask - [in] + settings_mask is a bitfield that specifies which settings + to check for. The bits are defined in the + ON_Layer::PER_VIEWPORT_PROPERTIES enum. If you want to + determine if the layer has any per viewport settings, + then pass 0xFFFFFFFF. + Returns: + True if the layer has per viewport override for the specified + settings. + */ + bool HasPerViewportSettings( + ON_UUID viewport_id, + unsigned int settings_mask + ) const; + + /* + Parameters: + viewport_id - [in] + If viewport_id is not nil, then checks for setting for + that specific viewport. + If viewport_id is nil, then checks for any viewport settings. + Returns: + True if the layer has per viewport settings. + */ + bool HasPerViewportSettings( + const ON_UUID& viewport_id + ) const; + + + /* + Description: + Copies all per viewport settings for the source_viewport_id + Parameters: + source_viewport_id - [in] + viewport id to copy all per viewport settings from + destination_viewport_id - [in] + viewport od to copy all per viewport settings to + Returns: + True if the settings could be copied, False if no per-viewport + settings exist for the source viewport id + */ + bool CopyPerViewportSettings( + ON_UUID source_viewport_id, + ON_UUID destination_viewport_id + ); + + + /* + Description: + Copies specified per viewport settings from a source layer to this + layer. + Parameters: + source_layer - [in] + layer to copy settings from + viewport_id - [in] + viewport id to copy all per viewport settings from. + If viewport_id is nil, then the per viewport settings + for all viewports will be copied. + settings_mask - [in] + bits indicate which settings to copy + Use the ON_Layer PER_VIEWPORT_SETTINGS enum to + set the bits. + Returns: + True if the settings were copied, False if no per-viewport + settings exist for the specified viewport_id. + */ + bool CopyPerViewportSettings( + const ON_Layer& source_layer, + ON_UUID viewport_id, + unsigned int settings_mask + ); + + /* + Description: + Delete per viewport layer settings. + Parameters: + viewport_id - [in] + If viewport_id is not nil, then the settings for that + viewport are deleted. If viewport_id is nil, then all + per viewport settings are deleted. + */ + void DeletePerViewportSettings( + const ON_UUID& viewport_id + ) const; + + /* + Description: + Cull unused per viewport layer settings. + Parameters: + viewport_id_count - [in] + viewport_id_list - [in] + Settings for any viewports NOT in the viewport_id_list[] + are culled. + */ + void CullPerViewportSettings( + int viewport_id_count, + const ON_UUID* viewport_id_list + ); + + /* + Description: + The PerViewportSettingsCRC() can be used to determine + when layers have different per viewport settings. + */ + ON__UINT32 PerViewportSettingsCRC() const; + + /* + Description: + Set the color used by objects on this layer that do + not have a per object color set + Parameters: + layer_color - [in] + Passing ON_UNSET_COLOR will clear the settings. + viewport_id - [in] + If viewport_id is not nil, then the setting applies only + to the viewport with the specified id. + */ + void SetColor( ON_Color layer_color ); // layer display color + + /* + Description: + Set the color used by objects on this layer that do + not have a per object color set + Parameters: + viewport_id - [in] + If viewport_id is not nil, then the setting applies only + to the viewport with the specified id. + layer_color - [in] + Passing ON_UNSET_COLOR will clear the settings. + */ + void SetPerViewportColor( ON_UUID viewport_id, ON_Color layer_color ); + + // /* use ON_Layer::SetPerViewportColor */ + //ON_DEPRECATED void SetColor( ON_Color, const ON_UUID& ); + + /* + Parameters: + viewport_id - [in] + If viewport_id is not nil, then the setting to use + for a specific viewport is returned. + Returns: + The color used by objects on this layer that do + not have a per object color set. + */ + ON_Color Color() const; + + /* + Parameters: + viewport_id - [in] + If viewport_id is not nil, then the setting to use + for a specific viewport is returned. + Returns: + The color used by objects in the specified viewport and + on this layer that do not have a per object color set. + */ + ON_Color PerViewportColor( ON_UUID viewport_id ) const; + + // /* use ON_Layer::PerViewportColor */ + //ON_DEPRECATED ON_Color Color( const ON_UUID& ) const; + + /* + Description: + Remove any per viewport layer color setting so the + layer's overall setting will be used for all viewports. + Parameters: + viewport_id - [in] + If viewport_id is not nil, then the setting for this + viewport will be deleted. If viewport_id is nil, + the all per viewport layer color settings will be removed. + */ + void DeletePerViewportColor( const ON_UUID& viewport_id ); + + /* + Description: + Set the plotting color used by objects on this layer that do + not have a per object plotting color set + Parameters: + plot_color - [in] + Passing ON_UNSET_COLOR will clear the settings. + viewport_id - [in] + If viewport_id is not nil, then the setting applies only + to the viewport with the specified id. + */ + void SetPlotColor( ON_Color plot_color ); // plotting color + + void SetPerViewportPlotColor( ON_UUID viewport_id, ON_Color plot_color ); + + // /* use ON_Layer::SetPerViewportPlotColor */ + //ON_DEPRECATED void SetPlotColor( ON_Color, const ON_UUID& ); + + /* + Returns: + The plotting color used by objects on this layer that do + not have a per object color set. + */ + ON_Color PlotColor() const; + + /* + Parameters: + viewport_id - [in] + If viewport_id is not nil, then the setting to use + for a specific viewport is returned. + Returns: + The plotting color used by objects on this layer that do + not have a per object color set. + */ + ON_Color PerViewportPlotColor( ON_UUID viewport_id ) const; + + // /* use ON_Layer::PerViewportPlotColor */ + //ON_DEPRECATED ON_Color PlotColor( const ON_UUID& ) const; + + /* + Description: + Remove any per viewport plot color setting so the + layer's overall setting will be used for all viewports. + Parameters: + viewport_id - [in] + If viewport_id is not nil, then the setting for this + viewport will be deleted. If viewport_id is nil, + the all per viewport plot color settings will be removed. + */ + void DeletePerViewportPlotColor( const ON_UUID& viewport_id ); + + /* + Description: + Set the index of the linetype used by objects on this layer that do + not have a per object lintypes + Parameters: + linetype_index - [in] + Passing -1 will clear the setting. + */ + bool SetLinetypeIndex( int linetype_index ); + + /* + Returns: + The index of the linetype used by objects on this layer that do + not have a per object linetype set. + */ + int LinetypeIndex() const; + + /* + Returns: + Returns true if objects on layer are visible. + Remarks: + Does not inspect per viewport settings. + See Also: + ON_Layer::SetVisible + */ + bool IsVisible() const; + + /* + Description: + Controls layer visibility + Parameters: + bVisible - [in] true to make layer visible, + false to make layer invisible + viewport_id - [in] + If viewport_id is not nil, then the setting applies only + to the viewport with the specified id. + See Also: + ON_Layer::IsVisible + */ + void SetVisible( bool bVisible ); + + /* + Description: + The persistent visbility setting is used for layers whose + visibilty can be changed by a "parent" object. A common case + is when a layer is a child layer (ON_Layer.m_parent_id is + not nil). In this case, when a parent layer is turned off, + then child layers are also turned off. The persistent + visibility setting determines what happens when the parent + is turned on again. + Returns: + true: + If this layer's visibility is controlled by a parent object + and the parent is turned on (after being off), then this + layer will also be turned on. + false: + If this layer's visibility is controlled by a parent object + and the parent layer is turned on (after being off), then + this layer will continue to be off. + Remarks: + When the persistent visbility is not explicitly set, this + function returns the current value of IsVisible(). + See Also: + ON_Layer::SetPersistentVisibility + ON_Layer::UnsetPersistentVisibility + */ + bool PersistentVisibility() const; + + /* + Description: + Set the persistent visibility setting for this layer. + Parameters: + bPersistentVisibility - [in] + persistent visibility setting for this layer. + Remarks: + See ON_Layer::PersistentVisibility for a detailed description + of persistent visibility. + See Also: + ON_Layer::PersistentVisibility + ON_Layer::UnsetPersistentVisibility + */ + void SetPersistentVisibility( bool bPersistentVisibility ); + + /* + Description: + Remove any explicit persistent visibility setting from this + layer. When persistent visibility is not explictly set, + the value of ON_Layer::IsVisible() is used. + Remarks: + See ON_Layer::PersistentVisibility for a detailed description + of persistent visibility. + See Also: + ON_Layer::PersistentVisibility + ON_Layer::SetPersistentVisibility + */ + void UnsetPersistentVisibility(); + + /* + Parameters: + viewport_id - [in] + If viewport_id is not nil, then the visibility setting + for that viewport is returned. + + If viewport_id is nil, the ON_Layer::IsVisible() is returned. + Returns: + Returns true if objects on layer are visible. + */ + bool PerViewportIsVisible( ON_UUID viewport_id ) const; + + /* + Description: + Controls layer visibility in specific viewports. + Parameters: + viewport_id - [in] + If viewport_id is not nil, then the setting applies only + to the viewport with the specified id. If viewport_id + is nil, then the setting applies to all viewports with + per viewport layer settings. + bVisible - [in] true to make layer visible, + false to make layer invisible + See Also: + ON_Layer::IsVisibleInViewport() + */ + void SetPerViewportVisible( + ON_UUID viewport_id, + bool bVisible + ); + + // /* use ON_Layer::SetPerViewportVisible */ + // ON_DEPRECATED void SetVisible( bool, const ON_UUID& ); + + /* + Parameters: + viewport_id - [in] + id of a viewport. If viewport_id is nil, then + ON_Layer::PersistentVisibility() is returned. + Returns: + true: + If this layer's visibility in the specified viewport is + controlled by a parent object and the parent is turned on + (after being off), then this layer will also be turned on + in the specified viewport. + false: + If this layer's visibility in the specified viewport is + controlled by a parent object and the parent layer is + turned on (after being off), then this layer will continue + to be off in the specified viewport. + Remarks: + See ON_Layer::SetPersistentVisibility + for a description of persistent visibility. + See Also: + ON_Layer::SetPerViewportPersistentVisibility + */ + bool PerViewportPersistentVisibility( ON_UUID viewport_id ) const; + + /* + Description: + This function allows per viewport setting the + child visibility property. + Parameters + viewport_id - [in] + bPersistentVisibility - [in] + Remarks: + See ON_Layer::SetPersistentVisibility + for a description of the child visibility property. + See Also: + ON_Layer::SetPersistentVisibility + */ + void SetPerViewportPersistentVisibility( ON_UUID viewport_id, bool bPersistentVisibility ); + + void UnsetPerViewportPersistentVisibility( ON_UUID viewport_id ); + + /* + Description: + Remove any per viewport visibility setting so the + layer's overall setting will be used for all viewports. + Parameters: + viewport_id - [in] + If viewport_id is not nil, then the setting for this + viewport will be deleted. If viewport_id is nil, + the all per viewport visibility settings will be removed. + */ + void DeletePerViewportVisible( const ON_UUID& viewport_id ); + + /* + Description: + Get a list of the viewport ids of viewports that + that have per viewport visibility settings that + override the default layer visibility setting + ON_Layer::m_bVisible. + Parameters: + viewport_id_list - [out] + List of viewport id's that have a per viewport visibility + setting. If the returned list is empty, then there + are no per viewport visibility settings. + Returns: + Number of ids added to the list. + */ + void GetPerViewportVisibilityViewportIds( + ON_SimpleArray& viewport_id_list + ) const; + + /* + Description: + Controls layer locked + Parameters: + bLocked - [in] True to lock layer + False to unlock layer + See Also: + ON_Layer::IsLocked + */ + void SetLocked( bool bLocked ); + + /* + Description: + The persistent locking setting is used for layers that can + be locked by a "parent" object. A common case is when a layer + is a child layer (ON_Layer.m_parent_id is not nil). In this + case, when a parent layer is locked, then child layers are + also locked. The persistent locking setting determines what + happens when the parent is unlocked again. + Returns: + true: + If this layer's locking is controlled by a parent object + and the parent is unlocked (after being locked), then this + layer will also be unlocked. + false: + If this layer's locking is controlled by a parent object + and the parent layer is unlocked (after being locked), then + this layer will continue to be locked. + Remarks: + When the persistent locking is not explicitly set, this + function returns the current value of IsLocked(). + See Also: + ON_Layer::SetPersistentLocking + ON_Layer::UnsetPersistentLocking + */ + bool PersistentLocking() const; + + /* + Description: + Set the persistent locking setting for this layer. + Parameters: + bPersistentLocking - [in] + persistent locking for this layer. + Remarks: + See ON_Layer::PersistentLocking for a detailed description of + persistent locking. + See Also: + ON_Layer::PersistentLocking + ON_Layer::UnsetPersistentLocking + */ + void SetPersistentLocking(bool bPersistentLocking); + + /* + Description: + Remove any explicity persistent locking settings from this + layer. + Remarks: + See ON_Layer::PersistentLocking for a detailed description of + persistent locking. + See Also: + ON_Layer::PersistentLocking + ON_Layer::SetPersistentLocking + */ + void UnsetPersistentLocking(); + + /* + Returns: + Value of (IsVisible() && !IsLocked()). + */ + bool IsVisibleAndNotLocked() const; + + /* + Returns: + Value of (IsVisible() && IsLocked()). + */ + bool IsVisibleAndLocked() const; + + ////////// + // Index of render material for objects on this layer that have + // MaterialSource() == ON::material_from_layer. + // A material index of -1 indicates no material has been assigned + // and the material created by the default ON_Material constructor + // should be used. + bool SetRenderMaterialIndex( int ); // index of layer's rendering material + int RenderMaterialIndex() const; + + bool SetIgesLevel( int ); // IGES level for this layer + int IgesLevel() const; + + /* + Description: + Get the weight (thickness) of the plotting pen. + Returns: + Thickness of the plotting pen in millimeters. + A thickness of 0.0 indicates the "default" pen weight should be used. + A thickness of -1.0 indicates the layer should not be printed. + */ + double PlotWeight() const; + + double PerViewportPlotWeight( ON_UUID viewport_id ) const; + + // /* use ON_Layer::PerViewportPlotWeight */ + // ON_DEPRECATED double PlotWeight( const ON_UUID& ) const; + + /* + Description: + Set the weight of the plotting pen. + Parameters: + plot_weight_mm - [in] Set the thickness of the plotting pen in millimeters. + 0.0 means use the default pen width which is a Rhino app setting. + -1.0 means layer does not print (still displays on the screen) + */ + void SetPlotWeight(double plot_weight_mm); + + /* + Description: + Set the weight of the plotting pen. + Parameters: + plot_weight_mm - [in] Set the thickness of the plotting pen in millimeters. + 0.0 means use the default pen width which is a Rhino app setting. + -1.0 means layer does not print (still displays on the screen) + */ + void SetPerViewportPlotWeight(ON_UUID viewport_id, double plot_weight_mm); + + // /* use ON_Layer::SetPerViewportPlotWeight */ + // ON_DEPRECATED void SetPlotWeight(double, const ON_UUID& ); + + /* + Description: + Remove any per viewport plot weight setting so the + layer's overall setting will be used for all viewports. + Parameters: + viewport_id - [in] + If viewport_id is not nil, then the setting for this + viewport will be deleted. If viewport_id is nil, + the all per viewport plot weight settings will be removed. + */ + void DeletePerViewportPlotWeight( const ON_UUID& viewport_id ); + + /* + Description: + Use UpdateViewportIds() to change viewport ids in situations + like merging when a viewport id conflict requires the viewport + ids in a file to be changed. + Returns: + Number of viewport ids that were updated. + */ + int UpdateViewportIds( + const ON_UuidPairList& viewport_id_map + ); + +public: + + // Layers are origanized in a hierarchical + // structure (like file folders). + // If a layer is in a parent layer, + // then m_parent_layer_id is the id of + // the parent layer. + ON_UUID ParentLayerId() const; + + void SetParentLayerId( + ON_UUID parent_layer_id + ); + + int m_iges_level = -1; // IGES level number if this layer was made during IGES import + + // Rendering material: + // If you want something simple and fast, set + // m_material_index to the index of your rendering material + // and ignore m_rendering_attributes. + // If you are developing a fancy plug-in renderer, and a user is + // assigning one of your fabulous rendering materials to this + // layer, then add rendering material information to the + // m_rendering_attributes.m_materials[] array. + // + // Developers: + // As soon as m_rendering_attributes.m_materials[] is not empty, + // rendering material queries slow down. Do not populate + // m_rendering_attributes.m_materials[] when setting + // m_material_index will take care of your needs. + int m_material_index = -1; + ON_RenderingAttributes m_rendering_attributes; + + int m_linetype_index = -1; // index of linetype + + // Layer display attributes. + // If m_display_material_id is nil, then m_color is the layer color + // and defaults are used for all other display attributes. + // If m_display_material_id is not nil, then some complicated + // scheme is used to decide what objects on this layer look like. + // In all cases, m_color is a good choice if you don't want to + // deal with m_display_material_id. In Rhino, m_display_material_id + // is used to identify a registry entry that contains user specific + // display preferences. + ON_Color m_color = ON_Color::Black; + ON_UUID m_display_material_id = ON_nil_uuid; + + // Layer printing (plotting) attributes. + ON_Color m_plot_color = ON_Color::UnsetColor; // printing color + // ON_UNSET_COLOR means use layer color + double m_plot_weight_mm = 0.0; // printing pen thickness in mm + // 0.0 means use the default width (a Rhino app setting) + // -1.0 means layer does not print (still visible on screen) + + bool m_bExpanded = true; // If true, when the layer table is displayed in + // a tree control then the list of child layers is + // shown in the control. + +private: + // The following information may not be accurate and is subject + // to change at any time. + // + // m_extension_bits & 0x01: + // The value of ( m_extension_bits & 0x01) is used to speed + // common per viewport visiblity and color queries. + // 0x00 = there may be per viewport settings on this layer. + // 0x01 = there are no per viewport settings on this layer. + // + // m_extension_bits & 0x06: + // The value of ( m_extension_bits & 0x06) is the persistent + // visibility setting for this layer. + // 0x00 = no persistent visibility setting + // 0x02 = persistent visibility = true + // 0x04 = persistent visibility = false + // 0x06 = invalid value - treated as 0x00 + // + // m_extension_bits & 0x18: + // The value of ( m_extension_bits & 0x18) is the persistent + // locking setting for this layer. + // 0x00 = no persistent locking setting + // 0x08 = persistent locking = true + // 0x10 = persistent locking = false + // 0x18 = invalid value - treated as 0x00 + ON__UINT8 m_extension_bits = 0; + ON__UINT16 m_reserved = 0; + +private: + ON__UINT_PTR m_reserved_ptr = 0; +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray; +#endif + +#endif + diff --git a/opennurbs/Include/opennurbs_leader.h b/opennurbs/Include/opennurbs_leader.h new file mode 100644 index 0000000..d450a1e --- /dev/null +++ b/opennurbs/Include/opennurbs_leader.h @@ -0,0 +1,196 @@ + +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +// ON_Leader class +#ifndef OPENNURBS_LEADER_H_INCLUDED +#define OPENNURBS_LEADER_H_INCLUDED + + +class ON_CLASS ON_Leader : public ON_Annotation +{ + ON_OBJECT_DECLARE(ON_Leader); + +public: + ON_Leader(); + ~ON_Leader(); + + ON_Leader(const ON_Leader& src); + ON_Leader& operator=(const ON_Leader& src); + + static const ON_Leader Empty; + +private: + void Internal_Destroy(); + void Internal_CopyFrom(const ON_Leader& src); + +public: + + /* + Parameters: + dimstyle - [in] + If you want to specify text appearance or other custom properties ... + ON_DimStyle style = ON_DimStyle::DimStyleFromProperties( doc->DimStyleContext().CurrentDimStyle(), ... ); + style.Set...(...); + Then pass &style + + Remarks: + Parses text string and makes runs + */ + bool Create( + const wchar_t* leader_text, + const ON_DimStyle* dimstyle, + int point_count, + const ON_3dPoint* points, + const ON_Plane& plane, + bool bWrapped, + double rect_width + ); + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + void Dump(ON_TextLog& log) const override; + bool Write(ON_BinaryArchive& file) const override; + bool Read(ON_BinaryArchive& file) override; + ON::object_type ObjectType() const override; + + /* + Description: + Create a V6 leader from a V5 leader. + The function is used when reading V5 files. + Parameters: + v5_leader -[in] + dim_style - [in] + Dimstyle referenced by v5_leader or nullptr if not available. + destination - [in] + If destination is not nullptr, then the V6 leader is constructed + in destination. If destination is nullptr, then the new V6 leader + is allocated with a call to new ON_Leader(). + */ + static ON_Leader* CreateFromV5Leader( + const class ON_OBSOLETE_V5_Leader& V5_leader, + const class ON_3dmAnnotationContext* annotation_context, + ON_Leader* destination + ); + + int Dimension() const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + bool GetAnnotationBoundingBox( + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + double* boxmin, + double* boxmax, + bool bGrow = false + ) const override; // ON_Annotation override + + bool Transform(const ON_Xform& xform) override; + + bool GetTextGripPoints( + ON_2dPoint& base, + ON_2dPoint& width, + const ON_DimStyle* dimstyle, + double textscale) const; + + //bool Explode( + // const ON_DimStyle* dimstyle, + // ON_SimpleArray object_parts) const; + + // Transforms text from natural position at origin to + // 3d location as it displays in the leader + bool GetTextXform( + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + ON_Xform& text_xform_out + ) const override; + + bool GetTextXform( + const ON_Xform* model_xform, + const ON_Viewport* vp, + const ON_DimStyle* dimstyle, + double dimscale, + ON_Xform& text_xform_out + ) const; + + void UpdateTextAlignment(ON_2dVector angle); // Sets text to right or left justified per leader direction + + const ON_NurbsCurve* Curve( + const ON_DimStyle* dimstyle + ) const; // cached curve for display and picking + void DeleteCurve() const; + + void SetPlane(ON_Plane plane); + + //// TailDirection is the tangent direction + //// of the end of the leader tail + //// Returns 1,0 if there isn't a tangent + ON_2dVector TailDirection(const ON_DimStyle* dimstyle) const; + + // These do nothing and return false if + // HasLanding is false + // Otherwise, they return a line added to the + // tail of the leader in the direction of + // LeaderContentAngleStyle() + bool LandingLine2d( + const ON_DimStyle* style, + double dimscale, + ON_Line& line) const; + bool LandingLine3d( + const ON_DimStyle* style, + double dimscale, + ON_Line& line) const; + + ON__UINT32 PointCount() const; + void SetPoints2d(int count, const ON_2dPoint* points); + void SetPoints3d(int count, const ON_3dPoint* points); + bool SetPoint2d(int idx, ON_2dPoint point); + bool SetPoint3d(int idx, ON_3dPoint point); + void InsertPoint2d(int atidx, ON_2dPoint point); + void InsertPoint3d(int atidx, ON_3dPoint point); + void AppendPoint2d(ON_2dPoint point); + bool AppendPoint3d(ON_3dPoint point); + void RemovePoint(int idx); + bool Point2d(int idx, ON_2dPoint& point) const; + bool Point3d(int idx, ON_3dPoint& point) const; + + bool GetTextPoint2d( + const ON_DimStyle* dimstyle, + double leaderscale, + ON_2dPoint& point) const; + //bool GetTextPoint3d(ON_3dPoint& point) const; + ON_2dPointArray& Points2d(); + const ON_2dPointArray& Points2d() const; + + void InvalidateTextPoint(); + bool UpdateTextPosition( + const ON_DimStyle* dimstyle, + double leaderscale); + +private: + ON_2dPointArray m_points; + + // runtime + mutable ON_NurbsCurve* m_curve = nullptr; // Deleted by ~ON_Leader() + mutable ON_2dPoint m_text_point = ON_2dPoint::UnsetPoint; +}; + + + +#endif + diff --git a/opennurbs/Include/opennurbs_light.h b/opennurbs/Include/opennurbs_light.h new file mode 100644 index 0000000..556e18d --- /dev/null +++ b/opennurbs/Include/opennurbs_light.h @@ -0,0 +1,287 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_LIGHT_INC_) +#define OPENNURBS_LIGHT_INC_ + +class ON_CLASS ON_Light : public ON_Geometry +{ + ON_OBJECT_DECLARE(ON_Light); + +public: + ON_Light(); + ~ON_Light(); + ON_Light& operator=(const ON_Light&) = default; + ON_Light(const ON_Light&) = default; + + static const ON_Light Unset; + + ///////////////////////////////////////////////////////////////// + // + // ON_Object virtual functions + // + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + void Dump( ON_TextLog& ) const override; // for debugging + + // Use ON_BinaryArchive::WriteObject() and ON_BinaryArchive::ReadObject() + // for top level serialization. These Read()/Write() members should just + // write/read specific definitions. In particular, they should not write/ + // read any chunk typecode or length information. The default + // implementations return false and do nothing. + bool Write( + ON_BinaryArchive& // serialize definition to binary archive + ) const override; + + bool Read( + ON_BinaryArchive& // restore definition from binary archive + ) override; + + ON::object_type ObjectType() const override; + + // virtual + ON_UUID ModelObjectId() const override; + + + ///////////////////////////////////////////////////////////////// + // + // ON_Geometry virtual functions + // + int Dimension() const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + bool Transform( + const ON_Xform& + ) override; + + ///////////////////////////////////////////////////////// + // + // Interface + // + + void Default(); // make default light + + ///////////////////////////////////////////////////////// + // + // turn light on/off + // + bool Enable( bool = true ); // returns previous state + bool IsEnabled() const; + + ///////////////////////////////////////////////////////// + // + // style, location, and direction + // direction is ignored for "point" and "ambient" lights + // location is ignored for "directional" and "ambient" lights + void SetStyle(ON::light_style); + ON::light_style Style() const; + + const bool IsPointLight() const; + const bool IsDirectionalLight() const; + const bool IsSpotLight() const; + const bool IsLinearLight() const; + const bool IsRectangularLight() const; + + ON::coordinate_system CoordinateSystem() const; // determined by style + + /* + Description: + A light's location and direction can be defined with respect + to world, camera, or view coordinates. GetLightXform gets + the transformation from the light's intrinsic coordinate + system to the destination coordinate system specified + by dest_cs. + Parameters: + vp - [in] viewport where light is being used + dest_cs - [in] destination coordinate system + xform - [out] transformation from the light's intrinsic + coordinate system to cs. + Returns: + true if successful. + */ + bool GetLightXform( + const ON_Viewport& vp, + ON::coordinate_system dest_cs, + ON_Xform& xform + ) const; + + void SetLocation( const ON_3dPoint& ); + void SetDirection( const ON_3dVector& ); + + ON_3dPoint Location() const; + ON_3dVector Direction() const; + ON_3dVector PerpindicularDirection() const; + + double Intensity() const; // 0.0 = 0% 1.0 = 100% Only clamped above zero - no maximum. + void SetIntensity(double); + + double PowerWatts() const; + double PowerLumens() const; + double PowerCandela() const; + + void SetPowerWatts( double ); + void SetPowerLumens( double ); + void SetPowerCandela( double ); + + ///////////////////////////////////////////////////////// + // + // colors + // + void SetAmbient( ON_Color ); + void SetDiffuse( ON_Color ); + void SetSpecular( ON_Color ); + ON_Color Ambient() const; + ON_Color Diffuse() const; + ON_Color Specular() const; + + ///////////////////////////////////////////////////////// + // + // attenuation settings (ignored for "directional" and "ambient" lights) + // attenuation = 1/(a[0] + d*a[1] + d^2*a[2]) where d = distance to light + // + void SetAttenuation(double,double,double); + void SetAttenuation(const ON_3dVector&); + ON_3dVector Attenuation() const; + double Attenuation(double) const; // computes 1/(a[0] + d*a[1] + d^2*a[2]) where d = argument + // returns 0 if a[0] + d*a[1] + d^2*a[2] <= 0 + + ///////////////////////////////////////////////////////// + // + // spot light parameters (ignored for non-spot lights) + // + // angle = 0 to 90 degrees + // exponent = 0 to 128 (0=uniform, 128=high focus) + // + void SetSpotAngleDegrees( double ); + double SpotAngleDegrees() const; + + void SetSpotAngleRadians( double ); + double SpotAngleRadians() const; + + ////////// + // The spot exponent varies from 0.0 to 128.0 and provides + // an exponential interface for controling the focus or + // concentration of a spotlight (like the + // OpenGL GL_SPOT_EXPONENT parameter). The spot exponent + // and hot spot parameters are linked; changing one will + // change the other. + // A hot spot setting of 0.0 corresponds to a spot exponent of 128. + // A hot spot setting of 1.0 corresponds to a spot exponent of 0.0. + void SetSpotExponent( double ); + double SpotExponent() const; + + ////////// + // The hot spot setting runs from 0.0 to 1.0 and is used to + // provides a linear interface for controling the focus or + // concentration of a spotlight. + // A hot spot setting of 0.0 corresponds to a spot exponent of 128. + // A hot spot setting of 1.0 corresponds to a spot exponent of 0.0. + void SetHotSpot( double ); + double HotSpot() const; + + // The spotlight radii are useful for display UI. + bool GetSpotLightRadii( double* inner_radius, double* outer_radius ) const; + + + ///////////////////////////////////////////////////////// + // + // linear and rectangular light parameters + // (ignored for non-linear/rectangular lights) + // + void SetLength( const ON_3dVector& ); + ON_3dVector Length() const; + + void SetWidth( const ON_3dVector& ); + ON_3dVector Width() const; + + ///////////////////////////////////////////////////////// + // + // shadow parameters (ignored for non-spot lights) + // + // shadow intensity 0.0 = does not cast any shadows + // 1.0 = casts black shadows + // + void SetShadowIntensity(double); + double ShadowIntensity() const; + + + ///////////////////////////////////////////////////////// + // + // light index + // + void SetLightIndex( int ); + int LightIndex() const; + + ///////////////////////////////////////////////////////// + // + // light name + // + void SetLightName( const char* ); + void SetLightName( const wchar_t* ); + const ON_wString& LightName() const; + +public: + int m_light_index; + ON_UUID m_light_id; + ON_wString m_light_name; + + bool m_bOn; // true if light is on + ON::light_style m_style; // style of light + + ON_Color m_ambient; + ON_Color m_diffuse; + ON_Color m_specular; + + ON_3dVector m_direction; // ignored for "point" and "ambient" lights + ON_3dPoint m_location; // ignored for "directional" and "ambient" lights + ON_3dVector m_length; // only for linear and rectangular lights + // ends of linear lights are m_location and m_location+m_length + ON_3dVector m_width; // only for rectangular lights + // corners of rectangular lights are m_location, m_location+m_length, + // m_location+m_width, m_location+m_width+m_length + + double m_intensity; // Linear dimming/brightening factor: 0.0 = off, 1.0 = 100%. + // Values < 0.0 and values > 1.0 are permitted but are + // not consistently interpreted by various renderers. + // Renderers should clamp the range to [0.0, 1.0] if their + // lighting model does not support more exotic interpretations + // of m_intensity. + double m_watts; // Used by lighting models that reference lighting fixtures. + // Values < 0.0 are invalid. If m_watts is 0.0, the + // value is ignored. + + // spot settings - ignored for non-spot lights + double m_spot_angle; // 0.0 to 90.0 + double m_spot_exponent; // 0.0 to 128.0 + // 0.0 = uniform + // 128.0 = high focus + double m_hotspot; // 0.0 to 1.0 (See SetHotSpot() for details) + + // attenuation settings - ignored for "directional" and "ambient" lights + ON_3dVector m_attenuation; // each entry >= 0.0 + // att = 1/(a[0] + d*a[1] + d^2*a[2]) + // where d = distance to light + + // shawdow casting + double m_shadow_intensity; // 0.0 = no shadow casting, 1.0 = full shadow casting +}; + + + +#endif diff --git a/opennurbs/Include/opennurbs_line.h b/opennurbs/Include/opennurbs_line.h new file mode 100644 index 0000000..e8dc1b6 --- /dev/null +++ b/opennurbs/Include/opennurbs_line.h @@ -0,0 +1,606 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_LINE_INC_) +#define ON_LINE_INC_ + +class ON_CLASS ON_Line +{ +public: + + static const ON_Line ZeroLine; // (ON_3dPoint::Origin, ON_3dPoint::Origin) + static const ON_Line UnsetLine; // (ON_3dPoint::UnsetPoint, ON_3dPoint::UnsetPoint) + static const ON_Line NanLine; // (ON_3dPoint::NanPoint, ON_3dPoint::NanPoint) + + // Default constructor sets from = to = ON_3dPoint::Origin + ON_Line(); + ~ON_Line(); + + explicit ON_Line( + ON_3dPoint start, + ON_3dPoint end + ); + + explicit ON_Line( + ON_2dPoint start, + ON_2dPoint end + ); + + /* + Returns: + True if from != to and both from and to are valid. + */ + bool IsValid() const; + + // line[0] = start point line[1] = end point + ON_3dPoint& operator[](int); + const ON_3dPoint& operator[](int) const; + + + // Description: + // Create a line from two points. + // Parameters: + // start - [in] point at start of line segment + // end - [in] point at end of line segment + // Returns: + // true if start and end are distinct points. + bool Create( + const ON_3dPoint start, + const ON_3dPoint end + ); + bool Create( + const ON_2dPoint start, + const ON_2dPoint end + ); + + /* + Description: + Get line's 3d axis aligned bounding box. + Returns: + 3d bounding box. + */ + ON_BoundingBox BoundingBox() const; + + /* + Description: + Get line's 3d axis aligned bounding box or the + union of the input box with the object's bounding box. + Parameters: + bbox - [in/out] 3d axis aligned bounding box + bGrowBox - [in] (default=false) + If true, then the union of the input bbox and the + object's bounding box is returned in bbox. + If false, the object's bounding box is returned in bbox. + Returns: + true if object has bounding box and calculation was successful. + */ + bool GetBoundingBox( + ON_BoundingBox& bbox, + int bGrowBox = false + ) const; + + /* + Description: + Get tight bounding box. + Parameters: + tight_bbox - [in/out] tight bounding box + bGrowBox -[in] (default=false) + If true and the input tight_bbox is valid, then returned + tight_bbox is the union of the input tight_bbox and the + line's tight bounding box. + xform -[in] (default=nullptr) + If not nullptr, the tight bounding box of the transformed + line is calculated. The line is not modified. + Returns: + True if a valid tight_bbox is returned. + */ + bool GetTightBoundingBox( + ON_BoundingBox& tight_bbox, + bool bGrowBox = false, + const ON_Xform* xform = nullptr + ) const; + + /* + Description: + Get a plane that contains the line. + Parameters: + plane - [out] a plane that contains the line. The orgin + of the plane is at the start of the line. The distance + from the end of the line to the plane is <= tolerance. + If possible a plane parallel to the world xy, yz or zx + plane is returned. + tolerance - [in] + Returns: + true if a coordinate of the line's direction vector is + larger than tolerance. + */ + bool InPlane( ON_Plane& plane, double tolerance = 0.0 ) const; + + // Returns: + // Length of line + double Length() const; + + // Returns: + // direction vector = line.to - line.from + // See Also: + // ON_Line::Tangent + ON_3dVector Direction() const; + + // Returns: + // Unit tangent vector. + // See Also: + // ON_Line::Direction + ON_3dVector Tangent() const; + + /* + Description: + Evaluate point on (infinite) line. + Parameters: + t - [in] evaluation parameter. t=0 returns line.from + and t=1 returns line.to. + Returns: + (1-t)*line.from + t*line.to. + See Also: + ON_Line::Direction + ON_Line::Tangent + */ + ON_3dPoint PointAt( + double t + ) const; + + /* + Description: + Find the point on the (infinite) line that is + closest to the test_point. + Parameters: + test_point - [in] + t - [out] line.PointAt(*t) is the point on the line + that is closest to test_point. + Returns: + true if successful. + */ + bool ClosestPointTo( + const ON_3dPoint& test_point, + double* t + ) const; + + /* + Description: + Find the point on the (infinite) line that is + closest to the test_point. + Parameters: + test_point - [in] + Returns: + The point on the line that is closest to test_point. + */ + ON_3dPoint ClosestPointTo( + const ON_3dPoint& test_point + ) const; + + /* + Description: + Find the point on the (infinite) line that is + closest to the test_point. + Parameters: + test_point - [in] + Returns: + distance from the point on the line that is closest + to test_point. + See Also: + ON_3dPoint::DistanceTo + ON_Line::ClosestPointTo + */ + double DistanceTo( ON_3dPoint test_point ) const; + + + /* + Description: + Finds the shortest distance between the line as a finite + chord and the other object. + Parameters: + P - [in] + L - [in] (another finite chord) + Returns: + A value d such that if Q is any point on + this line and P is any point on the other object, + then d <= Q.DistanceTo(P). + */ + double MinimumDistanceTo( const ON_3dPoint& P ) const; + double MinimumDistanceTo( const ON_Line& L ) const; + + /* + Description: + Finds the longest distance between the line as a finite + chord and the other object. + Parameters: + P - [in] + L - [in] (another finite chord) + Returns: + A value d such that if Q is any point on this line and P is any + point on the other object, then d >= Q.DistanceTo(P). + */ + double MaximumDistanceTo( const ON_3dPoint& P ) const; + double MaximumDistanceTo( const ON_Line& other ) const; + + + /* + Description: + Quickly determine if the shortest distance from + this line to the other object is greater than d. + Parameters: + d - [in] distance (> 0.0) + P - [in] + L - [in] + Returns: + True if if the shortest distance from this line + to the other object is greater than d. + */ + bool IsFartherThan( double d, const ON_3dPoint& P ) const; + bool IsFartherThan( double d, const ON_Line& L ) const; + + + // For intersections see ON_Intersect(); + + // Description: + // Reverse line by swapping from and to. + void Reverse(); + + bool Transform( + const ON_Xform& xform + ); + + // rotate line about a point and axis + bool Rotate( + double sin_angle, + double cos_angle, + const ON_3dVector& axis_of_rotation, + const ON_3dPoint& center_of_rotation + ); + + bool Rotate( + double angle_in_radians, + const ON_3dVector& axis_of_rotation, + const ON_3dPoint& center_of_rotation + ); + + bool Translate( + const ON_3dVector& delta + ); + + +public: + ON_3dPoint from; // start point + ON_3dPoint to; // end point +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +#endif + +/* +Returns: + True if a and be are identical and no coordinate is a nan. +*/ +ON_DECL +bool operator==(const ON_Line& a, const ON_Line& b); + +/* +Returns: + True if a and be are not identical. +Remarks: + If a nan is involved in every coordinate compare, + the result will be false. +*/ +ON_DECL +bool operator!=(const ON_Line& a, const ON_Line& b); + + + +class ON_CLASS ON_Triangle +{ +public: + + static const ON_Triangle ZeroTriangle; // {ON_3dPoint::Origin, ON_3dPoint::Origin, ON_3dPoint::Origin} + static const ON_Triangle UnsetTriangle; // {ON_3dPoint::UnsetPoint, ON_3dPoint::UnsetPoint, ON_3dPoint::UnsetPoint} + static const ON_Triangle NanTriangle; // {ON_3dPoint::NanPoint, ON_3dPoint::NanPoint, ON_3dPoint::NanPoint} + + ON_Triangle() = default; // Default constructor is uninitialized + ON_Triangle(const ON_3dPoint vertices[3]); + ON_Triangle(const ON_3dPoint& a, const ON_3dPoint& b, const ON_3dPoint& c); + ON_Triangle(double x); // Allows Triangle(0.0) ZeroTriangle + ON_Triangle(const double vertices[9]); + + ON_Triangle(const ON_Triangle& tri) = default; + ON_Triangle& operator=(const ON_Triangle& tri) = default; + ~ON_Triangle() = default; + + operator ON_3dPoint*(); + operator const ON_3dPoint*() const; + + /* + Returns: + True if m_V[i].IsValid() for all i + */ + bool IsValid() const; + + // Triangle[i] = Triangle.m_V[i] + ON_3dPoint& operator[](int); + const ON_3dPoint& operator[](int) const; + + + // Description: + // Create a Triangle from three points. + // Parameters: + // vertices - [in] vertices + void Create(const ON_3dPoint vertices[3]); + + // Description: + // Create a Triangle from three points. + // Parameters: + // a,b,c - [in] vertices + void Create(const ON_3dPoint& a, const ON_3dPoint& b, const ON_3dPoint& c); + + /* + Description: + Get Triangles 3d axis aligned bounding box. + Returns: + 3d bounding box. + */ + ON_BoundingBox BoundingBox() const; + + /* + Description: + Get line's 3d axis aligned bounding box or the + union of the input box with the object's bounding box. + Parameters: + bbox - [in/out] 3d axis aligned bounding box + bGrowBox - [in] (default=false) + If true, then the union of the input bbox and the + object's bounding box is returned in bbox. + If false, the object's bounding box is returned in bbox. + Returns: + true if object has bounding box and calculation was successful. + */ + bool GetBoundingBox( + ON_BoundingBox& bbox, + int bGrowBox = false + ) const; + + /* + Description: + Get tight bounding box with respect to a given frame + Parameters: + tight_bbox - [in/out] tight bounding box + bGrowBox -[in] (default=false) + If true and the input tight_bbox is valid, then returned + tight_bbox is the union of the input tight_bbox and the + line's tight bounding box. + xform -[in] (default=nullptr) + If not nullptr, the tight bounding box of the transformed + triangle is calculated. The triangle is not modified. + Returns: + True if a valid tight_bbox is returned. + */ + bool GetTightBoundingBox( + ON_BoundingBox& tight_bbox, + bool bGrowBox = false, + const ON_Xform* xform = nullptr + ) const; + + // Returns: + // Index of edge opposite to m_V[i] that is longest. + // When lenghts are equal, lowest index has priority. + unsigned char LongestEdge() const; + + // Returns: + // Index of edge opposite to m_V[i] that is shortest. + // When lenghts are equal, lowest index has priority. + unsigned char ShortestEdge() const; + + // Returns: + // Edge opposite m_V[i] + // Specifically, + // ON_Line( m_V[(i+1)%3 ], m_V[(i+2)%3 ] ) + ON_Line Edge(int i) const; + + // Returns: + // true if Area()< tol + // Note: + // Recall Area = .5* base * height. So this degeneracy tests for + // a combination long enough and high enough. + // See Also: + // ON_Triangle::Area() + bool IsDegenerate(double tol = ON_ZERO_TOLERANCE) const; + + // Returns: + // Area of triangle + double Area() const; + + + // Returns: + // N = ( b-a) X ( c-a) + // where a,b,c are the verticies + // See Also: + // ON_Triangle UnitNormal() + ON_3dVector Normal() const; + + // Returns: + // Normal().Unitize() + // Notes: + // Ensure !IsDegenerate() to gaurentee that UnitNormal().Length()==1 + // and the result is not just a bunch of noise. Can return zero vector + // in some degenerate cases. + ON_3dVector UnitNormal() const; + + // Returns: + // Plane containing Triangle with normal given by UnitNormal(). + // Notes: + // Ensure !IsDegenerate() to gaurentee meaningful result + ON_PlaneEquation PlaneEquation() const; + + /* + Description: + Evaluate point on triangle. + Parameters: + s1, s2 - [in] evaluation parameter. + Returns: + (1-s1-s2)* m_V[0] + s1*m_V[1] + s2*m_V[2] + Notes: + Point is in the triangle iff s1>=0, s2>=0 and s1 + s2<=1. + Other values produce points on the plane of the triangle. + */ + ON_3dPoint PointAt( + double s1, double s2 + ) const; + + // Returns: + // Evaluation of PointAt(1/3.0, 1/3.0); + ON_3dPoint Centroid() const; + + /* + Description: + Find the point on the triangle that is + closest to the test_point. + Parameters: + test_point - [in] + s1, s2 - [out] PointAt( *s1, *s2) is the point on the + triangle closest to test_point. + Returns: + true if successful. + */ + bool ClosestPointTo( + const ON_3dPoint& test_point, + double* s1, double *s2 + ) const; + + /* + Description: + Find the point that is closest to the test_point. + Parameters: + test_point - [in] + constrainInside[in] - if true, variable are inside triangle + s1, s2 - [out] PointAt( *s1, *s2) is the point on the + triangle closest to test_point. + + Returns: + true if successful. + */ + bool GetBarycentricCoordinates( + const ON_3dPoint& test_point, + bool constrainInside, + double* s1, double *s2 + ) const; + + /* + Description: + Find the point on the triangle that is + closest to the test_point. + Parameters: + test_point - [in] + Returns: + The point on the line that is closest to test_point. + */ + ON_3dPoint ClosestPointTo( + const ON_3dPoint& test_point + ) const; + + /* + Description: + Find the point on the triangle that is + closest to the test_point. + Parameters: + test_point -[in] + Returns: + distance from the point on triangle that is closest + to test_point. + See Also: + ON_3dPoint::DistanceTo + ON_Line::ClosestPointTo + */ + double DistanceTo(const ON_3dPoint& test_point) const; + + + // Description: + // Reverse endpoints of Edge[i]. + void Reverse(int i); + + bool Transform( + const ON_Xform& xform + ); + + // rotate line about a point and axis + bool Rotate( + double sin_angle, + double cos_angle, + const ON_3dVector& axis_of_rotation, + const ON_3dPoint& center_of_rotation + ); + + bool Rotate( + double angle_in_radians, + const ON_3dVector& axis_of_rotation, + const ON_3dPoint& center_of_rotation + ); + + bool Translate( + const ON_3dVector& delta + ); + + // Description: + // Split the triangles into two, by choosing an edge and a new point that will appear along the edge. + // Parameters: + // edge - [in] Edge index as defined in Edge() + // pt - [in] Point to add as splitter along edge + // out_a - [out] First triangle + // out_b - [out] Second triangle + void Split(unsigned char edge, ON_3dPoint pt, ON_Triangle& out_a, ON_Triangle& out_b) const; + + // Description: + // Flip the normal of the triangle, by swapping the points of an edge. + // Parameters: + // edge - [in] The edge, as defined in the Edge() method. I.e., edge 0 swaps m_V[1] and m_V[2] + void Flip(unsigned char edge = 0); + + // Description: + // Circle the order of points in the triangle, without any influence to any geometric property. + // Parameters: + // move - [in] Amounts of rotations in the order of the three points. + // By means of examples, "move" of 1 will move m_V[0] to m_V[1], + // m_V[1] to m_V[2] and m_V[2] to m_V[0]. + void Spin(unsigned char move); + +public: + ON_3dPoint m_V[3]; // verticies +}; + +/* +Returns: +True if a and be are identical and no coordinate is a nan. +*/ +ON_DECL +bool operator==(const ON_Triangle& a, const ON_Triangle& b); + +/* +Returns: +True if a and be are not identical. +Remarks: +If a nan is involved in every coordinate compare, +the result will be false. +*/ +ON_DECL +bool operator!=(const ON_Triangle& a, const ON_Triangle& b); + +#endif diff --git a/opennurbs/Include/opennurbs_linecurve.h b/opennurbs/Include/opennurbs_linecurve.h new file mode 100644 index 0000000..76e5533 --- /dev/null +++ b/opennurbs/Include/opennurbs_linecurve.h @@ -0,0 +1,385 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(ON_GEOMETRY_CURVE_LINE_INC_) +#define ON_GEOMETRY_CURVE_LINE_INC_ + +class ON_LineCurve; +class ON_CLASS ON_LineCurve : public ON_Curve +{ + ON_OBJECT_DECLARE(ON_LineCurve); + +public: + ON_LineCurve() ON_NOEXCEPT; + virtual ~ON_LineCurve(); + ON_LineCurve(const ON_LineCurve&); + ON_LineCurve& operator=(const ON_LineCurve&); + +#if defined(ON_HAS_RVALUEREF) + // rvalue copy constructor + ON_LineCurve( ON_LineCurve&& ) ON_NOEXCEPT; + + // The rvalue assignment operator calls ON_Object::operator=(ON_Object&&) + // which could throw exceptions. See the implementation of + // ON_Object::operator=(ON_Object&&) for details. + ON_LineCurve& operator=( ON_LineCurve&& ); +#endif + + ON_LineCurve(const ON_2dPoint&,const ON_2dPoint&); // creates a 2d line curve + ON_LineCurve(const ON_3dPoint&,const ON_3dPoint&); // creates a 3d line curve + ON_LineCurve(const ON_Line&); + ON_LineCurve(const ON_Line&, + double,double // domain + ); + + + + ON_LineCurve& operator=(const ON_Line&); + + ///////////////////////////////////////////////////////////////// + // ON_Object overrides + + // virtual ON_Object::SizeOf override + unsigned int SizeOf() const override; + + // virtual ON_Object::DataCRC override + ON__UINT32 DataCRC(ON__UINT32 current_remainder) const override; + + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + void Dump( ON_TextLog& ) const override; // for debugging + + bool Write( + ON_BinaryArchive& // open binary file + ) const override; + + bool Read( + ON_BinaryArchive& // open binary file + ) override; + + ///////////////////////////////////////////////////////////////// + // ON_Geometry overrides + + int Dimension() const override; + + // virtual ON_Geometry GetBBox override + bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; + + // virtual ON_Geometry GetTightBoundingBox override + bool GetTightBoundingBox( class ON_BoundingBox& tight_bbox, bool bGrowBox = false, const class ON_Xform* xform = nullptr ) const override; + + bool Transform( + const ON_Xform& + ) override; + + // virtual ON_Geometry::IsDeformable() override + bool IsDeformable() const override; + + // virtual ON_Geometry::MakeDeformable() override + bool MakeDeformable() override; + + bool SwapCoordinates( + int, int // indices of coords to swap + ) override; + + + ///////////////////////////////////////////////////////////////// + // ON_Curve overrides + + ON_Interval Domain() const override; + + // Description: + // Set the domain of the curve + // Parameters: + // t0 - [in] + // t1 - [in] new domain will be [t0,t1] + // Returns: + // true if successful. + bool SetDomain( + double t0, + double t1 + ) override; + + bool ChangeDimension( + int desired_dimension + ) override; + + int SpanCount() const override; // number of smooth spans in curve + + bool GetSpanVector( // span "knots" + double* // array of length SpanCount() + 1 + ) const override; // + + int Degree( // returns maximum algebraic degree of any span + // ( or a good estimate if curve spans are not algebraic ) + ) const override; + + bool IsLinear( // true if curve locus is a line segment between + // between specified points + double = ON_ZERO_TOLERANCE // tolerance to use when checking linearity + ) const override; + + /* + Description: + Several types of ON_Curve can have the form of a polyline including + a degree 1 ON_NurbsCurve, an ON_PolylineCurve, and an ON_PolyCurve + all of whose segments are some form of polyline. IsPolyline tests + a curve to see if it can be represented as a polyline. + Parameters: + pline_points - [out] if not nullptr and true is returned, then the + points of the polyline form are returned here. + t - [out] if not nullptr and true is returned, then the parameters of + the polyline points are returned here. + Returns: + @untitled table + 0 curve is not some form of a polyline + >=2 number of points in polyline form + */ + //virtual + int IsPolyline( + ON_SimpleArray* pline_points = nullptr, + ON_SimpleArray* pline_t = nullptr + ) const override; + + bool IsArc( // ON_Arc.m_angle > 0 if curve locus is an arc between + // specified points + const ON_Plane* = nullptr, // if not nullptr, test is performed in this plane + ON_Arc* = nullptr, // if not nullptr and true is returned, then arc parameters + // are filled in + double = ON_ZERO_TOLERANCE // tolerance to use when checking + ) const override; + + bool IsPlanar( + ON_Plane* = nullptr, // if not nullptr and true is returned, then plane parameters + // are filled in + double = ON_ZERO_TOLERANCE // tolerance to use when checking + ) const override; + + bool IsInPlane( + const ON_Plane&, // plane to test + double = ON_ZERO_TOLERANCE // tolerance to use when checking + ) const override; + + bool IsClosed( // true if curve is closed (either curve has + void // clamped end knots and euclidean location of start + ) const override; // CV = euclidean location of end CV, or curve is + // periodic.) + + bool IsPeriodic( // true if curve is a single periodic segment + void + ) const override; + + /* + Description: + Force the curve to start at a specified point. + Parameters: + start_point - [in] + Returns: + true if successful. + Remarks: + Some end points cannot be moved. Be sure to check return + code. + See Also: + ON_Curve::SetEndPoint + ON_Curve::PointAtStart + ON_Curve::PointAtEnd + */ + bool SetStartPoint( + ON_3dPoint start_point + ) override; + + /* + Description: + Force the curve to end at a specified point. + Parameters: + end_point - [in] + Returns: + true if successful. + Remarks: + Some end points cannot be moved. Be sure to check return + code. + See Also: + ON_Curve::SetStartPoint + ON_Curve::PointAtStart + ON_Curve::PointAtEnd + */ + bool SetEndPoint( + ON_3dPoint end_point + ) override; + + bool Reverse() override; // reverse parameterizatrion + // Domain changes from [a,b] to [-b,-a] + + bool Evaluate( // returns false if unable to evaluate + double, // evaluation parameter + int, // number of derivatives (>=0) + int, // array stride (>=Dimension()) + double*, // array of length stride*(ndir+1) + int = 0, // optional - determines which side to evaluate from + // 0 = default + // < 0 to evaluate from below, + // > 0 to evaluate from above + int* = 0 // optional - evaluation hint (int) used to speed + // repeated evaluations + ) const override; + + + // Description: + // virtual ON_Curve::Trim override. + // Removes portions of the curve outside the specified interval. + // Parameters: + // domain - [in] interval of the curve to keep. Portions of the + // curve before curve(domain[0]) and after curve(domain[1]) are + // removed. + // Returns: + // true if successful. + bool Trim( + const ON_Interval& domain + ) override; + + // Description: + // Where possible, analytically extends curve to include domain. + // Parameters: + // domain - [in] if domain is not included in curve domain, + // curve will be extended so that its domain includes domain. + // Original curve is identical + // to the restriction of the resulting curve to the original curve domain, + // Returns: + // true if successful. + bool Extend( + const ON_Interval& domain + ) override; + + // Description: + // virtual ON_Curve::Split override. + // Divide the curve at the specified parameter. The parameter + // must be in the interior of the curve's domain. The pointers + // passed to Split must either be nullptr or point to an ON_Curve + // object of the same of the same type. If the pointer is nullptr, + // then a curve will be created in Split(). You may pass "this" + // as one of the pointers to Split(). + // Parameters: + // t - [in] parameter in interval Domain(). + // left_side - [out] left portion of curve + // right_side - [out] right portion of curve + // Example: + // For example, if crv were an ON_NurbsCurve, then + // + // ON_NurbsCurve right_side; + // crv.Split( crv.Domain().Mid() &crv, &right_side ); + // + // would split crv at the parametric midpoint, put the left side + // in crv, and return the right side in right_side. + bool Split( + double t, // t = curve parameter to split curve at + ON_Curve*& left_side, // left portion returned here + ON_Curve*& right_side // right portion returned here + ) const override; + + // Description: + // virtual ON_Curve::GetNurbForm override. + // Get a NURBS curve representation of this curve. + // Parameters: + // nurbs_curve - [out] NURBS representation returned here + // tolerance - [in] tolerance to use when creating NURBS + // representation. + // subdomain - [in] if not nullptr, then the NURBS representation + // for this portion of the curve is returned. + // Returns: + // 0 unable to create NURBS representation + // with desired accuracy. + // 1 success - returned NURBS parameterization + // matches the curve's to wthe desired accuracy + // 2 success - returned NURBS point locus matches + // the curve's to the desired accuracy but, on + // the interior of the curve's domain, the + // curve's parameterization and the NURBS + // parameterization may not match to the + // desired accuracy. + int GetNurbForm( + ON_NurbsCurve&, + double = 0.0, + const ON_Interval* = nullptr + ) const override; + + // Description: + // virtual ON_Curve::HasNurbForm override. + // Does a NURBS curve representation of this curve exist. + // Parameters: + // Returns: + // 0 unable to create NURBS representation + // with desired accuracy. + // 1 success - returned NURBS parameterization + // matches the curve's to wthe desired accuracy + // 2 success - returned NURBS point locus matches + // the curve's to the desired accuracy but, on + // the interior of the curve's domain, the + // curve's parameterization and the NURBS + // parameterization may not match to the + // desired accuracy. + int HasNurbForm( + ) const override; + + // Description: + // virtual ON_Curve::GetCurveParameterFromNurbFormParameter override. + // Convert a NURBS curve parameter to a curve parameter + // + // Parameters: + // nurbs_t - [in] nurbs form parameter + // curve_t - [out] curve parameter + // + // Remarks: + // If GetNurbForm returns 2, this function converts the curve + // parameter to the NURBS curve parameter. + // + // See Also: + // ON_Curve::GetNurbForm, ON_Curve::GetNurbFormParameterFromCurveParameter + //virtual + bool GetCurveParameterFromNurbFormParameter( + double nurbs_t, + double* curve_t + ) const override; + + // Description: + // virtual ON_Curve::GetNurbFormParameterFromCurveParameter override. + // Convert a curve parameter to a NURBS curve parameter. + // + // Parameters: + // curve_t - [in] curve parameter + // nurbs_t - [out] nurbs form parameter + // + // Remarks: + // If GetNurbForm returns 2, this function converts the curve + // parameter to the NURBS curve parameter. + // + // See Also: + // ON_Curve::GetNurbForm, ON_Curve::GetCurveParameterFromNurbFormParameter + //virtual + bool GetNurbFormParameterFromCurveParameter( + double curve_t, + double* nurbs_t + ) const override; + + ///////////////////////////////////////////////////////////////// + // Interface + + ON_Line m_line; + ON_Interval m_t; // domain + int m_dim; // 2 or 3 (2 so ON_LineCurve can be uses as a trimming curve) +}; + + +#endif diff --git a/opennurbs/Include/opennurbs_linestyle.h b/opennurbs/Include/opennurbs_linestyle.h new file mode 100644 index 0000000..552b238 --- /dev/null +++ b/opennurbs/Include/opennurbs_linestyle.h @@ -0,0 +1,139 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_LINESTYLE_INC_) +#define OPENNURBS_LINESTYLE_INC_ + + +/////////////////////////////////////////////////////////////////////////////// +// +// Class ON_DisplayMaterialRef +// + +/* +Description: + Objects can have per viewport display properties + that override a viewport's default display + properties. These overrides are stored on + ON_3dmObjectAttributes as a list of + ON_DisplayMaterialRefs. + +Example: + For example, by default a viewport + might display objects using a wireframe, but + one special object may need to be shaded. + In this case the special object would have + a display material ref with the "wireframe" + viewport's id and the id of a display material + that specified shading. +*/ +class ON_CLASS ON_DisplayMaterialRef +{ +public: + /* + Description: + Default constructor sets both ids to nil. + */ + ON_DisplayMaterialRef(); + int Compare(const ON_DisplayMaterialRef& other) const; + bool operator==(const ON_DisplayMaterialRef& other) const; + bool operator!=(const ON_DisplayMaterialRef& other) const; + bool operator<(const ON_DisplayMaterialRef& other) const; + bool operator<=(const ON_DisplayMaterialRef& other) const; + bool operator>(const ON_DisplayMaterialRef& other) const; + bool operator>=(const ON_DisplayMaterialRef& other) const; + + // C++ default destructor, copy constructor and operator= + // work fine. + + ON_UUID m_viewport_id; // identifies the ON_Viewport + // If nil, then the display material + // will be used in all viewports + // that are not explictly referenced + // in other ON_DisplayMaterialRefs. + + ON_UUID m_display_material_id; // id used to find display attributes + + // For Rhino V4 the per detail visibility attribute is implemented + // through a display material reference on an object. This is ONLY + // for for detail viewports and only for V4. Keep this uuid around + // so the per detail attributes in future versions of Rhino can be + // implemented a different way. + // {1403A7E4-E7AD-4a01-A2AA-41DAE6BE7ECB} + static const ON_UUID m_invisible_in_detail_id; +}; + +#if defined(ON_DLL_TEMPLATE) + +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; + +#endif +////////////////////////////////////////////////////////////////////// +// class ON_LinetypeSegment + +class ON_CLASS ON_LinetypeSegment +{ +public: + + static const ON_LinetypeSegment Unset; + static const ON_LinetypeSegment OneMillimeterLine; + +public: + ON_LinetypeSegment() = default; + ~ON_LinetypeSegment() = default; + ON_LinetypeSegment(const ON_LinetypeSegment&) = default; + ON_LinetypeSegment& operator=(const ON_LinetypeSegment&) = default; + + bool operator==( const ON_LinetypeSegment& src) const; + bool operator!=( const ON_LinetypeSegment& src) const; + + // For a curve to be drawn starting at the start point + // and ending at the endpoint, the first segment + // in the pattern must be a stLine type + enum class eSegType : unsigned int + { + Unset = 0, + stLine = 1, + stSpace = 2 + }; + + static ON_LinetypeSegment::eSegType SegmentTypeFromUnsigned( + unsigned int segment_type_as_unsigned + ); + + ON_LinetypeSegment( + double segment_length, + ON_LinetypeSegment::eSegType segment_type + ); + + void Dump( class ON_TextLog& ) const; + + // do not add read/write functions to this class + + double m_length = 0.0; // length in millimeters on printed output + eSegType m_seg_type = ON_LinetypeSegment::eSegType::Unset; + +private: + unsigned int m_reserved2 = 0; +}; + +#if defined(ON_DLL_TEMPLATE) + +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; + +#endif + +#endif diff --git a/opennurbs/Include/opennurbs_linetype.h b/opennurbs/Include/opennurbs_linetype.h new file mode 100644 index 0000000..0ee8460 --- /dev/null +++ b/opennurbs/Include/opennurbs_linetype.h @@ -0,0 +1,219 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_LINETYPE_INC_) +#define OPENNURBS_LINETYPE_INC_ + + +// Description: +// Determine if a line width is deemed to be a "hairline width" in Rhino +// Any width that is >0 and < 0.001 mm is a hairline width for printing +// Parameters: +// width_mm: [in] the width to examine in millimeters +// Returns: +// true if this is a hairline width +ON_DECL bool ON_IsHairlinePrintWidth( double width_mm ); + +// Description: +// Return a width in millimeters that is a valid hairline width in rhino +ON_DECL double ON_HairlinePrintWidth(); + + + + +////////////////////////////////////////////////////////////////////// +// class ON_Linetype + +class ON_CLASS ON_Linetype : public ON_ModelComponent +{ + ON_OBJECT_DECLARE(ON_Linetype); + +public: + // no attributes are set. + static const ON_Linetype Unset; + + // index = -1, id, name and pattern are set. + static const ON_Linetype Continuous; + + // index = -2, id, name and pattern are set. + static const ON_Linetype ByLayer; + + // index = -3, id, name and pattern are set. + static const ON_Linetype ByParent; + + // index = -4, id, name and pattern are set. + static const ON_Linetype Hidden; + + // index = -5, id, name and pattern are set. + static const ON_Linetype Dashed; + + // index = -6, id, name and pattern are set. + static const ON_Linetype DashDot; + + // index = -7, id, name and pattern are set. + static const ON_Linetype Center; + + // index = -8, id, name and pattern are set. + static const ON_Linetype Border; + + // index = -9, id, name and pattern are set. + static const ON_Linetype Dots; + + /* + Parameters: + model_component_reference - [in] + none_return_value - [in] + value to return if ON_Linetype::Cast(model_component_ref.ModelComponent()) + is nullptr + Returns: + If ON_Linetype::Cast(model_component_ref.ModelComponent()) is not nullptr, + that pointer is returned. Otherwise, none_return_value is returned. + */ + static const ON_Linetype* FromModelComponentRef( + const class ON_ModelComponentReference& model_component_reference, + const ON_Linetype* none_return_value + ); + +public: + + ON_Linetype() ON_NOEXCEPT; + ~ON_Linetype() = default; + ON_Linetype(const ON_Linetype&); + ON_Linetype& operator=(const ON_Linetype&) = default; + + /* + Description: + Tests that name is set and there is at least one non-zero length segment + */ + bool IsValid( class ON_TextLog* text_log = nullptr ) const override; + + void Dump( ON_TextLog& ) const override; // for debugging + + /* + Description: + Write to file + */ + bool Write( + ON_BinaryArchive& // serialize definition to binary archive + ) const override; + + /* + Description: + Read from file + */ + bool Read( + ON_BinaryArchive& // restore definition from binary archive + ) override; + + + ////////////////////////////////////////////////////////////////////// + // + // Interface + + bool PatternIsSet() const; + bool ClearPattern(); + bool PatternIsLocked() const; + void LockPattern(); + + /* + Description: + Returns the total length of one repeat of the pattern + */ + double PatternLength() const; + + + /* + Description: + Returns the number of segments in the pattern + */ + int SegmentCount() const; + + /* + Description: + Adds a segment to the pattern + Returns: + Index of the added segment. + */ + int AppendSegment( const ON_LinetypeSegment& segment); + + /* + Description: + Removes a segment in the linetype. + Parameters: + index - [in] + Zero based index of the segment to remove. + Returns: + True if the segment index was removed. + */ + bool RemoveSegment( int index ); + + /* + Description: + Sets the segment at index to match segment + */ + bool SetSegment( int index, const ON_LinetypeSegment& segment); + + /* + Description: + Sets the length and type of the segment at index + */ + bool SetSegment( int index, double length, ON_LinetypeSegment::eSegType type); + + /* + Description: + Set all segments + Parameters: + segments - [in] + */ + bool SetSegments(const ON_SimpleArray& segments); + + + /* + Description: + Returns a copy of the segment at index + */ + ON_LinetypeSegment Segment( int index) const; + + /* + Description: + Expert user function to get access to the segment array + for rapid calculations. + */ + // Returns nullptr if the line pattern is locked. + ON_SimpleArray* ExpertSegments(); + + const ON_SimpleArray& Segments() const; + +private: + enum : unsigned char + { + pattern_bit = 1 + }; + unsigned char m_is_set_bits = 0; + unsigned char m_is_locked_bits = 0; + unsigned short m_reserved1 = 0; + unsigned int m_reserved2 = 0; + ON_SimpleArray m_segments; +}; + +#if defined(ON_DLL_TEMPLATE) +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray; +ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray; +#endif + +#endif + diff --git a/opennurbs/Include/opennurbs_locale.h b/opennurbs/Include/opennurbs_locale.h new file mode 100644 index 0000000..33f7532 --- /dev/null +++ b/opennurbs/Include/opennurbs_locale.h @@ -0,0 +1,713 @@ +/* $NoKeywords: $ */ +/* +// +// Copyright (c) 1993-2014 Robert McNeel & Associates. All rights reserved. +// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert +// McNeel & Associates. +// +// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. +// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF +// MERCHANTABILITY ARE HEREBY DISCLAIMED. +// +// For complete openNURBS copyright information see . +// +//////////////////////////////////////////////////////////////// +*/ + +#if !defined(OPENNURBS_LOCALE_INC_) +#define OPENNURBS_LOCALE_INC_ + +typedef +#if defined(ON_RUNTIME_WIN) + _locale_t +#elif defined(ON_RUNTIME_APPLE) + locale_t +#elif defined(ON_RUNTIME_ANDROID) + locale_t +#else + ON__UINT_PTR +#endif + ON_CRT_locale_t; + +class ON_CLASS ON_Locale +{ +public: + + enum WindowsLCID : unsigned int + { + OrdinalLCID = 0, // not a real Windows LCID + + InvariantCultureLCID = 0x0027, // 39 decimal + + // Windows LCID for languages Rhino supports + + // "cs-CZ" Czech, ???? script implied + cs_CZ_LCID = 0x0405, //1029 decimal + + // "de-DE" German, Germany, Latn script implied + de_DE_LCID = 0x0407, // 1031 decimal + + // "en-US" English, US, Latn script implied + en_US_LCID = 0x0409, // 1033 decimal + + // "en-CA" English, Canada, Latn script implied + en_CA_LCID = 0x1009, // 4105 decimal + + // "es-ES_tradnl" Spanish, Spain, Latn script implied, traditional sort + es_ES_tradnl_LCID = 0x040A, // 1034 decimal + + // "es-ES" Spanish, Spain, Latn script implied, modern sort + es_ES_LCID = 0x0c0a, // 3082 decimal + + // "fr-FR" French, France, Latn script implied + fr_FR_LCID = 0x040c, // 1036 decimal + + // "it-IT" Italian, Italy, Latn script implied + it_IT_LCID = 0x0410, // 1040 decimal + + // "ja-JP" Japanese, Japan, ???? script implied + ja_JP_LCID = 0x0411, // 1041 decimal + + // Korean, Republic of Korea, ???? script implied + ko_KR_LCID = 0x0412, // 1042 decimal + + // Polish, Poland, ???? script implied + pl_PL_LCID = 0x0415, // 1045 decimal + + // Portuguese, Portugal, Latn script implied + pt_PT_LCID = 0x0816, // 2070 decimal + + // According to https://en.wikipedia.org/wiki/Chinese_language, Chinese is a family of language + // varieties, often mutually unintelligible. Specifying both Script and REGION + // (zh-Hans-CN or zh-Hant-TW) doesn't narrow things down nearly enough. + // + // Basically we have to hope the string collate and mapping functions supplied by the OS and + // the translations supplied by our staff work well for our customers who select from the + // two types of "Chinese" Rhino offers. + // + + // Standard Chinese (Mandarin), Peoples Republic of China, Hans script implied (simplified characters) + zh_CN_LCID = 0x0804, // 2052 decimal + + // Standard Chinese (Mandarin), Taiwan, Hant script implied (traditional characters) + zh_TW_LCID = 0x0404 // 1028 decimal + }; + + // The ordinal locale. + // String compares use ordinal element values. + // The decimal point is a period. + static const ON_Locale Ordinal; + + // The invariant culture locale. + // The decimal point is a period. + static const ON_Locale InvariantCulture; + +private: + static ON_Locale m_CurrentCulture; + +public: + // Reference to ON_Locale::m_CurrentCulture. + // The value is set by calling ON_Locale::SetCurrentCulture(); + // The default is a copy of ON_Locale::Ordinal. + static const ON_Locale& CurrentCulture; + + /* + Description: + Set the current culture locale + Parameters: + current_culture_locale - [in] + */ + static bool SetCurrentCulture( + const ON_Locale& current_culture_locale + ); + + + // Default construction creates a copy of ON_Local::Ordinal + ON_Locale() ON_NOEXCEPT; + + ~ON_Locale() = default; + ON_Locale(const ON_Locale&) = default; + ON_Locale& operator=(const ON_Locale&) = default; + + // Maximum buffer capacity for any ON_Locale functions + // that return string information in a buffer. + enum + { + BUFFER_MAXIMUM_CAPACITY = 128 + }; + + /* + Description: + Get the language id. + + Parameters: + buffer - [out] + A null terminated string containing the language id is returned in this buffer. + The string has the form: + + [-