Files
opennurbs/opennurbs_internal_V2_annotation.cpp
2024-08-22 01:43:04 -07:00

7140 lines
193 KiB
C++

//
// Copyright (c) 1993-2022 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 <http://www.opennurbs.org>.
//
////////////////////////////////////////////////////////////////
#include "opennurbs.h"
#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
// obsolete V2 and V5 annotation objects
#include "opennurbs_internal_V2_annotation.h"
#include "opennurbs_internal_V5_annotation.h"
// This define is up here so anybody who want's to defeat the
// bozo vaccine has to be doing it on purpose.
#define BOZO_VACCINE_699FCC4262D4488c9109F1B7A37CE926
// Added for v5 - 12-10-2009 LW
ON_OBJECT_IMPLEMENT(ON_OBSOLETE_V5_TextExtra,ON_UserData,"D90490A5-DB86-49f8-BDA1-9080B1F4E976");
ON_OBSOLETE_V5_TextExtra::ON_OBSOLETE_V5_TextExtra()
{
m_userdata_uuid = ON_CLASS_ID(ON_OBSOLETE_V5_TextExtra);
m_application_uuid = ON_opennurbs5_id; // opennurbs.dll reads/writes this userdata
// The id must be the version 5 id because
// V6 SaveAs V5 needs to work, but SaveAs
// V4 should not write this userdata.
m_userdata_copycount = 1;
SetDefaults();
}
ON_OBSOLETE_V5_TextExtra::~ON_OBSOLETE_V5_TextExtra()
{
}
ON_OBSOLETE_V5_TextExtra* ON_OBSOLETE_V5_TextExtra::TextExtension(ON_OBSOLETE_V5_TextObject* pText, bool bCreate)
{
ON_OBSOLETE_V5_TextExtra* pExtra = 0;
if(pText)
{
pExtra = ON_OBSOLETE_V5_TextExtra::Cast(pText->GetUserData(ON_CLASS_ID(ON_OBSOLETE_V5_TextExtra)));
if(pExtra == 0 && bCreate)
{
pExtra = new ON_OBSOLETE_V5_TextExtra;
if(pExtra)
{
if(!pText->AttachUserData(pExtra))
{
delete pExtra;
pExtra = 0;
}
}
}
}
return pExtra;
}
const
ON_OBSOLETE_V5_TextExtra* ON_OBSOLETE_V5_TextExtra::TextExtension(const ON_OBSOLETE_V5_TextObject* pText, bool bCreate)
{
return TextExtension((ON_OBSOLETE_V5_TextObject*)pText, bCreate);
}
void ON_OBSOLETE_V5_TextExtra::SetDefaults()
{
m_parent_uuid = ON_nil_uuid;
m_color_source = 0;
m_mask_color = 0;
m_border_offset = 0.1;
}
void ON_OBSOLETE_V5_TextExtra::Dump( ON_TextLog& text_log ) const
{
// do nothing
}
unsigned int ON_OBSOLETE_V5_TextExtra::SizeOf() const
{
unsigned int sz = ON_UserData::SizeOf();
sz += sizeof(*this) - sizeof(ON_UserData);
return sz;
}
bool ON_OBSOLETE_V5_TextExtra::Write(ON_BinaryArchive& archive) const
{
bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
if(rc) rc = archive.WriteUuid(m_parent_uuid);
if(rc) rc = archive.WriteBool(m_bDrawMask);
if(rc) rc = archive.WriteInt(m_color_source);
if(rc) rc = archive.WriteColor(m_mask_color);
if(rc) rc = archive.WriteDouble(m_border_offset);
if(!archive.EndWrite3dmChunk())
rc = false;
return rc;
}
bool ON_OBSOLETE_V5_TextExtra::Read(ON_BinaryArchive& archive)
{
int major_version = 1;
int minor_version = 0;
bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
if(!rc)
return false;
if(major_version != 1)
return false;
if(rc) rc = archive.ReadUuid(m_parent_uuid);
if(rc) rc = archive.ReadBool(&m_bDrawMask);
if(rc) rc = archive.ReadInt(&m_color_source);
if(rc) rc = archive.ReadColor(m_mask_color);
if(rc) rc = archive.ReadDouble(&m_border_offset);
if ( !archive.EndRead3dmChunk() )
rc = false;
return rc;
}
bool ON_OBSOLETE_V5_TextExtra::GetDescription( ON_wString& description)
{
description = L"Userdata extension of ON_OBSOLETE_V2_TextObject";
return true;
}
bool ON_OBSOLETE_V5_TextExtra::Archive() const
{
// true to write to file
return true;
}
ON_UUID ON_OBSOLETE_V5_TextExtra::ParentUUID() const
{
return m_parent_uuid;
}
void ON_OBSOLETE_V5_TextExtra::SetParentUUID( ON_UUID parent_uuid)
{
m_parent_uuid = parent_uuid;
}
bool ON_OBSOLETE_V5_TextExtra::DrawTextMask() const
{
return m_bDrawMask;
}
void ON_OBSOLETE_V5_TextExtra::SetDrawTextMask(bool bDraw)
{
m_bDrawMask = bDraw;
}
int ON_OBSOLETE_V5_TextExtra::MaskColorSource() const
{
return m_color_source;
}
void ON_OBSOLETE_V5_TextExtra::SetMaskColorSource(int source)
{
if(source == 1)
m_color_source = 1;
else
m_color_source = 0;
}
ON_Color ON_OBSOLETE_V5_TextExtra::MaskColor() const
{
return m_mask_color;
}
void ON_OBSOLETE_V5_TextExtra::SetMaskColor(ON_Color color)
{
m_mask_color = color;
}
double ON_OBSOLETE_V5_TextExtra::MaskOffsetFactor() const
{
return m_border_offset;
}
void ON_OBSOLETE_V5_TextExtra::SetMaskOffsetFactor(double offset)
{
m_border_offset = offset;
}
//--------------------
// Added for v5 - 4-20-07 LW
ON_OBJECT_IMPLEMENT(ON_OBSOLETE_V5_DimExtra,ON_UserData,"8AD5B9FC-0D5C-47fb-ADFD-74C28B6F661E");
ON_OBSOLETE_V5_DimExtra::ON_OBSOLETE_V5_DimExtra()
{
m_userdata_uuid = ON_CLASS_ID(ON_OBSOLETE_V5_DimExtra);
m_application_uuid = ON_opennurbs5_id; // opennurbs.dll reads/writes this userdata
// The id must be the version 5 id because
// V6 SaveAs V5 needs to work, but SaveAs
// V4 should not write this userdata.
m_userdata_copycount = 1;
SetDefaults();
}
ON_OBSOLETE_V5_DimExtra::~ON_OBSOLETE_V5_DimExtra()
{
}
static ON_OBSOLETE_V5_DimExtra* AnnotationExtension(ON_OBSOLETE_V5_Annotation* pDim, bool bCreate)
{
ON_OBSOLETE_V5_DimExtra* pExtra = 0;
if(pDim)
{
pExtra = ON_OBSOLETE_V5_DimExtra::Cast(pDim->GetUserData(ON_CLASS_ID(ON_OBSOLETE_V5_DimExtra)));
if(pExtra == 0 && bCreate)
{
pExtra = new ON_OBSOLETE_V5_DimExtra;
if( pExtra)
{
if(!pDim->AttachUserData(pExtra))
{
delete pExtra;
pExtra = 0;
}
}
}
}
return pExtra;
}
ON_OBSOLETE_V5_DimExtra* ON_OBSOLETE_V5_DimExtra::DimensionExtension(ON_OBSOLETE_V5_DimLinear* pDim, bool bCreate)
{
return AnnotationExtension((ON_OBSOLETE_V5_Annotation*)pDim, bCreate);
}
const
ON_OBSOLETE_V5_DimExtra* ON_OBSOLETE_V5_DimExtra::DimensionExtension(const ON_OBSOLETE_V5_DimLinear* pDim, bool bCreate)
{
return DimensionExtension((ON_OBSOLETE_V5_DimLinear*)pDim, bCreate);
}
ON_OBSOLETE_V5_DimExtra* ON_OBSOLETE_V5_DimExtra::DimensionExtension(ON_OBSOLETE_V5_DimRadial* pDim, bool bCreate)
{
return AnnotationExtension((ON_OBSOLETE_V5_Annotation*)pDim, bCreate);
}
const
ON_OBSOLETE_V5_DimExtra* ON_OBSOLETE_V5_DimExtra::DimensionExtension(const ON_OBSOLETE_V5_DimRadial* pDim, bool bCreate)
{
return DimensionExtension((ON_OBSOLETE_V5_DimRadial*)pDim, bCreate);
}
ON_OBSOLETE_V5_DimExtra* ON_OBSOLETE_V5_DimExtra::DimensionExtension(ON_OBSOLETE_V5_DimOrdinate* pDim, bool bCreate)
{
return AnnotationExtension((ON_OBSOLETE_V5_Annotation*)pDim, bCreate);
}
const
ON_OBSOLETE_V5_DimExtra* ON_OBSOLETE_V5_DimExtra::DimensionExtension(const ON_OBSOLETE_V5_DimOrdinate* pDim, bool bCreate)
{
return DimensionExtension((ON_OBSOLETE_V5_DimOrdinate*)pDim, bCreate);
}
void ON_OBSOLETE_V5_DimExtra::SetDefaults()
{
m_partent_uuid = ON_nil_uuid;
m_arrow_position = 0;
m_text_rects = 0;
m_distance_scale = 1.0;
m_modelspace_basepoint = ON_3dPoint::Origin;
m_detail_measured = ON_nil_uuid;
}
void ON_OBSOLETE_V5_DimExtra::Dump( ON_TextLog& text_log ) const
{
// do nothing
}
unsigned int ON_OBSOLETE_V5_DimExtra::SizeOf() const
{
unsigned int sz = ON_UserData::SizeOf();
sz += sizeof(*this) - sizeof(ON_UserData);
return sz;
}
bool ON_OBSOLETE_V5_DimExtra::Write(ON_BinaryArchive& archive) const
{
int major_version = 1;
int minor_version = 2;
bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,major_version,minor_version);
if(rc) rc = archive.WriteUuid( m_partent_uuid);
if(rc) rc = archive.WriteInt( m_arrow_position);
if(rc)
{
if( m_text_rects)
{
rc = archive.WriteInt( 7);
rc = archive.WriteInt( 28, (const int*)m_text_rects);
}
else
rc = archive.WriteInt( 0);
}
// 21 June 2010 Added distance scale, minor version 1
if(rc) rc = archive.WriteDouble(m_distance_scale);
// 27 Aug, 2014 Added detail measured, minor version 2
if (rc) rc = archive.WriteUuid(m_detail_measured);
if(!archive.EndWrite3dmChunk())
rc = false;
return rc;
}
bool ON_OBSOLETE_V5_DimExtra::Read(ON_BinaryArchive& archive)
{
int major_version = 1;
int minor_version = 0;
bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
if(!rc)
return false;
if(major_version < 1)
return false;
if(rc) rc = archive.ReadUuid(m_partent_uuid);
if(rc) rc = archive.ReadInt(&m_arrow_position);
int rect_count = 0;
if(rc) rc = archive.ReadInt( &rect_count);
if( rc && rect_count)
rc = archive.ReadInt( rect_count, (int*)m_text_rects);
// 21 June 2010 Added distance scale, minor version 1
if (minor_version > 0)
{
if (rc) rc = archive.ReadDouble(&m_distance_scale);
}
// 27 Aug, 2014 Added detail measured, minor version 2
if (minor_version > 1)
{
m_detail_measured = ON_nil_uuid;
if (rc) rc = archive.ReadUuid(m_detail_measured);
}
if (!archive.EndRead3dmChunk())
rc = false;
return rc;
}
bool ON_OBSOLETE_V5_DimExtra::GetDescription( ON_wString& description)
{
description = L"Userdata extension of ON_Dimensions";
return true;
}
bool ON_OBSOLETE_V5_DimExtra::Archive() const
{
// true to write to file
return true;
}
ON_UUID ON_OBSOLETE_V5_DimExtra::ParentUUID() const
{
return m_partent_uuid;
}
void ON_OBSOLETE_V5_DimExtra::SetParentUUID( ON_UUID partent_uuid)
{
m_partent_uuid = partent_uuid;
}
int ON_OBSOLETE_V5_DimExtra::ArrowPosition() const
{
return m_arrow_position;
}
void ON_OBSOLETE_V5_DimExtra::SetArrowPosition( int position)
{
if( position > 0)
m_arrow_position = 1;
else if( position < 0)
m_arrow_position = -1;
else
m_arrow_position = 0;
}
double ON_OBSOLETE_V5_DimExtra::DistanceScale() const
{
return m_distance_scale;
}
void ON_OBSOLETE_V5_DimExtra::SetDistanceScale(double s)
{
m_distance_scale = s;
}
void ON_OBSOLETE_V5_DimExtra::SetModelSpaceBasePoint(ON_3dPoint basepoint)
{
m_modelspace_basepoint = basepoint;
}
ON_3dPoint ON_OBSOLETE_V5_DimExtra::ModelSpaceBasePoint() const
{
return m_modelspace_basepoint;
}
ON_UUID ON_OBSOLETE_V5_DimExtra::DetailMeasured() const
{
return m_detail_measured;
}
void ON_OBSOLETE_V5_DimExtra::SetDetailMeasured(ON_UUID detail_id)
{
m_detail_measured = detail_id;
}
/*
const wchar_t* ON_OBSOLETE_V5_DimExtra::ToleranceUpperString() const
{
return m_upper_string;
}
ON_wString& ON_OBSOLETE_V5_DimExtra::ToleranceUpperString()
{
return m_upper_string;
}
void ON_OBSOLETE_V5_DimExtra::SetToleranceUpperString( const wchar_t* upper_string)
{
m_upper_string = upper_string;
}
void ON_OBSOLETE_V5_DimExtra::SetToleranceUpperString( ON_wString& upper_string)
{
m_upper_string = upper_string;
}
const wchar_t* ON_OBSOLETE_V5_DimExtra::ToleranceLowerString() const
{
return m_lower_string;
}
ON_wString& ON_OBSOLETE_V5_DimExtra::ToleranceLowerString()
{
return m_lower_string;
}
void ON_OBSOLETE_V5_DimExtra::SetToleranceLowerString( const wchar_t* lower_string)
{
m_lower_string = lower_string;
}
void ON_OBSOLETE_V5_DimExtra::SetToleranceLowerString( ON_wString& lower_string)
{
m_lower_string = lower_string;
}
const wchar_t* ON_OBSOLETE_V5_DimExtra::AlternateString() const
{
return m_alt_string;
}
ON_wString& ON_OBSOLETE_V5_DimExtra::AlternateString()
{
return m_alt_string;
}
void ON_OBSOLETE_V5_DimExtra::SetAlternateString( const wchar_t* alt_string)
{
m_alt_string = alt_string;
}
void ON_OBSOLETE_V5_DimExtra::SetAlternateString( ON_wString& alt_string)
{
m_alt_string = alt_string;
}
const wchar_t* ON_OBSOLETE_V5_DimExtra::AlternateToleranceUpperString() const
{
return m_alt_upper_string;
}
ON_wString& ON_OBSOLETE_V5_DimExtra::AlternateToleranceUpperString()
{
return m_alt_upper_string;
}
void ON_OBSOLETE_V5_DimExtra::SetAlternateToleranceUpperString( const wchar_t* upper_string)
{
m_alt_upper_string = upper_string;
}
void ON_OBSOLETE_V5_DimExtra::SetAlternateToleranceUpperString( ON_wString& upper_string)
{
m_alt_upper_string = upper_string;
}
const wchar_t* ON_OBSOLETE_V5_DimExtra::AlternateToleranceLowerString() const
{
return m_alt_lower_string;
}
ON_wString& ON_OBSOLETE_V5_DimExtra::AlternateToleranceLowerString()
{
return m_alt_lower_string;
}
void ON_OBSOLETE_V5_DimExtra::SetAlternateToleranceLowerString( const wchar_t* lower_string)
{
m_alt_lower_string = lower_string;
}
void ON_OBSOLETE_V5_DimExtra::SetAlternateToleranceLowerString( ON_wString& lower_string)
{
m_alt_lower_string = lower_string;
}
*/
//--------------------
ON_VIRTUAL_OBJECT_IMPLEMENT( ON_OBSOLETE_V5_Annotation, ON_Geometry, "8D820224-BC6C-46b4-9066-BF39CC13AEFB");
ON_OBJECT_IMPLEMENT( ON_OBSOLETE_V5_DimLinear, ON_OBSOLETE_V5_Annotation, "BD57F33B-A1B2-46e9-9C6E-AF09D30FFDDE");
ON_OBJECT_IMPLEMENT( ON_OBSOLETE_V5_DimRadial, ON_OBSOLETE_V5_Annotation, "B2B683FC-7964-4e96-B1F9-9B356A76B08B");
ON_OBJECT_IMPLEMENT( ON_OBSOLETE_V5_DimAngular, ON_OBSOLETE_V5_Annotation, "841BC40B-A971-4a8e-94E5-BBA26D67348E");
ON_OBJECT_IMPLEMENT( ON_OBSOLETE_V5_TextObject, ON_OBSOLETE_V5_Annotation, "46F75541-F46B-48be-AA7E-B353BBE068A7");
ON_OBJECT_IMPLEMENT( ON_OBSOLETE_V5_Leader, ON_OBSOLETE_V5_Annotation, "14922B7A-5B65-4f11-8345-D415A9637129");
ON_OBJECT_IMPLEMENT( ON_TextDot, ON_Geometry, "74198302-CDF4-4f95-9609-6D684F22AB37");
ON_OBJECT_IMPLEMENT( ON_OBSOLETE_V5_DimOrdinate,ON_OBSOLETE_V5_Annotation, "C8288D69-5BD8-4f50-9BAF-525A0086B0C3");
// class ON_OBSOLETE_V5_Annotation
//--------------------------------------------------------------------
int ON_OBSOLETE_V5_Annotation::V5_3dmArchiveDimStyleIndex() const
{
return m_v5_3dm_archive_dimstyle_index;
}
void ON_OBSOLETE_V5_Annotation::SetV5_3dmArchiveDimStyleIndex(
int V5_dim_style_index
)
{
m_v5_3dm_archive_dimstyle_index = V5_dim_style_index;
}
void ON_OBSOLETE_V5_Annotation::Create()
{
Destroy();
m_textdisplaymode = ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kAboveLine;
m_v5_3dm_archive_dimstyle_index = -1;
m_textheight = 1.0;
}
void ON_OBSOLETE_V5_Annotation::Destroy()
{
m_v5_3dm_archive_dimstyle_index = -1;
// 10-27-03 LW memory leak prevention
m_points.Empty();
SetTextValue(0);
SetTextFormula(0);
m_type = ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtNothing;
m_plane = ON_xy_plane;
m_userpositionedtext = false;
m_justification = 0;
m_annotative_scale = true;
}
void ON_OBSOLETE_V5_Annotation::EmergencyDestroy()
{
m_points.EmergencyDestroy();
m_usertext.EmergencyDestroy();
}
ON_OBSOLETE_V5_Annotation::ON_OBSOLETE_V5_Annotation()
{
Create();
}
ON_OBSOLETE_V5_Annotation::~ON_OBSOLETE_V5_Annotation()
{
Destroy();
}
ON_OBSOLETE_V5_Annotation* ON_OBSOLETE_V5_Annotation::CreateFromV2Annotation(
const class ON_OBSOLETE_V2_Annotation& V2_annotation,
const class ON_3dmAnnotationContext* annotation_context
)
{
for (;;)
{
const ON_OBSOLETE_V2_Leader* V2_leader = ON_OBSOLETE_V2_Leader::Cast(&V2_annotation);
if (nullptr == V2_leader && ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader == V2_annotation.m_type)
V2_leader = static_cast<const ON_OBSOLETE_V2_Leader*>(&V2_annotation);
if (nullptr == V2_leader)
break;
return ON_OBSOLETE_V5_Leader::CreateFromV2Leader(
*V2_leader,
annotation_context,
nullptr
);
}
for(;;)
{
const ON_OBSOLETE_V2_TextObject* V2_text_object = ON_OBSOLETE_V2_TextObject::Cast(&V2_annotation);
if (nullptr == V2_text_object)
break;
return ON_OBSOLETE_V5_TextObject::CreateFromV2TextObject(
*V2_text_object,
annotation_context,
nullptr
);
}
for(;;)
{
const ON_OBSOLETE_V2_DimRadial* V2_radial_dimension = ON_OBSOLETE_V2_DimRadial::Cast(&V2_annotation);
if (nullptr == V2_radial_dimension)
break;
return ON_OBSOLETE_V5_DimRadial::CreateFromV2RadialDimension(
*V2_radial_dimension,
annotation_context,
nullptr
);
}
for(;;)
{
const ON_OBSOLETE_V2_DimLinear* V2_linear_dimension = ON_OBSOLETE_V2_DimLinear::Cast(&V2_annotation);
if (nullptr == V2_linear_dimension)
break;
return ON_OBSOLETE_V5_DimLinear::CreateFromV2LinearDimension(
*V2_linear_dimension,
annotation_context,
nullptr
);
}
for(;;)
{
const ON_OBSOLETE_V2_DimAngular* V2_angular_dimension = ON_OBSOLETE_V2_DimAngular::Cast(&V2_annotation);
if (nullptr == V2_angular_dimension)
break;
return ON_OBSOLETE_V5_DimAngular::CreateFromV2AngularDimension(
*V2_angular_dimension,
annotation_context,
nullptr
);
}
return nullptr;
}
////void ON_OBSOLETE_V5_Annotation::Internal_SetDimStyleFromV6Annotation(
//// const class ON_Annotation& V6_annotation,
//// const class ON_3dmAnnotationContext* annotation_context
////)
////{
//// if (nullptr != annotation_context)
//// SetV6_DimStyleId(annotation_context->DimStyleId(), annotation_context->V5_ArchiveDimStyleIndex());
//// else
//// SetV6_DimStyleId(V6_annotation.DimensionStyleId(), ON_UNSET_INT_INDEX);
////}
ON_OBSOLETE_V5_Annotation* ON_OBSOLETE_V5_Annotation::CreateFromV6Annotation(
const class ON_Annotation& V6_annotation,
const class ON_3dmAnnotationContext* annotation_context
)
{
const ON_Text* V6_text_object = ON_Text::Cast(&V6_annotation);
if (nullptr != V6_text_object)
return ON_OBSOLETE_V5_TextObject::CreateFromV6TextObject(*V6_text_object, annotation_context, nullptr);
const ON_Leader* V6_leader = ON_Leader::Cast(&V6_annotation);
if (nullptr != V6_leader)
return ON_OBSOLETE_V5_Leader::CreateFromV6Leader(*V6_leader, annotation_context, nullptr);
const ON_DimRadial* V6_dim_radial = ON_DimRadial::Cast(&V6_annotation);
if (nullptr != V6_dim_radial)
return ON_OBSOLETE_V5_DimRadial::CreateFromV6DimRadial(*V6_dim_radial, annotation_context, nullptr);
const ON_DimLinear* V6_dim_linear = ON_DimLinear::Cast(&V6_annotation);
if (nullptr != V6_dim_linear)
return ON_OBSOLETE_V5_DimLinear::CreateFromV6DimLinear(*V6_dim_linear, annotation_context, nullptr);
const ON_DimAngular* V6_dim_angle = ON_DimAngular::Cast(&V6_annotation);
if (nullptr != V6_dim_angle)
return ON_OBSOLETE_V5_DimAngular::CreateFromV6DimAngular(*V6_dim_angle, annotation_context, nullptr);
const ON_DimOrdinate* V6_dim_ordinate = ON_DimOrdinate::Cast(&V6_annotation);
if (nullptr != V6_dim_ordinate)
return ON_OBSOLETE_V5_DimOrdinate::CreateFromV6DimOrdinate(*V6_dim_ordinate, annotation_context, nullptr);
return nullptr;
}
bool ON_OBSOLETE_V5_Annotation::EvaluatePoint( const ON_ObjRef& objref, ON_3dPoint& P) const
{
bool rc = false;
switch( objref.m_component_index.m_type )
{
case ON_COMPONENT_INDEX::dim_linear_point:
case ON_COMPONENT_INDEX::dim_radial_point:
case ON_COMPONENT_INDEX::dim_angular_point:
case ON_COMPONENT_INDEX::dim_ordinate_point:
case ON_COMPONENT_INDEX::dim_text_point:
{
ON_2dPoint uv = Point(objref.m_component_index.m_index);
if ( uv.IsValid() )
{
P = m_plane.PointAt(uv.x,uv.y);
rc = true;
}
}
break;
default:
// other enum values skipped on purpose
break;
}
if (!rc)
{
P = ON_3dPoint::UnsetPoint;
}
return rc;
}
bool ON_OBSOLETE_V5_Annotation::IsValid( ON_TextLog* text_log ) const
{
if ( !m_plane.IsValid() )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_Annotation - m_plane is not valid\n");
}
return false;
}
const int points_count = m_points.Count();
int i;
for ( i = 0; i < points_count; i++ )
{
if ( !m_points[i].IsValid() )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_Annotation - m_points[%d] is not valid.\n");
}
return false;
}
}
switch ( m_type )
{
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAligned:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAngular:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtTextBlock:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimOrdinate:
break;
default:
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_Annotation - m_type = %d is not a valid enum value\n",m_type);
}
return false;
break;
}
return true;
}
static bool WriteAnnotation2UserText_V4( ON_BinaryArchive& file, const ON_wString& s )
{
bool rc;
ON_wString s4;
int len = s.Length();
for(int i = 0; i < len; i++)
{
if(s[i] == '\r' || s[i] == '\n')
{
s4 += L'\r';
s4 += L'\n';
// May 24, 2012 Tim - Fix for RR 100260. If we use a while here we
// miss adding carriage returns where the user really meant to have a
// blank line. If we only check the next character and then continue on
// we preserve the blank lines.
if(i < len-1 && (s[i+1] == L'\r' || s[i+1] == L'\n'))
i++;
continue;
}
s4 += s[i];
}
rc = file.WriteString(s4);
return rc;
}
static bool WriteAnnotation2UserText_V5( ON_BinaryArchive& file, const ON_wString& s )
{
bool rc;
rc = file.WriteString( s);
return rc;
}
bool ON_OBSOLETE_V5_Annotation::Write( ON_BinaryArchive& file ) const
{
//int i;
unsigned int ui;
bool rc = false;
bool bInChunk = (file.Archive3dmVersion() >= 5 );
if ( bInChunk )
{
// 18 October 2007 Dale Lear
// I modified this code so that V5 files can add
// information in ON_OBSOLETE_V5_Annotation chunks without
// breaking past and future file IO.
// The opennurbs version number before this change was
// 20071017*. I changed the version to 20071018* when
// I checked in this IO change. The reason I can get
// away with this is that nobody except developers has
// a copy of V5 Rhino.
// 28 Aug, 2010 - Lowell - changed minor version 0->1 to write
// annotative scale flag
// 24 September 2010 Dale Lear
// I incremented chunk version to 1.2 and wrote the TextFormula() string.
rc = file.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,3);
if (!rc)
return false;
}
else
{
// For archives with opennurbs version < 200710180
// The code before version 200710180 does not properly
// handle new additions to the ON_OBSOLETE_V5_Annotation chunk.
rc = file.Write3dmChunkVersion( 1, 0 );
}
while(rc)
{
ui = static_cast<unsigned char>(m_type);
rc = file.WriteInt(ui);
if ( !rc) break;
ui = (unsigned int)m_textdisplaymode;
rc = file.WriteInt(ui);
if ( !rc) break;
// June 17, 2010 - Lowell - Added adjustment to position text
// a little better in pre-v5 files.
// There's no adjustment for right/left justify because we don't
// know the width of the text here
// This doesn't change the size or position of any fields being
// written, but just adjusts the plane to tune up the alignment
// 16 Nov, 2011 - Lowell - Change text to bottom left justified for pre-v5 files rr94270
// This stuff is moved to CRhinoDoc::Write3DMHelper() so it will help with other file
// formats too
//ON_Plane plane = m_plane;
//if(file.Archive3dmVersion() <= 4 && m_type == ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtTextBlock)
//{
// double height = m_textheight;
// int lines = CountTextLines(m_usertext);
// double linefeed = ON_Font::m_default_linefeed_ratio;
// if(m_justification & tjBottom)
// {
// if(lines > 1)
// {
// ON_3dPoint p = plane.PointAt(0.0, -height * (lines-1) * linefeed);
// plane.SetOrigin(p);
// }
// }
// else if(m_justification & tjMiddle)
// {
// double h = height * (lines-1) * linefeed + height;
// ON_3dPoint p = plane.PointAt(0.0, h * 0.5);
// plane.SetOrigin(p);
// }
// else if(m_justification & tjTop)
// {
// ON_3dPoint p = plane.PointAt(0.0, -height);
// plane.SetOrigin(p);
// }
//}
rc = file.WritePlane(m_plane);
if ( !rc) break;
ON_2dPointArray points = m_points;
int bUserPositionedText = m_userpositionedtext?1:0;
switch( m_type )
{
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAligned:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear:
if ( 4 == points.Count() )
{
// so old versions will read enough points.
points.AppendNew();
points[4].Set(0.5*(points[0].x + points[2].x),points[1].y);
bUserPositionedText = false;
}
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAngular:
//user positioned text is supported.
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter:
// 9 August 2005 Dale Lear - radial dimensions do
// not support user positioned text. The never have
// in Rhino, but the old files had 5 points in them.
if ( 4 == points.Count() )
{
// so old versions will read enough points.
points.AppendNew();
}
if ( points.Count() >= 5 )
{
points[4] = points[2];
}
bUserPositionedText = false;
break;
default:
bUserPositionedText = false;
break;
}
rc = file.WriteArray( points);
if ( !rc) break;
// June 17, 2010 - Lowell - Added support for writing word-wrapped text
// to pre-v5 files with hard returns in place of wrapping markers
rc = ( file.Archive3dmVersion() <= 4 )
? WriteAnnotation2UserText_V4(file,m_usertext)
: WriteAnnotation2UserText_V5(file,m_usertext);
if ( !rc) break;
// 7-9-03 lw removed extra text string getting written
rc = file.WriteInt( bUserPositionedText );
if ( !rc) break;
const bool bIsText = IsText();
//rc = file.Write3dmReferencedComponentIndex(
// bIsText ? ON_ModelComponent::Type::TextStyle : ON_ModelComponent::Type::DimStyle, m_dimstyle_index );
rc = file.WriteInt(m_v5_3dm_archive_dimstyle_index);
if ( !rc) break;
rc = file.WriteDouble( m_textheight);
if ( !rc) break;
if ( !bInChunk )
break;
// NOTE WELL - NEVER change the code in this function
// above this comment. If you do, you will
// break reading and writing V4 files.
// Ask Dale Lear if you have any questions.
// 18 October 2007 - Dale Lear added m_justification IO
rc = file.WriteInt(m_justification);
if ( !rc)
break;
// 28 Aug 2010 - Lowell - Added flag for whether text gets scaled in modelspace
rc = file.WriteBool(m_annotative_scale);
if(!rc)
break;
// 24 September 2010 Dale Lear
// I incremented chunk version to 1.2
ON_wString text_formula = TextFormula();
rc = file.WriteString(text_formula);
if(!rc)
break;
// To write more ON_OBSOLETE_V5_Annotation fields, increment the minor version
// number and write the new information here.
// September 2015 Dale Lear
// I incremented chunk version to 1.3
// and separated text style and dim style
//rc = file.Write3dmReferencedComponentIndex( ON_ModelComponent::Type::TextStyle, bIsText ? m_dimstyle_index : -1 );
//if ( !rc) break;
//rc = file.Write3dmReferencedComponentIndex( ON_ModelComponent::Type::DimStyle, bIsText ? -1 : m_dimstyle_index );
//if ( !rc) break;
rc = file.WriteInt( bIsText ? m_v5_3dm_archive_dimstyle_index : -1 );
if ( !rc) break;
rc = file.WriteInt( bIsText ? -1 : m_v5_3dm_archive_dimstyle_index );
if ( !rc) break;
// Finished writing ON_OBSOLETE_V5_Annotation information
break;
}
if ( bInChunk )
{
if ( !file.EndWrite3dmChunk() )
rc = false;
}
return rc;
}
bool ON_OBSOLETE_V5_Annotation::Read( ON_BinaryArchive& file )
{
// NOTE WELL - If you make any changes to this code,
// you break file IO for some annotation
// objects. Please discuss all changes
// with Dale Lear BEFORE you check in any
// changes.
Destroy();
// If annotation is read from old files that do not contain
// the m_annotative_scale setting, then m_annotative_scale
// must be false so the text behaves the way it did in old
// files. The "Destroy()" function above can set m_annotative_scale
// any way that makes sense for new objects.
m_annotative_scale = false;
int major_version = 0;
int minor_version = 0;
bool rc = false;
bool bInChunk = (file.Archive3dmVersion() >= 5 && file.ArchiveOpenNURBSVersion() >= 200710180);
if ( bInChunk )
{
rc = file.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
if ( !rc )
return false;
}
else
{
rc = file.Read3dmChunkVersion(&major_version,&minor_version);
}
bool bIsText = false;
int dim_style_index = ON_UNSET_INT_INDEX;
int dim_style_index0 = ON_UNSET_INT_INDEX;
int dim_style_index1 = ON_UNSET_INT_INDEX;
int dim_style_index2 = ON_UNSET_INT_INDEX;
while(rc)
{
if ( 1 != major_version )
{
rc = false;
break;
}
unsigned int ui;
rc = file.ReadInt(&ui);
if (!rc) break;
m_type = ON_INTERNAL_OBSOLETE::V5AnnotationTypeFromUnsigned(ui);
rc = file.ReadInt(&ui);
if (!rc) break;
m_textdisplaymode = ON_INTERNAL_OBSOLETE::V5_TextDisplayMode(ui);
rc = file.ReadPlane( m_plane);
if (!rc) break;
rc = file.ReadArray( m_points);
if (!rc) break;
rc = file.ReadString( m_usertext);
if (!rc) break;
ui = 0;
rc = file.ReadInt( &ui );
if (!rc) break;
m_userpositionedtext = ui ? true : false;
// Initially, a single integer was used. It was either a text style index or a dim style index.
// In August 2016, text styles were removed and font information is saved on ON_DimStyle.
// When Read3dmReferencedComponentIndex() is called with the first parameter = ON_ModelComponent::Type::TextStyle,
// it returns the value to use as a dimstyle index.
bIsText = IsText();
rc = file.Read3dmReferencedComponentIndex(
bIsText ? ON_ModelComponent::Type::TextStyle : ON_ModelComponent::Type::DimStyle,
&dim_style_index0
);
if (!rc) break;
dim_style_index = dim_style_index0;
rc = file.ReadDouble( &m_textheight);
if (!rc) break;
switch( m_type )
{
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAligned:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear:
if ( m_points.Count() < 5 )
{
m_userpositionedtext = false;
}
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAngular:
if ( m_points.Count() <= 0 )
{
m_userpositionedtext = false;
}
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter:
// 9 August 2005 Dale Lear - radial dimensions do
// not support user positioned text. The never have
// in Rhino, but the old files had 5 points in them.
if ( 5 == m_points.Count() )
{
m_points.SetCount(4);
}
m_userpositionedtext = false;
break;
default:
m_userpositionedtext = false;
break;
}
if ( !bInChunk )
break;
// 18 October 2007 - Dale Lear added m_justification IO
rc = file.ReadInt( &m_justification );
if (!rc) break;
if ( minor_version <= 0 )
break;
if(minor_version >= 1)
{
// 28 Aug, 2010 - Lowell - added reading annotative scale flag
rc = file.ReadBool(&m_annotative_scale);
if (!rc) break;
if ( minor_version >= 2 )
{
// 24 September 2010 Dale Lear
// I incremented chunk version to 1.2
ON_wString text_formula;
rc = file.ReadString(text_formula);
if(!rc) break;
SetTextFormula(static_cast< const wchar_t* >(text_formula));
if (minor_version >= 3)
{
// September 2015 Dale Lear
// I incremented chunk version to 1.3
// and separated text style and dim style
// In August 2016, text styles were removed and font information is saved on ON_DimStyle.
// When Read3dmReferencedComponentIndex() is called with the first parameter = ON_ModelComponent::Type::TextStyle,
// it returns the value to use as a dimstyle index.
rc = file.Read3dmReferencedComponentIndex(ON_ModelComponent::Type::TextStyle, &dim_style_index1);
if (!rc) break;
rc = file.Read3dmReferencedComponentIndex(ON_ModelComponent::Type::DimStyle, &dim_style_index2);
if (!rc) break;
dim_style_index = ON_UNSET_INT_INDEX;
}
}
}
// Read new additions to ON_OBSOLETE_V5_Annotation here
break;
}
if ( bInChunk )
{
if (!file.EndRead3dmChunk() )
rc = false;
}
//if (!bInChunk)
{
// If justification is 0, change it to top-left
// and move the text point up by text height
if (bIsText && 0 == m_justification)
{
m_justification = eTextJustification::tjTopLeft;
m_plane.origin = m_plane.PointAt(0.0, m_textheight);
}
}
if (ON_UNSET_INT_INDEX == dim_style_index)
{
if (bIsText)
{
if (dim_style_index0 > ON_UNSET_INT_INDEX && dim_style_index0 == dim_style_index1)
dim_style_index = dim_style_index1;
else
{
ON_ERROR("Unexpected text object dim style index.");
if (dim_style_index1 >= 0)
dim_style_index = dim_style_index1;
else if (dim_style_index0 >= 0)
dim_style_index = dim_style_index0;
else if (dim_style_index2 >= 0)
dim_style_index = dim_style_index2;
}
}
else
{
// not text
if (dim_style_index0 > ON_UNSET_INT_INDEX && dim_style_index0 == dim_style_index2)
dim_style_index = dim_style_index2;
else
{
ON_ERROR("Unexpected dimension object dim style index.");
if (dim_style_index2 >= 0)
dim_style_index = dim_style_index2;
else if (dim_style_index0 >= 0)
dim_style_index = dim_style_index0;
else if (dim_style_index1 >= 0)
dim_style_index = dim_style_index1;
}
}
}
if (ON_UNSET_INT_INDEX != dim_style_index)
this->SetV5_3dmArchiveDimStyleIndex( dim_style_index );
// July 29, 2020 - Lowell
// If somebody has managed to make a V5 file that has text with single "\n" chars to delineate lines,
// and marks the text as "wrapped" it displays as text with various length lines.
// V5 itself uses '\r\n' to mark hard returns and '\n' to mark lines made by paragraph wrapping
// V6 and later ignore '\n' and convert '\r\n' to newlines and wraps the text to the specified
// wrapping width at runtime.
// The only example of this kind of text formatting I've seen here is from a file referenced by
// https://mcneel.myjetbrains.com/youtrack/issue/RH-59675
// Uncommenting the following clause will convert all of the '\n' in V5 wrapped text to '\r\n'
// causing V6 to make line breaks at those places.
// The text will no longer be "wrapped", but will have hard returns at the end of each line
// where it was wrapped in V5.
////////////////////////////////////
//if (bInChunk && bIsText)
//{
// const wchar_t* s0 = L"\n";
// const wchar_t* s1 = L"\r\n";
// const wchar_t* s2 = L"6C632E28-CF14-49D0-ADEE-DF6ACCAC74F1";
// if (m_usertext.Find(s0) > -1)
// {
// ON_wString usertext(m_usertext);
// usertext.Replace(s1, s2);
// usertext.Replace(s0, s1);
// usertext.Replace(s2, s1);
// m_usertext = usertext;
// }
//}
////////////////////////////////////
return rc;
}
ON::object_type ON_OBSOLETE_V5_Annotation::ObjectType() const
{
return ON::annotation_object;
}
int ON_OBSOLETE_V5_Annotation::Dimension() const
{
return 3;
}
bool ON_OBSOLETE_V5_Annotation::Transform( const ON_Xform& xform )
{
ON_Geometry::Transform(xform);
const double tol = 1.0e-4;
ON_3dVector vx = Plane().xaxis;
ON_3dVector vy = Plane().yaxis;
vx.Transform(xform);
vy.Transform(xform);
double sx = vx.Length();
double sy = vy.Length();
if ((fabs(sx - 1.0) > tol && fabs(sx) > tol) ||
(fabs(sy - 1.0) > tol && fabs(sy) > tol))
{
ON_Xform xfscale(ON_Xform::DiagonalTransformation(sx, sy, 1.0));
ON_2dPoint p;
for (int i = 0; i < m_points.Count(); i++)
{
p = Point(i);
p.Transform(xfscale);
SetPoint(i, p);
}
}
// This scales the text height on text but not on dimensions
if (ON_OBSOLETE_V5_Annotation::IsText())
{
SetHeight(sy * Height());
}
return m_plane.Transform(xform);
}
int ON_Plane_Repair(ON_Plane& plane)
{
int rc;
if ( plane.IsValid() )
{
rc = 1;
}
else
{
rc = 2;
if (!plane.origin.IsValid())
{
plane.origin.Set(0.0,0.0,0.0);
}
bool bGoodX = (plane.xaxis.IsValid() && !plane.xaxis.IsZero() );
bool bGoodY = (plane.yaxis.IsValid() && !plane.yaxis.IsZero() );
bool bGoodZ = (plane.zaxis.IsValid() && !plane.zaxis.IsZero() );
if ( bGoodX )
{
if ( fabs(plane.xaxis.Length()-1.0) > ON_SQRT_EPSILON )
plane.xaxis.Unitize();
}
if ( bGoodY )
{
if ( fabs(plane.yaxis.Length()-1.0) > ON_SQRT_EPSILON )
plane.yaxis.Unitize();
}
if ( bGoodZ )
{
if ( fabs(plane.zaxis.Length()-1.0) > ON_SQRT_EPSILON )
plane.zaxis.Unitize();
}
if ( bGoodZ )
{
double x = bGoodX ? fabs(plane.zaxis*plane.xaxis) : 99.0;
double y = bGoodX ? fabs(plane.zaxis*plane.yaxis) : 99.0;
if ( x <= ON_SQRT_EPSILON )
{
if ( y > ON_SQRT_EPSILON )
{
plane.yaxis = ON_CrossProduct(plane.zaxis,plane.xaxis);
plane.yaxis.Unitize();
}
}
else if ( y <= ON_SQRT_EPSILON )
{
plane.xaxis = ON_CrossProduct(plane.yaxis,plane.zaxis);
plane.xaxis.Unitize();
}
else if ( x <= y && x < 1.0 )
{
plane.yaxis = ON_CrossProduct(plane.zaxis,plane.xaxis);
if( plane.yaxis.Unitize() )
{
plane.xaxis = ON_CrossProduct(plane.yaxis,plane.zaxis);
plane.xaxis.Unitize();
}
else if ( y < 1.0 )
{
plane.CreateFromNormal( plane.origin, plane.zaxis );
}
}
else if ( y < 1.0 )
{
plane.xaxis = ON_CrossProduct(plane.yaxis,plane.zaxis);
if( plane.xaxis.Unitize() )
{
plane.yaxis = ON_CrossProduct(plane.zaxis,plane.xaxis);
plane.yaxis.Unitize();
}
else
{
plane.CreateFromNormal( plane.origin, plane.zaxis );
}
}
}
else if ( bGoodX )
{
if ( bGoodY )
{
plane.zaxis = ON_CrossProduct(plane.xaxis,plane.yaxis);
if ( plane.zaxis.Unitize() )
{
if ( fabs(plane.yaxis*plane.xaxis) > ON_SQRT_EPSILON )
{
plane.yaxis = ON_CrossProduct(plane.zaxis,plane.xaxis);
plane.yaxis.Unitize();
}
}
else
{
plane.yaxis.PerpendicularTo(plane.xaxis);
plane.yaxis.Unitize();
plane.zaxis = ON_CrossProduct(plane.xaxis,plane.yaxis);
plane.zaxis.Unitize();
}
}
else
{
plane.yaxis.PerpendicularTo(plane.xaxis);
plane.yaxis.Unitize();
plane.zaxis = ON_CrossProduct(plane.xaxis,plane.yaxis);
plane.zaxis.Unitize();
}
}
else if ( bGoodY )
{
plane.zaxis.PerpendicularTo(plane.yaxis);
plane.zaxis.Unitize();
plane.xaxis = ON_CrossProduct(plane.yaxis,plane.zaxis);
plane.xaxis.Unitize();
}
else
{
plane.xaxis.Set(1.0,0.0,0.0);
plane.yaxis.Set(0.0,1.0,0.0);
plane.zaxis.Set(0.0,0.0,1.0);
}
plane.UpdateEquation();
}
return rc;
}
// overrides virtual ON_Geometry::Transform()
bool ON_OBSOLETE_V5_DimRadial::Transform( const ON_Xform& xform )
{
// TODO fill in something that works for non-rigid transforms
return ON_OBSOLETE_V5_Annotation::Transform(xform);
}
bool ON_OBSOLETE_V5_Leader::Transform( const ON_Xform& xform )
{
bool rc = xform.IsIdentity();
if ( !rc)
{
ON_Plane plane = m_plane;
rc = plane.Transform(xform);
if ( rc )
{
int i;
const int point_count = m_points.Count();
ON_2dPointArray q(point_count);
ON_2dPoint p2, q2;
ON_3dPoint P, Q;
bool bUpdatePoints = false;
for ( i = 0; i < point_count && rc; i++ )
{
p2 = m_points[i];
P = m_plane.PointAt( p2.x, p2.y );
Q = xform*P;
if( !plane.ClosestPointTo(Q,&q2.x,&q2.y) )
rc = false;
if ( fabs(p2.x - q2.x) <= ON_SQRT_EPSILON )
q2.x = p2.x;
else
bUpdatePoints = true;
if ( fabs(p2.y - q2.y) <= ON_SQRT_EPSILON )
q2.y = p2.y;
else
bUpdatePoints = true;
q.Append(q2);
}
if(rc)
{
ON_Geometry::Transform(xform);
m_plane = plane;
if ( bUpdatePoints )
m_points = q;
if ( m_points[0].x != 0.0 || m_points[0].y != 0.0 )
{
ON_2dVector v = m_points[0];
if ( !v.IsZero() )
{
m_plane.origin = m_plane.PointAt(v.x,v.y);
m_plane.UpdateEquation();
v = -v;
for ( i = 1; i < point_count; i++ )
{
m_points[i] += v;
}
m_points[0].Set(0.0,0.0);
}
}
}
}
}
return rc;
}
bool ON_OBSOLETE_V5_DimAngular::Transform( const ON_Xform& xform )
{
// Dale Lear - this override fixes RR 11114 by correctly
// handling non uniform scaling.
bool rc = xform.IsIdentity();
if ( !rc)
{
ON_Plane plane = m_plane;
if ( dim_pt_count == m_points.Count() && plane.Transform( xform ) )
{
rc = true;
ON_3dPoint P[dim_pt_count], Q[dim_pt_count], A[3], B[3];
ON_2dVector p2[dim_pt_count], q2[dim_pt_count], a[3], b[3];
double r[3];
int i;
bool bUpdatePoints = false;
double a0 = 0.0;
double a1 = m_angle;
a[0].Set( m_radius*cos(a0), m_radius*sin(a0) );
a[1].Set( m_radius*cos(0.5*(a0+a1)), m_radius*sin(0.5*(a0+a1)) );
a[2].Set( m_radius*cos(a1), m_radius*sin(a1) );
for ( i = 0; i < dim_pt_count && rc; i++ )
{
p2[i] = m_points[i];
P[i] = m_plane.PointAt( p2[i].x, p2[i].y );
Q[i] = xform*P[i];
if( !plane.ClosestPointTo(Q[i],&q2[i].x,&q2[i].y) )
rc = false;
if ( fabs(p2[i].x - q2[i].x) > ON_SQRT_EPSILON
|| fabs(p2[i].y - q2[i].y) > ON_SQRT_EPSILON )
{
// transformation is not a rigid motion
bUpdatePoints = true;
}
}
for ( i = 0; i < 3 && rc; i++ )
{
A[i] = m_plane.PointAt( a[i].x, a[i].y );
B[i] = xform*A[i];
if( !plane.ClosestPointTo(B[i],&b[i].x,&b[i].y) )
rc = false;
r[i] = B[i].DistanceTo(plane.origin);
if ( fabs(a[i].x - b[i].x) > ON_SQRT_EPSILON
|| fabs(a[i].y - b[i].y) > ON_SQRT_EPSILON )
{
// transformation is not a rigid motion
bUpdatePoints = true;
}
if ( r[i] < ON_SQRT_EPSILON )
rc = false;
else if ( r[i] > m_radius*(1.0+ON_SQRT_EPSILON) )
bUpdatePoints = true;
else if ( r[i] < m_radius*(1.0-ON_SQRT_EPSILON) )
bUpdatePoints = true;
}
if (rc)
{
if ( bUpdatePoints )
{
ON_3dVector X = B[0] - plane.origin;
X.Unitize();
ON_3dVector Y1 = B[1] - plane.origin;
Y1.Unitize();
ON_3dVector Z1 = ON_CrossProduct(X,Y1);
double z1 = Z1.Length();
Z1.Unitize();
ON_3dVector Y2 = B[2] - plane.origin;
Y2.Unitize();
ON_3dVector Z2 = ON_CrossProduct(X,Y2);
double z2 = Z2.Length();
Z2.Unitize();
if ( z2 >= z1 && z2 >= 0.00001 ) // 4 April 2014 - Lowell - At 0.05, this was too big a tolerance
{ // when the dimension had previously been scaled by 0.001 etc. Rh-25926
plane.xaxis = X;
plane.zaxis = Z2;
if (Z1*Z2 < 0.0)
plane.zaxis = -plane.zaxis;
plane.yaxis = ON_CrossProduct(plane.zaxis,plane.xaxis);
plane.yaxis.Unitize();
}
else if ( z1 >= 0.00001 )
{
plane.xaxis = X;
plane.zaxis = Z1;
plane.yaxis = ON_CrossProduct(plane.zaxis,plane.xaxis);
plane.yaxis.Unitize();
}
else
{
rc = false;
}
if (rc)
{
plane.UpdateEquation();
ON_3dVector V = B[2] - plane.origin;
double x = V*plane.xaxis;
double y = V*plane.yaxis;
double angle = atan2(y,x);
if ( angle < 0.0 )
angle += 2.0*ON_PI;
double radius = (r[0]+r[1]+r[2])/3.0;
double arc_pt_angle = 1.0/3.0;
if ( m_angle > 0.0 && m_points[arc_pt_index].IsValid() )
{
arc_pt_angle = atan2(m_points[arc_pt_index].y,m_points[arc_pt_index].x);
if ( arc_pt_angle < 0.0 ) arc_pt_angle += 2.0*ON_PI;
if ( arc_pt_angle > m_angle )
arc_pt_angle = 1.0/3.0;
else
arc_pt_angle /= m_angle;
if ( arc_pt_angle < 0.0 )
arc_pt_angle = 0.0;
else if ( arc_pt_angle > 1.0 )
arc_pt_angle = 1.0;
}
arc_pt_angle *= angle;
ON_Geometry::Transform(xform);
m_plane = plane;
m_radius = radius;
m_angle = angle;
m_points[start_pt_index].Set(m_radius,0.0);
m_points[end_pt_index].Set(m_radius*cos(m_angle),m_radius*sin(m_angle));
m_points[arc_pt_index].Set(m_radius*cos(arc_pt_angle),m_radius*sin(arc_pt_angle));
if ( m_userpositionedtext )
{
m_plane.ClosestPointTo(Q[userpositionedtext_pt_index],
&m_points[userpositionedtext_pt_index].x,
&m_points[userpositionedtext_pt_index].y
);
}
else
{
m_points[userpositionedtext_pt_index].Set(m_radius*cos(0.5*m_angle),m_radius*sin(0.5*m_angle));
}
}
}
else
{
ON_Geometry::Transform(xform);
m_plane = plane;
}
}
}
}
return rc;
}
bool ON_OBSOLETE_V5_Annotation::IsText() const
{ return (ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtTextBlock == m_type); }
bool ON_OBSOLETE_V5_Annotation::IsLeader() const
{ return (ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader == m_type); }
bool ON_OBSOLETE_V5_Annotation::IsDimension() const
{ return (ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtTextBlock != m_type && ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader != m_type); }
double ON_OBSOLETE_V5_Annotation::NumericValue() const
{ return ON_UNSET_VALUE; }
void ON_OBSOLETE_V5_Annotation::SetHeight( double ht)
{ if( ht > ON_SQRT_EPSILON) m_textheight = ht; }
double ON_OBSOLETE_V5_Annotation::Height() const
{ return m_textheight; }
void ON_OBSOLETE_V5_Annotation::SetType( ON_INTERNAL_OBSOLETE::V5_eAnnotationType type )
{
m_type = type;
if(type == ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius)
SetTextValue(ON_OBSOLETE_V5_DimRadial::DefaultRadiusText());
else if(type == ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter)
SetTextValue(ON_OBSOLETE_V5_DimRadial::DefaultDiameterText());
else
SetTextValue(0);
SetTextFormula(0);
}
ON_INTERNAL_OBSOLETE::V5_eAnnotationType ON_OBSOLETE_V5_Annotation::Type() const
{ return m_type; }
void ON_OBSOLETE_V5_Annotation::SetPlane( const ON_Plane& plane )
{ m_plane = plane; }
const ON_Plane& ON_OBSOLETE_V5_Annotation::Plane() const
{ return m_plane; }
void ON_OBSOLETE_V5_Annotation::SetPointCount( int count)
{
if( m_points.Count() < count)
{
m_points.Reserve( count);
for( int i = m_points.Count(); i < count; i++)
m_points.Append( ON_2dPoint());
}
}
int ON_OBSOLETE_V5_Annotation::PointCount() const
{ return m_points.Count(); }
void ON_OBSOLETE_V5_Annotation::SetPoints( const ON_2dPointArray& points )
{ m_points = points; }
const ON_2dPointArray& ON_OBSOLETE_V5_Annotation::Points() const
{ return m_points; }
void ON_OBSOLETE_V5_Annotation::SetPoint( int idx, const ON_2dPoint& point )
{
if ( idx >= 0 )
{
if ( idx < m_points.Count() )
m_points[idx] = point;
else if ( idx == m_points.Count() )
m_points.Append(point);
}
}
ON_2dPoint ON_OBSOLETE_V5_Annotation::Point( int idx ) const
{
return ( idx >= 0 && idx < m_points.Count() )
? m_points[idx]
: ON_2dPoint( 0.0, 0.0 );
}
void ON_OBSOLETE_V5_Annotation::SetUserText( const wchar_t* text_value )
// ON_OBSOLETE_V5_Annotation::SetUserText is OBSOLETE - use ON_OBSOLETE_V5_Annotation::SetTextValue();
{
SetTextValue( text_value );
}
const ON_wString& ON_OBSOLETE_V5_Annotation::UserText() const
// ON_OBSOLETE_V5_Annotation::UserText() is OBSOLETE - use ON_OBSOLETE_V5_Annotation::TextValue();
{
return m_usertext;
}
void ON_OBSOLETE_V5_Annotation::SetUserPositionedText( int bMoved )
{ m_userpositionedtext = bMoved?true:false; }
bool ON_OBSOLETE_V5_Annotation::UserPositionedText() const
{ return m_userpositionedtext; }
// Converts 2d points in annotation to 3d WCS points
bool ON_OBSOLETE_V5_Annotation::GetECStoWCSXform( ON_Xform& xform ) const
{
ON_3dVector z = ON_CrossProduct( m_plane.xaxis, m_plane.yaxis );
return xform.ChangeBasis( m_plane.origin, m_plane.xaxis, m_plane.yaxis, z,
ON_3dPoint::Origin, ON_3dVector::XAxis, ON_3dVector::YAxis, ON_3dVector::ZAxis );
}
// Converts from WCS 3d points to 2d points in annotation
bool ON_OBSOLETE_V5_Annotation::GetWCStoECSXform( ON_Xform& xform ) const
{
ON_3dVector z = ON_CrossProduct( m_plane.xaxis, m_plane.yaxis );
return xform.ChangeBasis( ON_3dPoint::Origin, ON_3dVector::XAxis, ON_3dVector::YAxis, ON_3dVector::ZAxis,
m_plane.origin, m_plane.xaxis, m_plane.yaxis, z );
}
void ON_OBSOLETE_V5_Annotation::ReservePoints( int count)
{
m_points.SetCapacity( count);
m_points.SetCount( count);
}
const wchar_t* ON_OBSOLETE_V5_Annotation::DefaultText() { return L""; }
void ON_OBSOLETE_V5_Annotation::SetTextDisplayMode( ON_INTERNAL_OBSOLETE::V5_TextDisplayMode mode)
{
m_textdisplaymode = mode;
}
ON_INTERNAL_OBSOLETE::V5_TextDisplayMode ON_OBSOLETE_V5_Annotation::TextDisplayMode() const
{
return m_textdisplaymode;
}
void ON_OBSOLETE_V2_Annotation::Internal_InitializeFromV5Annotation(
const ON_OBSOLETE_V5_Annotation& V5_annotation,
const class ON_3dmAnnotationContext* annotation_context
)
{
SetType( V5_annotation.Type());
SetTextDisplayMode( V5_annotation.TextDisplayMode());
SetPlane( V5_annotation.Plane());
SetPoints( V5_annotation.Points());
SetUserText( V5_annotation.TextValue());
SetDefaultText( V5_annotation.DefaultText());
SetUserPositionedText( V5_annotation.UserPositionedText());
}
void ON_OBSOLETE_V5_Annotation::SetJustification( unsigned int justification)
{
if(this->IsLeader())
m_justification = justification;
}
unsigned int ON_OBSOLETE_V5_Annotation::Justification() const
{
if(this->IsLeader())
return m_justification;
else
return 0;
}
//----- ON_OBSOLETE_V5_DimLinear ------------------------------------------
ON_OBSOLETE_V5_DimLinear::ON_OBSOLETE_V5_DimLinear()
{
//ON_OBSOLETE_V5_DimExtra* pDE = new ON_OBSOLETE_V5_DimExtra;
//if( pDE)
//{
// if( !AttachUserData( pDE))
// delete pDE;
// else
// pDE->SetDefaults();
//}
m_type = ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear;
m_textdisplaymode = ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kAboveLine;
m_plane = ON_xy_plane;
SetTextValue(DefaultText());
SetTextFormula(0);
m_points.Reserve(ON_OBSOLETE_V5_DimLinear::dim_pt_count);
m_points.SetCount(ON_OBSOLETE_V5_DimLinear::dim_pt_count);
m_points.Zero();
}
ON_OBSOLETE_V5_DimLinear::~ON_OBSOLETE_V5_DimLinear()
{
}
bool ON_OBSOLETE_V5_DimLinear::IsValid( ON_TextLog* text_log ) const
{
if ( m_type != ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear && m_type != ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAligned )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimLinear - m_type != ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear or ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAligned.\n");
}
return false;
}
if ( !ON_OBSOLETE_V5_Annotation::IsValid( text_log ))
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimLinear - invalid ON_OBSOLETE_V5_Annotation base class.\n");
}
return false;
}
if ( m_points.Count() != 5 )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimLinear - m_points.Count() = %d (should be 5).\n",m_points.Count());
}
return false;
}
if ( m_points[1].x != m_points[0].x )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimLinear - m_points[1].x = %g != %g = m_points[0].x (should be equal)\n",
m_points[1].x, m_points[0].x
);
}
return false;
}
if ( m_points[3].x != m_points[2].x )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimLinear - m_points[3].x = %g != %g = m_points[2].x\n",
m_points[3].x, m_points[2].x
);
}
return false;
}
if ( m_points[3].y != m_points[1].y )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimLinear - m_points[3].y = %g != %g = m_points[1].y\n",
m_points[3].y, m_points[1].y
);
}
return false;
}
return true;
}
bool ON_OBSOLETE_V5_DimLinear::Write(ON_BinaryArchive& archive) const
{
// 18 October 2007 Dale Lear
// I added the chunk wrapping so V5 and future versions can
// add IO support for information specific to ON_OBSOLETE_V5_DimLinear
// V4 did not have a ON_OBSOLETE_V5_DimLinear::Write and simply called
// ON_OBSOLETE_V5_Annotation::Write.
bool rc = false;
bool bInChunk = (archive.Archive3dmVersion() >= 5);
if ( bInChunk )
{
rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
if ( !rc )
return false;
}
else
{
rc = true;
}
while(rc)
{
rc = ON_OBSOLETE_V5_Annotation::Write(archive)?true:false;
if (!rc) break;
if ( !bInChunk )
break;
// To write new fields, increment minor version number
// and write values here. Ask Dale Lear for help.
break;
}
if ( bInChunk )
{
if (!archive.EndWrite3dmChunk())
rc = false;
}
return rc;
}
bool ON_OBSOLETE_V5_DimLinear::Read(ON_BinaryArchive& archive)
{
// 18 October 2007 Dale Lear
// I added the chunk wrapping so V5 and future versions can
// add IO support for information specific to ON_OBSOLETE_V5_DimLinear
int major_version = 0;
int minor_version = 0;
bool rc = false;
bool bInChunk = (archive.Archive3dmVersion() >= 5 && archive.ArchiveOpenNURBSVersion() >= 200710180);
if ( bInChunk )
{
rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
if ( !rc )
return false;
}
else
{
rc = true;
}
while(rc)
{
rc = ON_OBSOLETE_V5_Annotation::Read(archive)?true:false;
if (!rc) break;
if ( !bInChunk || minor_version <= 0 )
break;
// read future addition here
break;
}
if ( bInChunk )
{
if ( !archive.EndRead3dmChunk() )
rc = false;
}
return rc;
}
bool ON_OBSOLETE_V5_DimLinear::GetBBox(
double* boxmin,
double* boxmax,
bool bGrowBox
) const
{
ON_BoundingBox bbox;
if ( bGrowBox )
{
bbox.m_min.x = boxmin[0];
bbox.m_min.y = boxmin[1];
bbox.m_min.z = boxmin[2];
bbox.m_max.x = boxmax[0];
bbox.m_max.y = boxmax[1];
bbox.m_max.z = boxmax[2];
if ( !bbox.IsValid() )
{
bbox.Destroy();
bGrowBox = false;
}
}
if ( 5 == m_points.Count() )
{
ON_3dPointArray P(5);
ON_2dPoint uv;
if ( m_userpositionedtext )
{
uv = m_points[0]; // point someplace in text
P.Append( m_plane.PointAt(uv.x,uv.y) );
}
P.Append( m_plane.origin );
uv.x = 0.0;
uv.y = m_points[1].y;
P.Append( m_plane.PointAt(uv.x,uv.y) );
uv = m_points[2];
P.Append( m_plane.PointAt(uv.x,uv.y) );
uv.y = m_points[1].y;
P.Append( m_plane.PointAt(uv.x,uv.y) );
bGrowBox = P.GetBBox(&bbox.m_min.x, &bbox.m_max.x, bGrowBox);
}
if ( bGrowBox )
{
boxmin[0] = bbox.m_min.x;
boxmin[1] = bbox.m_min.y;
boxmin[2] = bbox.m_min.z;
boxmax[0] = bbox.m_max.x;
boxmax[1] = bbox.m_max.y;
boxmax[2] = bbox.m_max.z;
}
return bGrowBox;
}
bool ON_OBSOLETE_V5_DimLinear::GetTightBoundingBox(
ON_BoundingBox& tight_bbox,
bool bGrowBox,
const ON_Xform* xform
) const
{
if ( 5 == m_points.Count() )
{
ON_3dPointArray P(5);
// 18 Oct 2012 - Lowell - Fixed this to add all of the points to the bbox rr116270
for(int i = 0; i < 5; i++)
P.Append( m_plane.PointAt(m_points[i].x,m_points[i].y) );
if ( P.GetTightBoundingBox( tight_bbox, bGrowBox, xform ) )
bGrowBox = true;
}
else if ( bGrowBox && !tight_bbox.IsValid() )
{
tight_bbox.Destroy();
bGrowBox = false;
}
return (0!=bGrowBox);
}
int ON_OBSOLETE_V5_DimLinear::Repair()
{
// returns 0 = unable to repair
// 1 = in perfect condition
// 2 == repaired.
const int ext0_pt_index = ON_OBSOLETE_V5_DimLinear::ext0_pt_index;
const int arrow0_pt_index = ON_OBSOLETE_V5_DimLinear::arrow0_pt_index;
const int ext1_pt_index = ON_OBSOLETE_V5_DimLinear::ext1_pt_index;
const int arrow1_pt_index = ON_OBSOLETE_V5_DimLinear::arrow1_pt_index;
const int userpositionedtext_pt_index = ON_OBSOLETE_V5_DimLinear::userpositionedtext_pt_index;
const int dim_pt_count = ON_OBSOLETE_V5_DimLinear::dim_pt_count;
int rc = 0;
if ( m_points.Count() >= dim_pt_count
&& m_points[ext0_pt_index].IsValid()
&& m_points[ext1_pt_index].IsValid() )
{
rc = 1;
if ( !m_plane.IsValid() )
{
rc = ON_Plane_Repair(m_plane);
}
if ( m_points.Count() > dim_pt_count )
{
rc = 2;
m_points.SetCount(dim_pt_count);
}
// m_points[ext0_pt_index] must be at (0,0)
ON_2dVector v = m_points[ext0_pt_index];
double d;
int i;
if ( !v.IsZero() )
{
rc = 2;
m_plane.origin = m_plane.PointAt(v.x,v.y);
m_plane.UpdateEquation();
v = -v;
for ( i = 0; i < dim_pt_count; i++ )
{
m_points[i] += v;
}
m_points[ext0_pt_index].Set(0.0,0.0);
}
if ( ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAligned == m_type && (m_points[ext1_pt_index].x < 0.0 || m_points[ext1_pt_index].y != 0.0) )
{
rc = 2;
// Aligned dims must have m_points[ext1_pt_index].x = m_points[ext0_pt_index].x
if ( m_points[ext1_pt_index].x > 100.0*ON_SQRT_EPSILON
&& fabs(m_points[ext1_pt_index].y) <= ON_SQRT_EPSILON )
{
m_points[ext1_pt_index].y = 0.0;
}
else
{
// Dimension line parallel to point0 -> point2
// rotate the plane so p2 is on the x axis
v = m_points[ext1_pt_index];
d = v.Length();
v.Unitize();
m_plane.Rotate(v.y,v.x,m_plane.zaxis,m_plane.origin);
// rotate points in opposite direction
v.y = -v.y;
for ( i = 0; i < dim_pt_count; i++ )
{
ON_2dPoint p = m_points[i];
m_points[i].Set( v.x*p.x - v.y*p.y, v.y*p.x + v.x*p.y );
}
m_points[ext0_pt_index].Set(0.0,0.0);
m_points[ext1_pt_index].Set(d,0.0);
}
}
else if ( ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear != m_type )
{
rc = 2;
m_type = ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear;
}
if ( m_points[arrow0_pt_index].x != m_points[ext0_pt_index].x )
{
rc = 2;
m_points[arrow0_pt_index].x = m_points[ext0_pt_index].x;
}
if ( m_points[arrow1_pt_index].x != m_points[ext1_pt_index].x )
{
rc = 2;
m_points[arrow1_pt_index].x = m_points[ext1_pt_index].x;
}
if ( !ON_IsValid(m_points[arrow0_pt_index].y) )
{
rc = 2;
if ( !ON_IsValid(m_points[arrow1_pt_index].y) )
m_points[arrow1_pt_index].y = 0.5*(m_points[ext0_pt_index].y + m_points[ext1_pt_index].y);
m_points[arrow0_pt_index].y = m_points[arrow1_pt_index].y;
}
else if ( !ON_IsValid(m_points[arrow1_pt_index].y) )
{
rc = 2;
m_points[arrow1_pt_index].y = m_points[arrow0_pt_index].y;
}
else if ( m_points[arrow0_pt_index].y != m_points[arrow1_pt_index].y )
{
rc = 2;
d = 0.5*(m_points[arrow0_pt_index].y + m_points[arrow1_pt_index].y);
m_points[arrow0_pt_index].y = d;
m_points[arrow1_pt_index].y = d;
}
if ( m_userpositionedtext )
{
if ( !m_points[userpositionedtext_pt_index].IsValid() )
{
rc = 2;
m_userpositionedtext = false;
}
}
if ( !m_userpositionedtext )
{
if ( m_points[userpositionedtext_pt_index].y != m_points[arrow0_pt_index].y
|| m_points[userpositionedtext_pt_index].x != 0.5*(m_points[arrow0_pt_index].x + m_points[arrow1_pt_index].x) )
{
rc = 2;
m_points[userpositionedtext_pt_index].y = m_points[arrow0_pt_index].y;
m_points[userpositionedtext_pt_index].x = 0.5*(m_points[arrow0_pt_index].x + m_points[arrow1_pt_index].x);
}
}
if ( !m_plane.IsValid() )
{
rc = 2;
ON_Plane_Repair(m_plane);
}
}
return rc;
}
bool ON_OBSOLETE_V5_DimLinear::Transform( const ON_Xform& xform )
{
// Dale Lear - this override fixes RR 11114 by correctly
// handling non uniform scaling.
bool rc = xform.IsIdentity();
if ( !rc)
{
ON_Plane plane = m_plane;
if ( dim_pt_count == m_points.Count() && plane.Transform( xform ) )
{
rc = true;
ON_3dPoint P[dim_pt_count], Q[dim_pt_count];
ON_2dVector p2[dim_pt_count], q2[dim_pt_count];
int i;
bool bUpdatePoints = false;
for ( i = 0; i < dim_pt_count && rc; i++ )
{
p2[i] = m_points[i];
P[i] = m_plane.PointAt( p2[i].x, p2[i].y );
Q[i] = xform*P[i];
if( !plane.ClosestPointTo(Q[i],&q2[i].x,&q2[i].y) )
rc = false;
if ( fabs(p2[i].x - q2[i].x) > ON_SQRT_EPSILON
|| fabs(p2[i].y - q2[i].y) > ON_SQRT_EPSILON )
{
// transformation is not in SL3
bUpdatePoints = true;
}
}
if (rc)
{
ON_Geometry::Transform(xform);
m_plane = plane;
if ( bUpdatePoints )
{
for ( i = 0; i < dim_pt_count && rc; i++ )
{
m_points[i] = q2[i];
}
// Repair() will properly align the arrow points, etc.
Repair();
}
}
}
}
return rc;
}
double ON_OBSOLETE_V5_DimLinear::NumericValue() const
{
// Use y coords of ext points instead of 3d distance
// to reduce noise in the answer.
return (m_points.Count() >= dim_pt_count)
? fabs(m_points[ext0_pt_index].x - m_points[ext1_pt_index].x)
: 0.0;
}
int ON_OBSOLETE_V5_DimLinear::StyleIndex() const
{
return ON_OBSOLETE_V5_Annotation::V5_3dmArchiveDimStyleIndex();
}
void ON_OBSOLETE_V5_DimLinear::SetStyleIndex( int i)
{
ON_OBSOLETE_V5_Annotation::SetV5_3dmArchiveDimStyleIndex( i);
}
/*
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
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
*/
ON_2dPoint ON_OBSOLETE_V5_DimLinear::Dim2dPoint( int point_index ) const
{
ON_2dPoint p2;
if ( m_points.Count() < dim_pt_count )
{
p2.x = p2.y = ON_UNSET_VALUE;
}
else
{
if ( text_pivot_pt == point_index )
{
point_index = m_userpositionedtext ? userpositionedtext_pt_index : dim_mid_pt;
}
const ON_2dPoint* points = m_points.Array();
switch(point_index)
{
case ext0_pt_index:
p2 = points[0];
break;
case arrow0_pt_index:
p2.x = points[0].x;
p2.y = points[1].y;
break;
case ext1_pt_index:
p2 = points[2];
break;
case arrow1_pt_index:
p2.x = points[2].x;
p2.y = points[1].y;
break;
case userpositionedtext_pt_index:
p2.x = points[4].x;
p2.y = points[4].y;
break;
case dim_mid_pt:
p2.x = 0.5*(points[0].x + points[2].x);
p2.y = points[1].y;
break;
default:
p2.x = p2.y = ON_UNSET_VALUE;
break;
}
}
return p2;
}
ON_3dPoint ON_OBSOLETE_V5_DimLinear::Dim3dPoint( int point_index ) const
{
ON_2dPoint p2 = Dim2dPoint(point_index);
return (ON_UNSET_VALUE == p2.x) ? ON_3dPoint::UnsetPoint : m_plane.PointAt(p2.x,p2.y);
}
ON_OBSOLETE_V2_TextObject* ON_OBSOLETE_V2_TextObject::CreateFromV5TextObject(
const class ON_OBSOLETE_V5_TextObject& V5_text_object,
const ON_3dmAnnotationContext* annotation_context,
ON_OBSOLETE_V2_TextObject* destination
)
{
if (nullptr == annotation_context)
annotation_context = &ON_3dmAnnotationContext::Default;
const ON_DimStyle& dim_style = annotation_context->DimStyle();
ON_OBSOLETE_V2_TextObject* V2_text_object
= (nullptr != destination)
? destination
: new ON_OBSOLETE_V2_TextObject();
V2_text_object->Internal_InitializeFromV5Annotation(V5_text_object,annotation_context);
V2_text_object->m_facename = dim_style.Font().WindowsLogfontName();
const double V5_text_height = V5_text_object.Height();
V2_text_object->m_fontweight = 400;
V2_text_object->m_height = V5_text_height;
if (V2_text_object->m_plane.IsValid())
{
// 8-20-03 lw convert from lower-left to upper-left reference point
V2_text_object->m_plane.origin += V2_text_object->m_plane.yaxis * 1.1 * V5_text_height;
V2_text_object->m_plane.UpdateEquation();
}
return V2_text_object;
}
ON_OBSOLETE_V2_DimAngular* ON_OBSOLETE_V2_DimAngular::CreateFromV5AngularDimension(
const class ON_OBSOLETE_V5_DimAngular& V5_angular_dimension,
const ON_3dmAnnotationContext* annotation_context,
ON_OBSOLETE_V2_DimAngular* destination
)
{
ON_OBSOLETE_V2_DimAngular* V2_angular_dimension
= (nullptr != destination)
? destination
: new ON_OBSOLETE_V2_DimAngular();
V2_angular_dimension->Internal_InitializeFromV5Annotation(V5_angular_dimension,annotation_context);
ON_SimpleArray<ON_2dPoint> V5_points(V5_angular_dimension.m_points);
V2_angular_dimension->m_points.SetCount(0);
V2_angular_dimension->SetPoint(0, ON_3dPoint(V5_angular_dimension.Point(1)));
V2_angular_dimension->SetPoint(1, ON_3dPoint(V5_angular_dimension.Point(2)));
V2_angular_dimension->SetPoint(2, ON_3dPoint(V5_angular_dimension.Point(3)));
V2_angular_dimension->SetPoint(3, ON_3dPoint(V5_angular_dimension.Point(0))); // text point or apex
V2_angular_dimension->SetAngle( V5_angular_dimension.Angle());
V2_angular_dimension->SetRadius( V5_angular_dimension.Radius());
return V2_angular_dimension;
}
ON_OBSOLETE_V2_DimRadial* ON_OBSOLETE_V2_DimRadial::CreateFromV5RadialDimension(
const class ON_OBSOLETE_V5_DimRadial& V5_linear_dimension,
const ON_3dmAnnotationContext* annotation_context,
ON_OBSOLETE_V2_DimRadial* destination
)
{
ON_OBSOLETE_V2_DimRadial* V2_radial_dimension
= (nullptr != destination)
? destination
: new ON_OBSOLETE_V2_DimRadial();
V2_radial_dimension->Internal_InitializeFromV5Annotation(V5_linear_dimension,annotation_context);
return V2_radial_dimension;
}
ON_OBSOLETE_V2_DimLinear* ON_OBSOLETE_V2_DimLinear::CreateFromV5LinearDimension(
const class ON_OBSOLETE_V5_DimLinear& V5_linear_dimension,
const ON_3dmAnnotationContext* annotation_context,
ON_OBSOLETE_V2_DimLinear* destination
)
{
ON_OBSOLETE_V2_DimLinear* V2_linear_dimension
= (nullptr != destination)
? destination
: new ON_OBSOLETE_V2_DimLinear();
V2_linear_dimension->Internal_InitializeFromV5Annotation(V5_linear_dimension,annotation_context);
return V2_linear_dimension;
}
ON_OBSOLETE_V5_DimLinear* ON_OBSOLETE_V5_DimLinear::CreateFromV2LinearDimension(
const class ON_OBSOLETE_V2_DimLinear& V2_linear_dimension,
const ON_3dmAnnotationContext* annotation_context,
ON_OBSOLETE_V5_DimLinear* destination
)
{
ON_OBSOLETE_V5_DimLinear* V5_linear_dimension
= (nullptr != destination)
? destination
: new ON_OBSOLETE_V5_DimLinear();
V5_linear_dimension->Internal_InitializeFromV2Annotation(V2_linear_dimension,annotation_context);
return V5_linear_dimension;
}
int ON_OBSOLETE_V5_DimLinear::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 x[6],
bool& bInside
) const
{
int rc = 0;
x[0] = 0.0;
x[1] = 0.0;
x[2] = 0.0;
x[3] = 0.0;
x[4] = 0.0;
x[5] = 0.0;
bInside = true;
if ( m_points.Count() < 3 )
return 0;
int i = (m_points[ext0_pt_index].x <= m_points[ext1_pt_index].x)
? ext0_pt_index
: ext1_pt_index;
const double x0 = m_points[i].x;
const double x1 = m_points[(ext0_pt_index==i) ? ext1_pt_index : ext0_pt_index].x;
x[0] = x0; // left end of first dimension line
x[1] = x1; // right end of first dimension line
x[2] = x0; // left end of second dimension line
x[3] = x1; // right end of second dimension line
x[4] = x0; // tip of first arrow
x[5] = x1; // tip of second arrow
if ( 0 == gdi_height_of_I )
{
// Default to height of Ariel 'I'
gdi_height_of_I = (165*ON_Font::Constants::AnnotationFontCellHeight)/256;
}
if ( 0.0 == dimscale )
{
dimscale = 1.0;
}
double t;
ON_INTERNAL_OBSOLETE::V5_TextDisplayMode textdisplay = ON_INTERNAL_OBSOLETE::V5TextDisplayModeFromV6DimStyle(dimstyle);
const double text_height_of_I = dimscale*dimstyle.TextHeight();
const double textgap = fabs(dimscale*dimstyle.TextGap());
const double gdi_to_plane_scale = text_height_of_I/gdi_height_of_I;
const double textwidth = fabs(gdi_to_plane_scale*(gdi_text_rect.right - gdi_text_rect.left));
const double arrowwidth = dimscale*dimstyle.ArrowSize();
const double tailwidth = 0.5*arrowwidth;
const double dimwidth = x1 - x0;
const double mindimwidth = (ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kInLine == textdisplay)
? (2.0*(arrowwidth + tailwidth + textgap) + textwidth)
: (2.0*arrowwidth + tailwidth);
const double dimextension = dimscale*dimstyle.DimExtension();
int ForceArrows = 0;
const ON_OBSOLETE_V5_DimExtra* pDE = ON_OBSOLETE_V5_DimExtra::DimensionExtension(this,false);
if( pDE)
ForceArrows = pDE->ArrowPosition();
// 19 Apr 2012 - Lowell - Fixed so forcing arrows inside won't cause the dim line to
// draw through InLine text rr103322
if(ForceArrows == -1 || // force outside
(dimwidth < mindimwidth && ForceArrows != 1)) // arrowheads have to be "outside" - they won't fit inside even without text
{
t = arrowwidth + tailwidth;
x[0] = x0;
x[1] = x0-t;
x[2] = x1+t;
x[3] = x1;
x[4] = x0; // arrow tips
x[5] = x1;
if( dimextension != 0.0)
{
x[0] += dimextension;
x[3] -= dimextension;
}
bInside = false;
rc = 2;
}
// Horizontal text or Userpositioned text
else if ((ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kHorizontalToScreen == textdisplay && vp) || m_userpositionedtext)
{
// use projected rectangle to clip dimension line
double xx0, xx1, xx, y0, y1;
ON_3dPoint P, R;
ON_2dPoint corners[4]; // corners of text rect in plane coords
ON_Line ray;
ON_3dVector vp_zaxis = (ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kHorizontalToScreen == textdisplay && vp)
? vp->CameraZ()
: m_plane.zaxis;
// 30 July 2012 - Lowell - Slightly shrink the text gap value
// so that text + gap won't intersect the dim line if when text
// is moved along the dim line. rr110504
double gdi_gap = fabs(textgap/gdi_to_plane_scale)-12;
if(gdi_gap < 0.0) gdi_gap = 0.0;
R.Set(gdi_text_rect.left-gdi_gap,gdi_text_rect.bottom+gdi_gap,0.0);
ray.from = gdi_to_world*R; ray.to = ray.from + vp_zaxis;
P = ( ON_Intersect(ray,m_plane,&t) ) ? ray.PointAt(t) : ray.from;
m_plane.ClosestPointTo(P,&corners[0].x,&corners[0].y);
R.Set(gdi_text_rect.right+gdi_gap,gdi_text_rect.bottom+gdi_gap,0.0);
ray.from = gdi_to_world*R; ray.to = ray.from + vp_zaxis;
P = ( ON_Intersect(ray,m_plane,&t) ) ? ray.PointAt(t) : ray.from;
m_plane.ClosestPointTo(P,&corners[1].x,&corners[1].y);
R.Set(gdi_text_rect.right+gdi_gap,gdi_text_rect.top-gdi_gap,0.0);
ray.from = gdi_to_world*R; ray.to = ray.from + vp_zaxis;
P = ( ON_Intersect(ray,m_plane,&t) ) ? ray.PointAt(t) : ray.from;
m_plane.ClosestPointTo(P,&corners[2].x,&corners[2].y);
R.Set(gdi_text_rect.left-gdi_gap,gdi_text_rect.top-gdi_gap,0.0);
ray.from = gdi_to_world*R; ray.to = ray.from + vp_zaxis;
P = ( ON_Intersect(ray,m_plane,&t) ) ? ray.PointAt(t) : ray.from;
m_plane.ClosestPointTo(P,&corners[3].x,&corners[3].y);
// Test if text rect intersects dimension line
xx0 = xx1 = ON_UNSET_VALUE;
for ( i = 0; i < 4; i++ )
{
y0 = corners[i].y - m_points[1].y; // vertical dist from corner to dimension line
y1 = corners[(i+1)%4].y - m_points[1].y; // vertical dist from next corner to dimension line
// if they're both above or both below, no intersection of this segment
if ( (y0 > 0.0 && y1 > 0.0) || (y0 < 0.0 && y1 < 0.0) || y0 == y1 )
continue;
// segment intersects dimension line.
// find x-coord of intersection
t = y0/(y0-y1);
xx = (1.0-t)*corners[i].x + t*corners[(i+1)%4].x;
if ( ON_UNSET_VALUE == xx0 )
{
xx0 = xx1 = xx;
}
else if ( xx < xx0 )
{
xx0 = xx;
}
else if ( xx > xx1 )
{
xx1 = xx;
}
}
// Nov 4 2009 - Lowell - Added test for no intersection of text with dimension line rr33003
// Important for user positioned text that's moved out of the way of the dimension line
if(xx0 != ON_UNSET_VALUE && xx1 != ON_UNSET_VALUE)
{
// xx0 is left edge of text rect
// xx1 is right edge of text rect
t = arrowwidth + tailwidth;
if ( x0 + t <= xx0 && xx0 < xx1 && xx1 <= x1 - t )
{
// clip line, 2 segments arrows inside
x[0] = x0;
x[1] = xx0;
x[2] = xx1;
x[3] = x1;
x[4] = x0;
x[5] = x1;
if( dimextension != 0.0)
{
x[0] -= dimextension;
x[3] += dimextension;
}
rc = 2;
}
else // 2 segments, put the arrows outside the extension lines
{
x[0] = x0;
x[1] = x0 - t;
x[2] = x1 + t;
x[3] = x1;
x[4] = x0;
x[5] = x1;
if( dimextension != 0.0)
{
x[0] += dimextension;
x[3] -= dimextension;
}
bInside = false;
rc = 2;
}
}
else
{
// 1 segment, arrows inside
x[0] = x0;
x[1] = x1;
x[2] = x0;
x[3] = x1;
x[4] = x0;
x[5] = x1;
if( dimextension != 0.0)
{
x[0] -= dimextension;
x[1] += dimextension;
}
rc = 1;
}
}
// Above line text
else if (ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kAboveLine == textdisplay || m_userpositionedtext)
{
// 1 segment, arrows inside
x[0] = x0;
x[1] = x1;
x[2] = x0;
x[3] = x1;
x[4] = x0;
x[5] = x1;
if( dimextension != 0.0)
{
x[0] -= dimextension;
x[1] += dimextension;
}
rc = 1;
}
// In line text
else if (ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kInLine == textdisplay)
{
// 2 segments, arrows inside
t = 0.5*(dimwidth - textwidth - 2.0*textgap);
x[0] = x0;
x[1] = x0+t;
x[2] = x1-t;
x[3] = x1;
x[4] = x0;
x[5] = x1;
if( dimextension != 0.0)
{
x[0] -= dimextension;
x[3] += dimextension;
}
rc = 2;
}
return rc;
}
const wchar_t* ON_OBSOLETE_V5_DimLinear::DefaultText() { return L"<>"; }
//----- ON_OBSOLETE_V5_DimRadial ------------------------------------------
ON_OBSOLETE_V5_DimRadial::ON_OBSOLETE_V5_DimRadial()
{
m_type = ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter;
m_textdisplaymode = ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kInLine;
SetTextValue(DefaultDiameterText());
SetTextFormula(0);
m_points.Reserve(ON_OBSOLETE_V5_DimRadial::dim_pt_count);
m_points.SetCount(ON_OBSOLETE_V5_DimRadial::dim_pt_count);
m_points.Zero();
}
ON_OBSOLETE_V5_DimRadial* 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
)
{
ON_OBSOLETE_V5_DimRadial* V5_radial_dimension
= (nullptr != destination)
? destination
: new ON_OBSOLETE_V5_DimRadial();
V5_radial_dimension->Internal_InitializeFromV2Annotation(V2_radial_dimension,annotation_context);
return V5_radial_dimension;
}
bool ON_OBSOLETE_V5_DimRadial::IsValid( ON_TextLog* text_log ) const
{
if ( m_type != ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius && m_type != ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimRadial - m_type != ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius or ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter\n");
}
return false;
}
if ( !ON_OBSOLETE_V5_Annotation::IsValid( text_log ))
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimRadial - invalid ON_OBSOLETE_V5_Annotation base class.\n");
}
return false;
}
if ( 4 != m_points.Count() )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimRadial - m_points.Count() = %d (should be 4 or 5)\n", m_points.Count() );
}
return false;
}
return true;
}
bool ON_OBSOLETE_V5_DimRadial::Write(ON_BinaryArchive& archive) const
{
// 18 October 2007 Dale Lear
// I added the chunk wrapping so V5 and future versions can
// add IO support for information specific to ON_OBSOLETE_V5_DimRadial
// V4 did not have a ON_OBSOLETE_V5_DimRadial::Write and simply called
// ON_OBSOLETE_V5_Annotation::Write.
bool rc = false;
bool bInChunk = (archive.Archive3dmVersion() >= 5);
if ( bInChunk )
{
rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
if ( !rc )
return false;
}
else
{
rc = true;
}
while(rc)
{
rc = ON_OBSOLETE_V5_Annotation::Write(archive)?true:false;
if (!rc) break;
if ( !bInChunk )
break;
// To write new fields, increment minor version number
// and write values here. Ask Dale Lear for help.
break;
}
if ( bInChunk )
{
if (!archive.EndWrite3dmChunk())
rc = false;
}
return rc;
}
bool ON_OBSOLETE_V5_DimRadial::Read(ON_BinaryArchive& archive)
{
// 18 October 2007 Dale Lear
// I added the chunk wrapping so V5 and future versions can
// add IO support for information specific to ON_OBSOLETE_V5_DimRadial
int major_version = 0;
int minor_version = 0;
bool rc = false;
bool bInChunk = (archive.Archive3dmVersion() >= 5 && archive.ArchiveOpenNURBSVersion() >= 200710180);
if ( bInChunk )
{
rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
if ( !rc )
return false;
}
else
{
rc = true;
}
while(rc)
{
rc = ON_OBSOLETE_V5_Annotation::Read(archive)?true:false;
if (!rc) break;
if ( !bInChunk || minor_version <= 0 )
break;
// read future addition here
break;
}
if ( bInChunk )
{
if ( !archive.EndRead3dmChunk() )
rc = false;
}
return rc;
}
bool ON_OBSOLETE_V5_DimRadial::GetBBox(
double* boxmin,
double* boxmax,
bool bGrowBox
) const
{
ON_BoundingBox bbox;
if ( bGrowBox )
{
bbox.m_min.x = boxmin[0];
bbox.m_min.y = boxmin[1];
bbox.m_min.z = boxmin[2];
bbox.m_max.x = boxmax[0];
bbox.m_max.y = boxmax[1];
bbox.m_max.z = boxmax[2];
if ( !bbox.IsValid() )
{
bbox.Destroy();
bGrowBox = false;
}
}
if ( 4 == m_points.Count() )
{
ON_3dPointArray P(4);
ON_2dPoint uv;
if ( m_userpositionedtext )
{
uv = m_points[0]; // point someplace in text
P.Append( m_plane.PointAt(uv.x,uv.y) );
}
P.Append( m_plane.origin ); // + sign at center of dimension
uv = m_points[1];
P.Append( m_plane.PointAt(uv.x,uv.y) );
uv = m_points[2];
P.Append( m_plane.PointAt(uv.x,uv.y) );
uv = m_points[3];
P.Append( m_plane.PointAt(uv.x,uv.y) );
bGrowBox = P.GetBBox(&bbox.m_min.x, &bbox.m_max.x, bGrowBox);
}
if ( bGrowBox )
{
boxmin[0] = bbox.m_min.x;
boxmin[1] = bbox.m_min.y;
boxmin[2] = bbox.m_min.z;
boxmax[0] = bbox.m_max.x;
boxmax[1] = bbox.m_max.y;
boxmax[2] = bbox.m_max.z;
}
return bGrowBox;
}
bool ON_OBSOLETE_V5_DimRadial::GetTightBoundingBox(
ON_BoundingBox& tight_bbox,
bool bGrowBox,
const ON_Xform* xform
) const
{
if ( 4 == m_points.Count() )
{
ON_3dPointArray P(4);
for(int i = 0; i < 4; i++)
P.Append( m_plane.PointAt(m_points[i].x,m_points[i].y) );
if ( P.GetTightBoundingBox( tight_bbox, bGrowBox, xform ) )
bGrowBox = true;
}
else if ( bGrowBox && !tight_bbox.IsValid() )
{
tight_bbox.Destroy();
bGrowBox = false;
}
return (0!=bGrowBox);
}
ON_2dPoint ON_OBSOLETE_V5_DimRadial::Dim2dPoint(
int point_index
) const
{
ON_2dPoint p2;
if ( m_points.Count() < dim_pt_count || point_index < 0 )
{
p2.x = p2.y = ON_UNSET_VALUE;
}
else
{
if ( text_pivot_pt == point_index )
{
point_index = tail_pt_index;
}
if ( point_index < dim_pt_count )
{
p2 = m_points[point_index];
}
else
{
p2.x = p2.y = ON_UNSET_VALUE;
}
}
return p2;
}
ON_3dPoint ON_OBSOLETE_V5_DimRadial::Dim3dPoint(
int point_index
) const
{
ON_2dPoint p2 = Dim2dPoint(point_index);
return (ON_UNSET_VALUE == p2.x) ? ON_3dPoint::UnsetPoint : m_plane.PointAt(p2.x,p2.y);
}
// set the plane, center, and point on curve.
// the rest will be set by the Rhino dimension
bool ON_OBSOLETE_V5_DimRadial::CreateFromPoints(
ON_3dPoint center,
ON_3dPoint arrowtip,
ON_3dVector xaxis,
ON_3dVector normal,
double offset_distance)
{
if ( m_type != ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter )
m_type = ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius;
bool rc = false;
if ( center.IsValid() && arrowtip.IsValid() && normal.IsValid() && !normal.IsZero() && xaxis.IsValid() && !xaxis.IsZero() )
{
ON_Plane plane( center, normal);
double c = xaxis*plane.xaxis;
double s = xaxis*plane.yaxis;
if ( c != 0.0 || s != 0.0 )
{
if ( c <= 0.0 || s != 0.0 )
{
plane.Rotate( s, c, plane.zaxis );
}
m_plane = plane;
ON_2dVector tip;
if ( m_plane.ClosestPointTo(arrowtip,&tip.x,&tip.y) )
{
//double r = tip.Length();
m_points.SetCapacity(dim_pt_count);
m_points.SetCount(dim_pt_count);
m_points[center_pt_index].Set(0.0,0.0);
m_points[arrow_pt_index] = tip;
tip.Unitize();
m_points[knee_pt_index] = m_points[arrow_pt_index] + offset_distance*tip;
m_points[tail_pt_index] = m_points[knee_pt_index];
if ( m_points[arrow_pt_index].x < 0.0 )
m_points[tail_pt_index].x -= offset_distance;
else
m_points[tail_pt_index].x += offset_distance;
m_plane = plane;
m_userpositionedtext = false;
rc = true;
}
}
}
return rc;
}
double ON_OBSOLETE_V5_DimRadial::NumericValue() const
{
double d = 0.0;
if ( m_points.Count() >= dim_pt_count )
{
d = (m_points[center_pt_index] - m_points[arrow_pt_index]).Length();
if( ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter == m_type )
d *= 2.0;
}
return d;
}
int ON_OBSOLETE_V5_DimRadial::StyleIndex() const
{
return ON_OBSOLETE_V5_Annotation::V5_3dmArchiveDimStyleIndex();
}
void ON_OBSOLETE_V5_DimRadial::SetStyleIndex( int i)
{
ON_OBSOLETE_V5_Annotation::SetV5_3dmArchiveDimStyleIndex( i);
}
const wchar_t* ON_OBSOLETE_V5_DimRadial::DefaultRadiusText()
{
static wchar_t defstr[4] = { ON_wString::RadiusSymbol, L'<', L'>', 0 };
return defstr;
}
const wchar_t* ON_OBSOLETE_V5_DimRadial::DefaultDiameterText()
{
static wchar_t defstr[4] = { ON_wString::DiameterSymbol, L'<', L'>', 0 };
return defstr;
}
bool ON_OBSOLETE_V5_DimRadial::CreateFromV2(
const ON_OBSOLETE_V2_Annotation& v2_ann,
const ON_3dmAnnotationSettings& settings,
int dimstyle_index
)
{
bool rc = false;
if( ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius == v2_ann.m_type || ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter == v2_ann.m_type )
{
const ON_SimpleArray<ON_2dPoint>& points = v2_ann.Points();
if ( points.Count() >= 4 )
{
m_points.Reserve(4);
m_points.SetCount(0);
m_points.Append(4,points.Array());
m_plane = v2_ann.m_plane;
m_plane.UpdateEquation();
SetTextValue(static_cast< const wchar_t* >(v2_ann.UserText()));
SetTextFormula(0);
m_userpositionedtext = false;
m_type = v2_ann.Type();
m_textdisplaymode = ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kInLine;
SetV5_3dmArchiveDimStyleIndex(dimstyle_index);
ON_2dVector v = m_points[0];
if ( !v.IsZero() )
{
m_plane.origin = m_plane.PointAt(v.x,v.y);
m_plane.UpdateEquation();
v = -v;
m_points[0].Set(0.0,0.0);
m_points[1] += v;
m_points[2] += v;
m_points[3] += v;
}
rc = true;
}
}
return rc;
}
//----- ON_AngularDimension2Extra -----------------------------------------
// Additions to ON_OBSOLETE_V5_DimAngular class
class ON_AngularDimension2Extra : public ON_UserData
{
ON_OBJECT_DECLARE(ON_AngularDimension2Extra);
public:
static ON_AngularDimension2Extra* AngularDimensionExtra(ON_OBSOLETE_V5_DimAngular* pDim/*, bool bCreate*/);
static const ON_AngularDimension2Extra* AngularDimensionExtra(const ON_OBSOLETE_V5_DimAngular* pDim/*, bool bCreate*/);
ON_AngularDimension2Extra();
~ON_AngularDimension2Extra();
// override virtual ON_Object::Dump function
void Dump( ON_TextLog& text_log ) const override;
// override virtual ON_Object::SizeOf 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;
// Scale all of the length values
void Scale( double scale);
//
double DimpointOffset(int index) const;
void SetDimpointOffset(int index, double offset);
// offsets from apex of dimension to point from which extension lines start
// if these are < 0.0, they are ignored
// Extension lines are drawn from theses points to the Arrow tip points
// subject to dimexe & dimexo & dimse1 & dimse2
double m_dimpoint_offset[2];
};
ON_OBJECT_IMPLEMENT(ON_AngularDimension2Extra,ON_UserData,"A68B151F-C778-4a6e-BCB4-23DDD1835677");
ON_AngularDimension2Extra* ON_AngularDimension2Extra::AngularDimensionExtra(ON_OBSOLETE_V5_DimAngular* pDim)
{
ON_AngularDimension2Extra* pExtra = 0;
if(pDim)
{
pExtra = ON_AngularDimension2Extra::Cast(pDim->GetUserData(ON_CLASS_ID(ON_AngularDimension2Extra)));
if(pExtra == 0)
{
pExtra = new ON_AngularDimension2Extra;
if( pExtra)
{
if(!pDim->AttachUserData(pExtra))
{
delete pExtra;
pExtra = 0;
}
}
}
}
return pExtra;
}
const ON_AngularDimension2Extra* ON_AngularDimension2Extra::AngularDimensionExtra(const ON_OBSOLETE_V5_DimAngular* pDim)
{
return AngularDimensionExtra((ON_OBSOLETE_V5_DimAngular*)pDim);
}
ON_AngularDimension2Extra::ON_AngularDimension2Extra()
{
m_userdata_uuid = ON_CLASS_ID(ON_AngularDimension2Extra);
m_application_uuid = ON_opennurbs5_id; // opennurbs.dll reads/writes this userdata
// The id must be the version 5 id because
// V6 SaveAs V5 needs to work, but SaveAs
// V4 should not write this userdata.
m_userdata_copycount = 1;
m_dimpoint_offset[0] = 0;
m_dimpoint_offset[1] = 0;
}
ON_AngularDimension2Extra::~ON_AngularDimension2Extra()
{
}
void ON_AngularDimension2Extra::Dump( ON_TextLog& text_log ) const
{
// do nothing
}
unsigned int ON_AngularDimension2Extra::SizeOf() const
{
unsigned int sz = ON_UserData::SizeOf();
sz += sizeof(*this) - sizeof(ON_UserData);
return sz;
}
bool ON_AngularDimension2Extra::Write(ON_BinaryArchive& archive) const
{
int major_version = 1;
int minor_version = 0;
bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,major_version,minor_version);
if(rc) rc = archive.WriteDouble(m_dimpoint_offset[0]);
if(rc) rc = archive.WriteDouble(m_dimpoint_offset[1]);
if(!archive.EndWrite3dmChunk())
rc = false;
return rc;
}
bool ON_AngularDimension2Extra::Read(ON_BinaryArchive& archive)
{
int major_version = 1;
int minor_version = 0;
bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
if(major_version != 1)
rc = false;
if(rc) rc = archive.ReadDouble(&m_dimpoint_offset[0]);
if(rc) rc = archive.ReadDouble(&m_dimpoint_offset[1]);
if ( !archive.EndRead3dmChunk() )
rc = false;
return rc;
}
bool ON_AngularDimension2Extra::GetDescription( ON_wString& description)
{
description = L"Userdata extension of ON_OBSOLETE_V5_DimAngular";
return true;
}
bool ON_AngularDimension2Extra::Archive() const
{
// true to write to file
return true;
}
void ON_AngularDimension2Extra::Scale(double scale)
{
if( ON_IsValid(scale) && scale > ON_SQRT_EPSILON)
{
m_dimpoint_offset[0] *= scale;
m_dimpoint_offset[1] *= scale;
}
}
double ON_AngularDimension2Extra::DimpointOffset(int index) const
{
if(index == 0)
return m_dimpoint_offset[0];
if(index == 1)
return m_dimpoint_offset[1];
return -1;
}
void ON_AngularDimension2Extra::SetDimpointOffset(int index, double offset)
{
if(index >= 0 && index <= 1)
m_dimpoint_offset[index] = offset;
}
//----- ON_OBSOLETE_V5_DimAngular -----------------------------------------
ON_OBSOLETE_V5_DimAngular::ON_OBSOLETE_V5_DimAngular()
: m_angle(0.0)
, m_radius(1.0)
{
m_type = ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAngular;
m_textdisplaymode = ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kAboveLine;
SetTextValue(DefaultText());
SetTextFormula(0);
m_points.Reserve(ON_OBSOLETE_V5_DimAngular::dim_pt_count);
m_points.SetCount(ON_OBSOLETE_V5_DimAngular::dim_pt_count);
m_points.Zero();
}
ON_OBSOLETE_V5_DimAngular* 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
)
{
ON_OBSOLETE_V5_DimAngular* V5_angular_dimension
= (nullptr != destination)
? destination
: new ON_OBSOLETE_V5_DimAngular();
V5_angular_dimension->Internal_InitializeFromV2Annotation(V2_angular_dimension,annotation_context);
ON_2dVector v0 // point on first line
= (V2_angular_dimension.m_points.Count() >= 2 && V2_angular_dimension.m_points[0].IsValid())
? (V2_angular_dimension.m_points[0] - ON_2dPoint::Origin)
: ON_2dVector::ZeroVector;
ON_2dVector v1 // point on second line
= (V2_angular_dimension.m_points.Count() >= 2 && V2_angular_dimension.m_points[1].IsValid())
? (V2_angular_dimension.m_points[1] - ON_2dPoint::Origin)
: ON_2dVector::ZeroVector;
ON_2dPoint tp // point on second line
= (V2_angular_dimension.m_points.Count() >= 3 && V2_angular_dimension.m_points[2].IsValid())
? V2_angular_dimension.m_points[2]
: ON_2dPoint::UnsetPoint;
double angle = V2_angular_dimension.Radius();
double radius = V2_angular_dimension.Angle();
bool bUserPositionedText = (v0.IsNotZero() && v1.IsNotZero() && V5_angular_dimension->m_userpositionedtext && tp.IsValid());
V5_angular_dimension->m_userpositionedtext = bUserPositionedText;
if (v0.IsNotZero() && v1.IsNotZero())
{
ON_Plane plane = V5_angular_dimension->m_plane;
for (;;)
{
if (v0.x > 0.0 && 0.0 == v0.y)
break;
bUserPositionedText = false;
const double length0 = v0.Length();
if (!(length0 > 0.0))
break;
const ON_3dPoint P0 = plane.PointAt(v0.x, v0.y);
if (!P0.IsValid())
break;
const ON_3dPoint P1 = plane.PointAt(v1.x, v1.y);
if (!P1.IsValid())
break;
plane.xaxis = P0 - plane.origin;
if (!plane.xaxis.Unitize())
break;
plane.yaxis = ON_CrossProduct(plane.zaxis, plane.xaxis);
if (!plane.yaxis.Unitize())
break;
if (!plane.IsValid())
break;
ON_2dVector v = v1;
if (!plane.ClosestPointTo(P1, &v.x, &v.y))
break;
v0.x = length0;
v0.y = 0.0;
v1 = v;
V5_angular_dimension->m_plane = plane;
angle = atan2(v1.y,v1.x);
if ( angle < 0.0 )
angle += 2.0*ON_PI;
radius = 0.5*(v0.Length() + v1.Length());
break;
}
}
if ( !bUserPositionedText )
{
tp.x = radius*cos(0.5*angle);
tp.y = radius*sin(0.5*angle);
}
const ON_2dPoint arcpt( radius*cos(angle/3.0), radius*sin(angle/3.0) );
V5_angular_dimension->m_points.SetCapacity(4);
V5_angular_dimension->m_points.SetCount(4);
V5_angular_dimension->m_points[0] = tp.IsValid() ? tp : ON_2dPoint::Origin;
V5_angular_dimension->m_points[1] = (v0.IsValid() && v0.IsNotZero()) ? ON_2dPoint(v0) : ON_2dPoint::Origin;
V5_angular_dimension->m_points[2] = (v1.IsValid() && v1.IsNotZero()) ? ON_2dPoint(v1) : ON_2dPoint::Origin;
V5_angular_dimension->m_points[3] = arcpt.IsValid() ? arcpt : ON_2dPoint::Origin;
V5_angular_dimension->m_angle = angle;
V5_angular_dimension->m_radius = radius;
V5_angular_dimension->m_userpositionedtext = bUserPositionedText;
return V5_angular_dimension;
}
bool ON_OBSOLETE_V5_DimAngular::IsValid( ON_TextLog* text_log ) const
{
if ( m_type != ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAngular )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimAngular - m_type != ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAngular\n");
}
return false;
}
if ( !ON_OBSOLETE_V5_Annotation::IsValid( text_log ))
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimAngular - invalid ON_OBSOLETE_V5_Annotation base class.\n");
}
return false;
}
if ( 4 != m_points.Count() )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimAngular - m_points.Count() = %d (should be 4)\n", m_points.Count() );
}
return false;
}
if ( !ON_IsValid(m_angle) || m_angle <= 0.0 || m_angle > 2.0*ON_PI )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimAngular - bogus m_angle = %g\n",m_angle);
}
return false;
}
if ( !ON_IsValid(m_radius) || m_radius <= 0.0 )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimAngular - bogus m_radius = %g\n",m_radius);
}
return false;
}
if ( 0.0 == m_points[1].x && 0.0 == m_points[1].y )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimAngular - angle dim m_points[1] = center (should be on start ray).\n");
}
return false;
}
if ( 0.0 == m_points[2].x && 0.0 == m_points[2].y )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimAngular - angle dim m_points[2] = center (should be on end ray).\n");
}
return false;
}
if ( 0.0 == m_points[3].x && 0.0 == m_points[3].y )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimAngular - angle dim m_points[3] = center (should be on interior of arc).\n");
}
return false;
}
double a1 = atan2(m_points[1].y, m_points[1].x);
double a2 = atan2(m_points[2].y, m_points[2].x);
double a3 = atan2(m_points[3].y, m_points[3].x);
if ( a1 < 0.0 )
a1 += 2.0*ON_PI;
while ( a2 <= a1 )
a2 += 2.0*ON_PI;
while ( a3 < a1 ) // Oct 23 2009 LW changed from a3 <= a1 to allow point at end of arc rr53634
a3 += 2.0*ON_PI;
if ( fabs(m_angle - (a2-a1)) > ON_ZERO_TOLERANCE + m_angle*ON_SQRT_EPSILON )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimAngular - m_angle = %g != %g = (end angle - start angle)\n",m_angle,a2-a1);
}
return false;
}
double r = ON_2dVector(m_points[3]).Length();
if ( fabs(r - m_radius) > ON_ZERO_TOLERANCE + m_radius*ON_SQRT_EPSILON )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimAngular - m_radius = %g != %g = |m_point[3])|\n",m_radius,r);
}
return false;
}
if ( a3 > a2 ) // Oct 23 2009 LW changed from a3 >= a2 to allow point at end of arc rr53634
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimAngular - angle dim m_points[3] = not on arc interior.\n");
}
return false;
}
return true;
}
bool ON_OBSOLETE_V5_DimAngular::GetBBox(
double* boxmin,
double* boxmax,
bool bGrowBox
) const
{
ON_BoundingBox bbox;
if ( bGrowBox )
{
bbox.m_min.x = boxmin[0];
bbox.m_min.y = boxmin[1];
bbox.m_min.z = boxmin[2];
bbox.m_max.x = boxmax[0];
bbox.m_max.y = boxmax[1];
bbox.m_max.z = boxmax[2];
if ( !bbox.IsValid() )
{
bbox.Destroy();
bGrowBox = false;
}
}
ON_Arc arc;
if ( GetArc(arc) )
{
if ( arc.GetTightBoundingBox(bbox,bGrowBox?true:false,0) )
bGrowBox = true;
}
if ( bGrowBox )
{
boxmin[0] = bbox.m_min.x;
boxmin[1] = bbox.m_min.y;
boxmin[2] = bbox.m_min.z;
boxmax[0] = bbox.m_max.x;
boxmax[1] = bbox.m_max.y;
boxmax[2] = bbox.m_max.z;
}
return bGrowBox;
}
bool ON_OBSOLETE_V5_DimAngular::GetTightBoundingBox(
ON_BoundingBox& tight_bbox,
bool bGrowBox,
const ON_Xform* xform
) const
{
ON_Arc arc;
if ( GetArc(arc) )
{
if ( arc.GetTightBoundingBox(tight_bbox,bGrowBox,xform) )
bGrowBox = true;
}
else if ( bGrowBox && !tight_bbox.IsValid() )
{
tight_bbox.Destroy();
bGrowBox = false;
}
return (0!=bGrowBox);
}
ON_2dPoint ON_OBSOLETE_V5_DimAngular::Dim2dPoint( int point_index ) const
{
ON_2dPoint p2;
if ( m_points.Count() < dim_pt_count || point_index < 0 )
{
p2.x = p2.y = ON_UNSET_VALUE;
}
else
{
if ( text_pivot_pt == point_index )
{
point_index = m_userpositionedtext
? userpositionedtext_pt_index
: arcmid_pt;
}
if ( point_index < dim_pt_count )
{
p2 = m_points[point_index];
}
else
{
switch(point_index)
{
case arcstart_pt:
p2.x = m_radius;
p2.y = 0.0;
break;
case arcend_pt:
p2.x = m_radius*cos(m_angle);
p2.y = m_radius*sin(m_angle);
break;
case arccenter_pt:
p2.x = 0.0;
p2.y = 0.0;
break;
case arcmid_pt:
p2.x = m_radius*cos(0.5*m_angle);
p2.y = m_radius*sin(0.5*m_angle);
break;
case extension0_pt:
{
p2 = m_points[start_pt_index];
double dp0 = DimpointOffset(0);
if(dp0 >= 0)
{
ON_2dVector v2 = (ON_2dVector)p2;
v2.Unitize();
p2 = (ON_2dPoint)v2 * dp0;
}
}
break;
case extension1_pt:
{
p2 = m_points[end_pt_index];
double dp1 = DimpointOffset(1);
if(dp1 >= 0)
{
ON_2dVector v2 = (ON_2dVector)p2;
v2.Unitize();
p2 = (ON_2dPoint)v2 * dp1;
}
}
break;
default:
p2.x = p2.y = ON_UNSET_VALUE;
break;
}
}
}
return p2;
}
ON_3dPoint ON_OBSOLETE_V5_DimAngular::Dim3dPoint( int point_index ) const
{
ON_2dPoint p2 = Dim2dPoint(point_index);
if (ON_UNSET_VALUE == p2.x)
return ON_3dPoint::UnsetPoint;
ON_3dPoint p = m_plane.PointAt(p2.x, p2.y);
return p;
//return (ON_UNSET_VALUE == p2.x) ? ON_3dPoint::UnsetPoint : m_plane.PointAt(p2.x,p2.y);
}
bool ON_OBSOLETE_V5_DimAngular::Write( ON_BinaryArchive& file ) const
{
// 18 October 2007 Dale Lear
// I added the chunk wrapping so V5 and future versions can
// add IO support for information specific to ON_OBSOLETE_V5_DimLinear
// V4 did not have a ON_OBSOLETE_V5_DimLinear::Write and simply called
// ON_OBSOLETE_V5_Annotation::Write.
bool rc = false;
bool bInChunk = (file.Archive3dmVersion() >= 5);
if ( bInChunk )
{
rc = file.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
if ( !rc )
return false;
}
else
{
rc = true;
}
while(rc)
{
rc = ON_OBSOLETE_V5_Annotation::Write(file)?true:false;
if (!rc) break;
rc = file.WriteDouble( m_angle);
if (!rc) break;
rc = file.WriteDouble( m_radius);
if (!rc) break;
if ( !bInChunk )
break;
// to write new V5 fields, increment the minor
// version number and write them below
break;
}
if ( bInChunk )
{
if (!file.EndWrite3dmChunk())
rc = false;
}
return rc;
}
bool ON_OBSOLETE_V5_DimAngular::Read( ON_BinaryArchive& file )
{
// 18 October 2007 Dale Lear
// I added the chunk wrapping so V5 and future versions can
// add IO support for information specific to ON_OBSOLETE_V5_DimAngular
int major_version = 0;
int minor_version = 0;
bool rc = false;
bool bInChunk = (file.Archive3dmVersion() >= 5 && file.ArchiveOpenNURBSVersion() >= 200710180);
if ( bInChunk )
{
rc = file.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
if ( !rc )
return false;
}
else
{
rc = true;
}
while(rc)
{
rc = ON_OBSOLETE_V5_Annotation::Read(file)?true:false;
if (!rc) break;
rc = file.ReadDouble( &m_angle);
if (!rc) break;
rc = file.ReadDouble( &m_radius);
if (!rc) break;
if ( !bInChunk || minor_version <= 0 )
break;
// Code to read any new ON_OBSOLETE_V5_DimAngular fields will
// go here.
break;
}
if ( bInChunk )
{
// To read new ON_OBSOLETE_V5_DimAngular specific additions,
// examine the minor version number and read the information
// here. Please ask Dale Lear for help.
if ( !file.EndRead3dmChunk() )
rc = false;
}
return rc;
}
static bool VectorAngle( const ON_2dVector& v, double& angle)
{
if( v.IsTiny())
return false;
angle = atan2( v.y, v.x);
if( angle < 0.0)
angle += 2.0 * ON_PI;
if( angle > 2.0 * ON_PI)
angle -= 2.0 * ON_PI;
return true;
}
bool ON_OBSOLETE_V5_DimAngular::CreateFromArc( const ON_Arc& arc )
{
// June 9, 2010 - Lowell - Changed to call CreateFromPoints()
bool rc = arc.IsValid();
if (rc)
{
ON_3dPoint C = arc.Center();
ON_3dPoint S = arc.StartPoint();
ON_3dPoint E = arc.EndPoint();
ON_3dPoint M = arc.MidPoint();
ON_3dVector N = arc.Plane().zaxis;
rc = CreateFromPoints(C, S, E, M, N);
}
return rc;
}
bool ON_OBSOLETE_V5_DimAngular::GetArc( ON_Arc& arc ) const
{
bool rc = false;
// Jan 25, 2007 - changed min radius from >0 to >ON_SQRT_EPSILON
// to avoid domain problems trying to use very small arcs later
if ( ON_IsValid(m_radius) && m_radius > ON_SQRT_EPSILON
&& ON_IsValid(m_angle) && m_angle > 0.0 && m_angle <= 2.0*ON_PI
&& m_plane.origin.IsValid()
&& m_plane.xaxis.IsValid()
&& m_plane.yaxis.IsValid()
&& m_plane.zaxis.IsValid()
&& fabs( m_plane.zaxis.Length() - 1.0 ) <= ON_SQRT_EPSILON
&& 4 == m_points.Count()
)
{
ON_3dVector X = m_plane.PointAt( m_points[start_pt_index].x, m_points[start_pt_index].y ) - m_plane.origin;
if ( fabs(X.Length()-1.0) <= ON_SQRT_EPSILON || X.Unitize() )
{
if ( fabs(X*m_plane.zaxis) <= ON_SQRT_EPSILON )
{
ON_3dVector Y = ON_CrossProduct( m_plane.zaxis, X );
if ( fabs(Y.Length()-1.0) <= ON_SQRT_EPSILON || Y.Unitize() )
{
arc.plane = m_plane;
arc.plane.xaxis = X;
arc.plane.yaxis = Y;
arc.plane.UpdateEquation();
arc.SetAngleIntervalRadians( ON_Interval(0.0,m_angle) );
arc.radius = m_radius;
rc = true;
}
}
}
}
return rc;
}
bool ON_OBSOLETE_V5_DimAngular::GetExtensionLines(ON_Line extensions[2]) const
{
bool rc = false;
if ( ON_IsValid(m_radius) && m_radius > ON_SQRT_EPSILON
&& ON_IsValid(m_angle) && m_angle > 0.0 && m_angle <= 2.0*ON_PI
&& m_plane.origin.IsValid()
&& m_plane.xaxis.IsValid()
&& m_plane.yaxis.IsValid()
&& m_plane.zaxis.IsValid()
&& fabs( m_plane.zaxis.Length() - 1.0 ) <= ON_SQRT_EPSILON
&& 4 == m_points.Count()
)
{
const ON_AngularDimension2Extra* pDE = ON_AngularDimension2Extra::AngularDimensionExtra(this);
if(pDE != 0)
{
double exoffset0 = pDE->DimpointOffset(0);
double exoffset1 = pDE->DimpointOffset(1);
ON_3dPoint e00, e01, e10, e11;
e00 = m_plane.PointAt(m_points[start_pt_index].x, m_points[start_pt_index].y);
e10 = m_plane.PointAt(m_points[end_pt_index].x, m_points[end_pt_index].y);
ON_3dVector X = e00 - m_plane.origin;
ON_3dVector Y = e10 - m_plane.origin;
if((fabs(X.Length()-1.0) <= ON_SQRT_EPSILON || X.Unitize()) &&
(fabs(Y.Length()-1.0) <= ON_SQRT_EPSILON || Y.Unitize()))
{
if((fabs(X*m_plane.zaxis) <= ON_SQRT_EPSILON) &&
(fabs(Y*m_plane.zaxis) <= ON_SQRT_EPSILON))
{
e00 = m_plane.origin + X * exoffset0;
e10 = m_plane.origin + Y * exoffset1;
e01 = m_plane.origin + X * m_radius;
e11 = m_plane.origin + Y * m_radius;
extensions[0].from = e00;
extensions[0].to = e01;
extensions[1].from = e10;
extensions[1].to = e11;
rc = true;
}
}
}
}
return rc;
}
bool ON_OBSOLETE_V5_DimAngular::CreateFromPoints(
const ON_3dPoint& pc,
const ON_3dPoint& p0in,
const ON_3dPoint& p1in,
ON_3dPoint& arcpt,
ON_3dVector& Normal)
{
ON_3dPoint p0, p1;
p0 = p0in;
p1 = p1in;
ON_Plane plane( pc, Normal);
ON_2dPoint pa, pp0, pp1;
if( !plane.ClosestPointTo( p0, &pp0.x, &pp0.y))
return false;
// rotate so that p0 is on x-axis
ON_2dVector v0( pp0);
v0.Unitize();
if ( v0.IsValid() && v0.IsNotZero() )
plane.Rotate( v0.y, v0.x, plane.Normal());
if( !plane.ClosestPointTo( p0, &pp0.x, &pp0.y))
return false;
if( !plane.ClosestPointTo( arcpt, &pa.x, &pa.y))
return false;
if( !plane.ClosestPointTo( p1, &pp1.x, &pp1.y))
return false;
double a1 = ON_DBL_QNAN;
double aa = ON_DBL_QNAN;
if( !VectorAngle( ON_2dVector( pp1), a1) || !VectorAngle( ON_2dVector( pa), aa))
return false;
if( aa > a1) // the angle is really the bigger one ( > 180)
{
// rotate so that p0 is on x-axis
v0.Set( pp1.x, pp1.y);
v0.Unitize();
plane.Rotate( v0.y, v0.x, plane.Normal());
if( !plane.ClosestPointTo( arcpt, &pa.x, &pa.y))
return false;
if( !plane.ClosestPointTo( p1, &pp0.x, &pp0.y))
return false;
if( !plane.ClosestPointTo( p0, &pp1.x, &pp1.y))
return false;
}
VectorAngle( ON_2dVector( pp1), a1);
SetAngle( a1);
SetRadius( ON_2dVector( pa).Length());
ON_AngularDimension2Extra* pDE = ON_AngularDimension2Extra::AngularDimensionExtra(this);
if(pDE != 0)
{
double os = ((ON_2dVector)pp0).Length();
pDE->SetDimpointOffset(0, os);
os = ((ON_2dVector)pp1).Length();
pDE->SetDimpointOffset(1, os);
}
ReservePoints( 4);
SetPlane( plane);
SetPoint( 1, pp0);
SetPoint( 2, pp1);
SetPoint( 3, pa);
return true;
}
void ON_OBSOLETE_V5_DimAngular::SetAngle( double angle)
{
m_angle = angle;
}
double ON_OBSOLETE_V5_DimAngular::Angle() const
{
return m_angle;
}
void ON_OBSOLETE_V5_DimAngular::SetRadius( double radius)
{
m_radius = radius;
}
double ON_OBSOLETE_V5_DimAngular::Radius() const
{
return m_radius;
}
double ON_OBSOLETE_V5_DimAngular::NumericValue() const
{
// This returns degrees - if we get another angular unit system, add it
return (m_angle*180.0/ON_PI);
}
int ON_OBSOLETE_V5_DimAngular::StyleIndex() const
{
return ON_OBSOLETE_V5_Annotation::V5_3dmArchiveDimStyleIndex();
}
void ON_OBSOLETE_V5_DimAngular::SetStyleIndex( int i)
{
ON_OBSOLETE_V5_Annotation::SetV5_3dmArchiveDimStyleIndex( i);
}
const wchar_t* ON_OBSOLETE_V5_DimAngular::DefaultText()
{
return L"<>"; // Aug 31, 2009 - Lowell
}
static void OrientRectHelper( ON_2dVector corners[4] )
{
double twice_area = 0.0;
ON_2dVector p0, p1;
int i;
p1 = corners[3];
for ( i = 0; i < 4; i++ )
{
p0 = p1;
p1 = corners[i];
twice_area += (p0.x-p1.x)*(p0.y+p1.y);
}
if ( twice_area < 0.0 )
{
p1 = corners[1];
corners[1] = corners[3];
corners[3] = p1;
}
}
int ON_OBSOLETE_V5_DimAngular::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
{
int rc = 0;
a[0] = 0.0;
a[1] = 0.0;
if ( m_angle <= 0.0 || !ON_IsValid(m_angle) )
return 0;
a[1] = m_angle;
if ( m_radius <= 0.0 || !ON_IsValid(m_radius) || m_angle >= 2.0*ON_PI )
return 0;
if ( 0 == gdi_height_of_I )
{
// Default to height of Ariel 'I' (this code still works if ON_Font::Constants::AnnotationFontCellHeight != 256)
gdi_height_of_I = (165*ON_Font::Constants::AnnotationFontCellHeight)/256;
}
if ( 0.0 == dimscale )
{
dimscale = 1.0;
}
double t;
ON_INTERNAL_OBSOLETE::V5_TextDisplayMode textdisplay = ON_INTERNAL_OBSOLETE::V5TextDisplayModeFromV6DimStyle(dimstyle);
const double text_height_of_I = dimscale*dimstyle.TextHeight();
const double textgap = dimscale*dimstyle.TextGap();
const double gdi_to_plane_scale = text_height_of_I/gdi_height_of_I;
const double textwidth = fabs(gdi_to_plane_scale*(gdi_text_rect.right - gdi_text_rect.left));
const double arrowwidth = fabs(dimscale*dimstyle.ArrowSize());
const double tailwidth = 0.5*arrowwidth;
const double dimextension = fabs(dimscale*dimstyle.DimExtension());
const double a0 = 0.0;
const double a1 = m_angle;
double sin_angle = 0.5*dimextension/m_radius;
if ( sin_angle > 1.0 ) sin_angle = 1.0; else if (sin_angle < -1.0) sin_angle = -1.0;
const double dimextension_angle = 2.0*asin(sin_angle);
sin_angle = 0.5*arrowwidth/m_radius;
if ( sin_angle > 1.0 ) sin_angle = 1.0; else if (sin_angle < -1.0) sin_angle = -1.0;
const double arrowangle = 2.0*asin(sin_angle);
sin_angle = 0.5*tailwidth/m_radius;
if ( sin_angle > 1.0 ) sin_angle = 1.0; else if (sin_angle < -1.0) sin_angle = -1.0;
const double tailangle = 2.0*asin(sin_angle);
// June 7, 2010 - Lowell - Added some special handling for very small dimensions
double arrow_angle = arrowangle + tailangle;
if(arrow_angle > ON_PI * 0.5)
arrow_angle = ON_PI * 0.5;
if ( m_radius <= arrowwidth + tailwidth || m_radius*(a1-a0) < 2.0*(arrowwidth) + tailwidth )
{
// arc is tiny with respect to arrowhead size - arrowheads have to be "outside"
// 2 arc segments, arrowheads outside
a[0] = a0;
a[1] = a0 - arrow_angle;
a[2] = a1 + arrow_angle;
a[3] = a1;
a[4] = a0;
a[5] = a1;
if( dimextension_angle != 0.0)
{
a[0] += dimextension_angle;
a[3] -= dimextension_angle;
}
bInside = false;
return 2;
}
if (ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kInLine == textdisplay && m_radius <= 0.5*(textwidth + 2.0*textgap))
{
// 2 arc segments, arrowheads outside
a[0] = a0;
a[1] = a0 - arrow_angle;
a[2] = a1 + arrow_angle;
a[3] = a1;
a[4] = a0;
a[5] = a1;
if( dimextension_angle != 0.0)
{
a[0] += dimextension_angle;
a[3] -= dimextension_angle;
}
bInside = false;
return 2;
}
sin_angle = 0.5*(textwidth+2.0*textgap)/m_radius;
if ( sin_angle > 1.0 ) sin_angle = 1.0; else if (sin_angle < -1.0) sin_angle = -1.0;
const double textangle = (ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kInLine == textdisplay && !m_userpositionedtext)
? 2.0*asin(sin_angle)
: 0.0;
if ( (a1-a0) <= 2.0*(arrow_angle) + textangle )
{
// 2 arc segments, arrowheads outside
a[0] = a0;
a[1] = a0 - arrow_angle;
a[2] = a1 + arrow_angle;
a[3] = a1;
a[4] = a0;
a[5] = a1;
if( dimextension_angle != 0.0)
{
a[0] += dimextension_angle;
a[3] -= dimextension_angle;
}
bInside = false;
return 2;
}
if ((ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kHorizontalToScreen == textdisplay && vp) || m_userpositionedtext)
{
// use projected rectangle to clip dimension arc
double aa0, aa1, aa, r0, r1, tt[2];
ON_3dPoint P, R, c[2];
ON_2dVector corners[4], N;
ON_Line ray;
int i,xi, xrc;
const ON_Circle circle(ON_xy_plane,1.0);
ON_3dVector vp_zaxis = (ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kHorizontalToScreen == textdisplay && vp)
? vp->CameraZ()
: m_plane.zaxis;
// 30 July 2012 - Lowell - Slightly shrink the text gap value
// so that text + gap won't intersect the dim line if when text
// is moved along the dim line. rr110504
double gdi_gap = fabs(textgap/gdi_to_plane_scale)-12;
if(gdi_gap < 0.0) gdi_gap = 0.0;
R.Set(gdi_text_rect.left-gdi_gap,gdi_text_rect.bottom+gdi_gap,0.0);
ray.from = gdi_to_world*R; ray.to = ray.from + vp_zaxis;
P = ( ON_Intersect(ray,m_plane,&t) ) ? ray.PointAt(t) : ray.from;
m_plane.ClosestPointTo(P,&corners[0].x,&corners[0].y);
R.Set(gdi_text_rect.right+gdi_gap,gdi_text_rect.bottom+gdi_gap,0.0);
ray.from = gdi_to_world*R; ray.to = ray.from + vp_zaxis;
P = ( ON_Intersect(ray,m_plane,&t) ) ? ray.PointAt(t) : ray.from;
m_plane.ClosestPointTo(P,&corners[1].x,&corners[1].y);
R.Set(gdi_text_rect.right+gdi_gap,gdi_text_rect.top-gdi_gap,0.0);
ray.from = gdi_to_world*R; ray.to = ray.from + vp_zaxis;
P = ( ON_Intersect(ray,m_plane,&t) ) ? ray.PointAt(t) : ray.from;
m_plane.ClosestPointTo(P,&corners[2].x,&corners[2].y);
R.Set(gdi_text_rect.left-gdi_gap,gdi_text_rect.top-gdi_gap,0.0);
ray.from = gdi_to_world*R; ray.to = ray.from + vp_zaxis;
P = ( ON_Intersect(ray,m_plane,&t) ) ? ray.PointAt(t) : ray.from;
m_plane.ClosestPointTo(P,&corners[3].x,&corners[3].y);
// orient projected rect so it is counter-clockwise
OrientRectHelper(corners);
aa0 = a0;
aa1 = a1;
P.Set(cos(a0)*m_radius,sin(a0)*m_radius,0.0);
R.Set(cos(a1)*m_radius,sin(a1)*m_radius,0.0);
for ( i = 0; i < 4; i++ )
{
N.x = (corners[i].y-corners[(i+1)%4].y);
N.y = (corners[(i+1)%4].x-corners[i].x);
if ( !N.Unitize() )
continue;
if ( (P.x - corners[i].x)*N.x + (P.y - corners[i].y)*N.y < 0.0 )
{
// end point not in text box
aa0 = ON_UNSET_VALUE;
}
if ( (R.x - corners[i].x)*N.x + (R.y - corners[i].y)*N.y < 0.0 )
{
// start point not in text box
aa1 = ON_UNSET_VALUE;
}
}
if ( ON_UNSET_VALUE == aa0 )
aa0 = aa1;
else if ( ON_UNSET_VALUE == aa1 )
aa1 = aa0;
r1 = corners[3].Length() - m_radius;
ray.to.x = corners[3].x/m_radius; ray.to.y = corners[3].y/m_radius;
ray.to.z = ray.from.z = 0.0;
for ( i = 0; i < 4; i++ )
{
r0 = r1;
r1 = corners[i].Length() - m_radius;
ray.from = ray.to;
ray.to.x = corners[i].x/m_radius; ray.to.y = corners[i].y/m_radius;
if ( r0 < 0.0 && r1 < 0.0 )
{
continue; // ray is inside circle
}
if ( r0 > 0.0 && r1 > 0.0 )
{
if ( !ray.ClosestPointTo(ON_3dPoint::Origin,&t ) )
continue;
R = ray.PointAt(t);
if ( R.x*R.x + R.y*R.y >= 1.0 )
continue; // ray is outside circle
}
xrc = 0;
if ( 0.0 == r0 )
tt[xrc++] = 0.0;
if ( 0.0 == r1 )
tt[xrc++] = 1.0;
if ( 0 == xrc )
xrc = ON_Intersect(ray,circle,&tt[0],c[0],&tt[1],c[1]);
if ( xrc < 1 || xrc > 2 )
continue; // ray does not intersect circle;
for ( xi = 0; xi < xrc; xi++ )
{
if ( tt[xi] < 0.0 || tt[xi] > 1.0 )
continue; // intersection point not on segment
P = ray.PointAt(tt[xi]);
if ( 0.0 == P.x && 0.0 == P.y )
continue; // bogus
aa = atan2(P.y,P.x);
if ( aa < a0 ) aa += 2.0*ON_PI; else if ( aa > a1 ) aa -= 2.0*ON_PI;
if ( aa < a0 || aa > a1 )
{
continue;
}
if ( ON_UNSET_VALUE == aa0 )
aa0 = aa1 = aa;
else if ( aa < aa0 )
aa0 = aa;
else if ( aa > aa1 )
aa1 = aa;
}
}
if ( ON_UNSET_VALUE != aa0 && ON_UNSET_VALUE != aa1
&& a0 <= aa0 && aa0 < aa1 && aa1 <= a1 )
{
t = arrow_angle;
if ( aa0 < a0+t && aa1 > a1-t )
{
// text box hits both arrowheads
// 2 arc segments, arrowheads outside
a[0] = a0;
a[1] = a0 - arrow_angle;
a[2] = a1 + arrow_angle;
a[3] = a1;
a[4] = a0;
a[5] = a1;
if( dimextension_angle != 0.0)
{
a[0] += dimextension_angle;
a[3] -= dimextension_angle;
}
bInside = false;
rc = 2;
}
else
{
if ( aa0 < a0+t ) aa0 = a0+t;
if ( aa1 > a1-t ) aa1 = a1-t;
if ( a0 < aa0 && aa0 < aa1 && aa1 < a1 )
{
// clip arc to text rectangle
// 2 arc segments, arrowheads inside
a[0] = a0;
a[1] = aa0;
a[2] = aa1;
a[3] = a1;
a[4] = a0;
a[5] = a1;
if( dimextension_angle != 0.0)
{
a[0] -= dimextension_angle;
a[3] += dimextension_angle;
}
bInside = true;
rc = 2;
}
else
{
// nasty case - don't bother clipping
// 1 segment, arrows inside
a[0] = a0;
a[1] = a1;
a[2] = a0;
a[3] = a1;
a[4] = a0;
a[5] = a1;
if( dimextension_angle != 0.0)
{
a[0] -= dimextension_angle;
a[1] += dimextension_angle;
}
bInside = true;
rc = 1;
}
}
}
else
{
// 1 segment, arrows inside
a[0] = a0;
a[1] = a1;
a[2] = a0;
a[3] = a1;
a[4] = a0;
a[5] = a1;
if( dimextension_angle != 0.0)
{
a[0] -= dimextension_angle;
a[1] += dimextension_angle;
}
bInside = true;
rc = 1;
}
}
else if (ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kAboveLine == textdisplay || m_userpositionedtext)
{
// 1 segment, arrows inside
a[0] = a0;
a[1] = a1;
a[2] = a0;
a[3] = a1;
a[4] = a0;
a[5] = a1;
if( dimextension_angle != 0.0)
{
a[0] -= dimextension_angle;
a[1] += dimextension_angle;
}
bInside = true;
rc = 1;
}
else if (ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kInLine == textdisplay)
{
// 2 segments, arrows inside
t = 0.5*((a1-a0) - textangle);
a[0] = a0;
a[1] = a0+t;
a[2] = a1-t;
a[3] = a1;
a[4] = a0;
a[5] = a1;
if( dimextension_angle != 0.0)
{
a[0] -= dimextension_angle;
a[3] += dimextension_angle;
}
bInside = true;
rc = 2;
}
return rc;
}
double ON_OBSOLETE_V5_DimAngular::DimpointOffset(int index) const
{
const ON_AngularDimension2Extra* pDE = ON_AngularDimension2Extra::AngularDimensionExtra(this);
if(pDE != 0)
return pDE->DimpointOffset(index);
return -1.0;
}
void ON_OBSOLETE_V5_DimAngular::SetDimpointOffset(int index, double offset)
{
ON_AngularDimension2Extra* pDE = ON_AngularDimension2Extra::AngularDimensionExtra(this);
if(pDE != 0)
pDE->SetDimpointOffset(index, offset);
}
//----- ON_OBSOLETE_V5_DimOrdinate -----------------------------------------
ON_OBSOLETE_V5_DimOrdinate::ON_OBSOLETE_V5_DimOrdinate()
{
m_type = ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimOrdinate;
SetTextValue(DefaultText());
SetTextFormula(0);
m_direction = -1; // undetermined direction
m_points.Reserve(ON_OBSOLETE_V5_DimOrdinate::dim_pt_count);
m_points.SetCount(ON_OBSOLETE_V5_DimOrdinate::dim_pt_count);
m_points.Zero();
m_kink_offset_0 = ON_UNSET_VALUE;
m_kink_offset_1 = ON_UNSET_VALUE;
}
ON_OBSOLETE_V5_DimOrdinate::~ON_OBSOLETE_V5_DimOrdinate()
{
}
bool ON_OBSOLETE_V5_DimOrdinate::Transform( const ON_Xform& xform )
{
bool rc = xform.IsIdentity();
if ( !rc)
{
return ON_OBSOLETE_V5_Annotation::Transform(xform);
}
return rc;
}
ON_2dPoint ON_OBSOLETE_V5_DimOrdinate::Dim2dPoint( int point_index, double default_offset) const
{
ON_2dPoint p2( ON_UNSET_VALUE, ON_UNSET_VALUE);
int dir = m_direction;
if( dir == -1 && ( point_index == offset_pt_0 || point_index == offset_pt_1))
{
if( fabs( m_points[definition_pt_index].y - m_points[leader_end_pt_index].y) >
fabs( m_points[definition_pt_index].x - m_points[leader_end_pt_index].x))
dir = 0;
else
dir = 1;
}
if( point_index >= 0 && point_index < dim_pt_count && m_points.Count() == dim_pt_count)
{
p2 = m_points[point_index];
}
else if( point_index == text_pivot_pt)
{
// ON_3dPoint::UnsetPoint
}
else if( point_index == offset_pt_0)
{
double offset;
if( m_kink_offset_0 == ON_UNSET_VALUE)
offset = default_offset;
else
offset = m_kink_offset_0;
if( dir == x)
{
p2 = m_points[leader_end_pt_index];
if( p2.y > m_points[definition_pt_index].y)
p2.y -= offset;
else
p2.y += offset;
}
else if( dir == y)
{
p2 = m_points[leader_end_pt_index];
if( p2.x > m_points[definition_pt_index].x)
p2.x -= offset;
else
p2.x += offset;
}
}
else if( point_index == offset_pt_1)
{
double offset0;
if( m_kink_offset_0 == ON_UNSET_VALUE)
offset0 = default_offset;
else
offset0 = m_kink_offset_0;
double offset1;
if( m_kink_offset_1 == ON_UNSET_VALUE)
offset1 = default_offset;
else
offset1 = m_kink_offset_1;
if( dir == x)
{
p2.x = m_points[definition_pt_index].x;
if( m_points[leader_end_pt_index].y > m_points[definition_pt_index].y)
p2.y = m_points[leader_end_pt_index].y - offset0 - offset1;
else
p2.y = m_points[leader_end_pt_index].y + offset0 + offset1;
}
else if( dir == y)
{
p2.y = m_points[definition_pt_index].y;
if( m_points[leader_end_pt_index].x > m_points[definition_pt_index].x)
p2.x = m_points[leader_end_pt_index].x - offset0 - offset1;
else
p2.x = m_points[leader_end_pt_index].x + offset0 + offset1;
}
}
return p2;
}
ON_3dPoint ON_OBSOLETE_V5_DimOrdinate::Dim3dPoint( int point_index, double default_offset) const
{
ON_2dPoint p2 = Dim2dPoint(point_index, default_offset);
return (ON_UNSET_VALUE == p2.x) ? ON_3dPoint::UnsetPoint : m_plane.PointAt(p2.x,p2.y);
}
bool ON_OBSOLETE_V5_DimOrdinate::IsValid( ON_TextLog* text_log) const
{
if ( m_type != ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimOrdinate)
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimOrdinate - m_type != ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimOrdinate.\n");
}
return false;
}
if ( !ON_OBSOLETE_V5_Annotation::IsValid( text_log ))
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimOrdinate - invalid ON_OBSOLETE_V5_Annotation base class.\n");
}
return false;
}
if ( m_points.Count() != 2 )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_DimOrdinate - m_points.Count() = %d (should be 2).\n",m_points.Count());
}
return false;
}
return true;
}
bool ON_OBSOLETE_V5_DimOrdinate::Write( ON_BinaryArchive& file ) const
{
// put the entire ON_OBSOLETE_V5_DimOrdinate in a chunk so we can
// add fields without breaking the file IO for old product.
bool rc = file.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,1);
if (rc)
{
rc = file.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
if (rc)
{
// As of 18 October 2007, the following comment is out of date.
// But, we still need to write this "extra" chunk so we don't
// break V4 file writing.
//
// The output of ON_OBSOLETE_V5_Annotation::Write must be wrapped
// in an additional chunk because it does not put
// itself in a chunk. If you don't put it in a chunk,
// the versioning in the ON_OBSOLETE_V5_Annotation::Write is useless and
// will cause serious IO bugs if fields are ever added.
rc = ON_OBSOLETE_V5_Annotation::Write( file) ? true : false;
if (!file.EndWrite3dmChunk() )
rc = false;
}
if (rc)
rc = file.WriteInt( m_direction);
// kink offsets, ver 1.1 added 2-4-06
if (rc)
rc = file.WriteDouble( m_kink_offset_0);
if (rc)
rc = file.WriteDouble( m_kink_offset_1);
// end of ON_OBSOLETE_V5_DimOrdinate chunk
if (!file.EndWrite3dmChunk() )
rc = false;
}
return rc;
}
bool ON_OBSOLETE_V5_DimOrdinate::Read( ON_BinaryArchive& file )
{
int major_version=0, minor_version=0;
bool rc = file.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
if (rc)
{
if ( 1 != major_version )
{
rc = false;
}
else
{
int submajor_version=0, subminor_version=0;
// subchunk wraps ON_OBSOLETE_V5_Annotation field so this
// function won't break if ON_OBSOLETE_V5_Annotation changes.
rc = file.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&submajor_version,&subminor_version);
if (rc)
{
if ( 1 != submajor_version )
rc = false;
else
{
rc = ON_OBSOLETE_V5_Annotation::Read( file) ? true : false;
}
if ( !file.EndRead3dmChunk() )
rc = false;
}
if( rc)
rc = file.ReadInt( &m_direction);
if( minor_version > 0)
{
if( rc)
rc = file.ReadDouble( &m_kink_offset_0);
if( rc)
rc = file.ReadDouble( &m_kink_offset_1);
}
}
if (!file.EndRead3dmChunk())
rc = false;
}
return rc;
}
double ON_OBSOLETE_V5_DimOrdinate::NumericValue() const
{
if( m_direction == 0)
return m_points[1].x - m_points[0].x;
else
return m_points[1].y - m_points[0].y;
}
int ON_OBSOLETE_V5_DimOrdinate::StyleIndex() const
{
return ON_OBSOLETE_V5_Annotation::V5_3dmArchiveDimStyleIndex();
}
void ON_OBSOLETE_V5_DimOrdinate::SetStyleIndex( int i)
{
ON_OBSOLETE_V5_Annotation::SetV5_3dmArchiveDimStyleIndex( i);
}
bool ON_OBSOLETE_V5_DimOrdinate::GetBBox(
double* boxmin,
double* boxmax,
bool bGrowBox
) const
{
ON_BoundingBox bbox;
if ( bGrowBox )
{
bbox.m_min.x = boxmin[0];
bbox.m_min.y = boxmin[1];
bbox.m_min.z = boxmin[2];
bbox.m_max.x = boxmax[0];
bbox.m_max.y = boxmax[1];
bbox.m_max.z = boxmax[2];
if ( !bbox.IsValid() )
{
bbox.Destroy();
bGrowBox = false;
}
}
if( m_points.Count() == 2)
{
ON_3dPointArray P( 2);
P.Append( m_plane.PointAt( m_points[0].x, m_points[0].y));
P.Append( m_plane.PointAt( m_points[1].x, m_points[1].y));
bGrowBox = P.GetBBox(&bbox.m_min.x, &bbox.m_max.x, bGrowBox);
}
if ( bGrowBox )
{
boxmin[0] = bbox.m_min.x;
boxmin[1] = bbox.m_min.y;
boxmin[2] = bbox.m_min.z;
boxmax[0] = bbox.m_max.x;
boxmax[1] = bbox.m_max.y;
boxmax[2] = bbox.m_max.z;
}
return bGrowBox;
}
bool ON_OBSOLETE_V5_DimOrdinate::GetTightBoundingBox( ON_BoundingBox& tight_bbox,
bool bGrowBox,
const ON_Xform* xform) const
{
if( m_points.Count() == 2)
{
ON_3dPointArray P(2);
P.Append( m_plane.PointAt( m_points[0].x, m_points[0].y));
P.Append( m_plane.PointAt( m_points[1].x, m_points[1].y));
if ( P.GetTightBoundingBox( tight_bbox, bGrowBox, xform))
bGrowBox = true;
}
else if( bGrowBox && !tight_bbox.IsValid())
{
tight_bbox.Destroy();
bGrowBox = false;
}
return( 0 != bGrowBox);
}
int ON_OBSOLETE_V5_DimOrdinate::ImpliedDirection() const
{
int direction = -1;
const ON_2dPoint& p0 = m_points[definition_pt_index];
const ON_2dPoint& p1 = m_points[leader_end_pt_index];
if( fabs( p1.x - p0.x) <= fabs( p1.y - p0.y))
direction = 0; // measures along x axis
else
direction = 1; // measures along y axis
return direction;
}
int ON_OBSOLETE_V5_DimOrdinate::Direction() const
{
return m_direction;
}
void ON_OBSOLETE_V5_DimOrdinate::SetDirection( int direction)
{
m_direction = direction;
}
const wchar_t* ON_OBSOLETE_V5_DimOrdinate::DefaultText() { return L"<>"; }
double ON_OBSOLETE_V5_DimOrdinate::KinkOffset( int index) const
{
if( index == 0)
return m_kink_offset_0;
else if( index == 1)
return m_kink_offset_1;
else
return ON_UNSET_VALUE;
}
void ON_OBSOLETE_V5_DimOrdinate::SetKinkOffset( int index, double offset)
{
if( index == 0)
m_kink_offset_0 = offset;
else if( index == 1)
m_kink_offset_1 = offset;
}
void ON_OBSOLETE_V5_DimOrdinate::CalcKinkPoints( ON_2dPoint p0, ON_2dPoint p1,
int direction, double default_offset,
ON_2dPoint& k0, ON_2dPoint& k1) const
{
double offset0 = KinkOffset( 0);
double offset1 = KinkOffset( 1);
// if these haven't been set by dragging the offset points
// use 2*textheight
if( offset0 == ON_UNSET_VALUE)
offset0 = default_offset;
if( offset1 == ON_UNSET_VALUE)
offset1 = default_offset;
if( p0[1-direction] > p1[1-direction])
{
offset0 = -offset0;
offset1 = -offset1;
}
//double d = fabs( p0[1-direction] - p1[1-direction]);
if( direction == 0)
{
//if( d - fabs( offset0) > default_offset)
//{
k1.x = p0.x;
k1.y = p1.y - offset0 - offset1;
//}
//else
//{
// k1.x = p0.x;
// k1.y = p1.y + offset0 - offset1;
//}
k0.x = p1.x;
k0.y = p1.y - offset0;
}
else
{
//if( d - fabs( offset0) > default_offset)
//{
k1.x = p1.x - offset0 - offset1;
k1.y = p0.y;
//}
//else
//{
// k1.x = p1.x + offset0 - offset1;
// k1.y = p0.y;
//}
k0.x = p1.x - offset0;
k0.y = p1.y;
}
}
//----- ON_OBSOLETE_V5_TextObject -----------------------------------------------
ON_OBSOLETE_V5_TextObject::ON_OBSOLETE_V5_TextObject()
{
m_type = ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtTextBlock;
m_textdisplaymode = ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kNormal;
}
ON_OBSOLETE_V5_TextObject::~ON_OBSOLETE_V5_TextObject()
{
}
bool ON_OBSOLETE_V5_TextObject::IsValid( ON_TextLog* text_log ) const
{
if ( m_type != ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtTextBlock )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_TextObject - m_type != ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtTextBlock\n");
}
return false;
}
// 05 March 2009 S. Baer
// Text blocks with no "printable" characters are considered invalid. Any
// character with a value greater than 32 (the value of space) is "printable."
int count = m_usertext.Length();
bool bValidText = false;
for( int i=0; i<count; i++ )
{
wchar_t c = m_usertext[i];
// all characters <= space are nonprintable
if( c > L' ' )
{
bValidText = true;
break;
}
}
// 9 Oct 2010 S. Baer
// With the addition of text formulas, the user text can be 0 length
if( !bValidText && count<1 )
{
const wchar_t* formula = TextFormula();
if( formula && formula[0] )
bValidText = true;
}
if( !bValidText )
{
if( text_log )
{
text_log->Print("ON_OBSOLETE_V5_TextObject - m_usertext does not contain printable characters.\n");
}
return false;
}
if ( !ON_OBSOLETE_V5_Annotation::IsValid( text_log ))
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_TextObject - invalid ON_OBSOLETE_V5_Annotation base class.\n");
}
return false;
}
if ( 0 != m_points.Count() )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_TextObject - m_points.Count() = %d (should be 0)\n", m_points.Count() );
}
return false;
}
return true;
}
bool ON_OBSOLETE_V5_TextObject::Write(ON_BinaryArchive& archive) const
{
// 18 October 2007 Dale Lear
// I added the chunk wrapping so V5 and future versions can
// add IO support for information specific to ON_OBSOLETE_V5_TextObject
// V4 did not have a ON_OBSOLETE_V5_TextObject::Write and simply called
// ON_OBSOLETE_V5_Annotation::Write.
bool rc = false;
bool bInChunk = (archive.Archive3dmVersion() >= 5);
if ( bInChunk )
{
rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
if ( !rc )
return false;
}
else
{
rc = true;
}
while(rc)
{
rc = ON_OBSOLETE_V5_Annotation::Write(archive)?true:false;
if (!rc) break;
if ( !bInChunk )
break;
// To write new fields, increment minor version number
// and write values here. Ask Dale Lear for help.
break;
}
if ( bInChunk )
{
if (!archive.EndWrite3dmChunk())
rc = false;
}
return rc;
}
bool ON_OBSOLETE_V5_TextObject::Read(ON_BinaryArchive& archive)
{
// 18 October 2007 Dale Lear
// I added the chunk wrapping so V5 and future versions can
// add IO support for information specific to ON_OBSOLETE_V5_TextObject
int major_version = 0;
int minor_version = 0;
bool rc = false;
bool bInChunk = (archive.Archive3dmVersion() >= 5 && archive.ArchiveOpenNURBSVersion() >= 200710180);
if ( bInChunk )
{
rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
if ( !rc )
return false;
}
else
{
rc = true;
}
while(rc)
{
rc = ON_OBSOLETE_V5_Annotation::Read(archive)?true:false;
if (!rc) break;
if ( !bInChunk || minor_version <= 0 )
break;
// read future addition here
break;
}
if ( bInChunk )
{
// To read new ON_OBSOLETE_V5_TextObject specific additions,
// examine the minor version number and read the information
// here. Please ask Dale Lear for help.
if ( !archive.EndRead3dmChunk() )
rc = false;
}
return rc;
}
bool ON_OBSOLETE_V5_TextObject::GetBBox(
double* boxmin,
double* boxmax,
bool bGrowBox
) const
{
ON_BoundingBox bbox;
if ( bGrowBox )
{
bbox.m_min.x = boxmin[0];
bbox.m_min.y = boxmin[1];
bbox.m_min.z = boxmin[2];
bbox.m_max.x = boxmax[0];
bbox.m_max.y = boxmax[1];
bbox.m_max.z = boxmax[2];
if ( !bbox.IsValid() )
{
bbox.Destroy();
bGrowBox = false;
}
}
if ( 1 == m_points.Count() )
{
ON_2dPoint uv = m_points[0];
bbox.Set( m_plane.PointAt(uv.x,uv.y), bGrowBox );
bGrowBox = true;
}
else if ( 0 == m_points.Count() )
{
bbox.Set( m_plane.origin, bGrowBox );
bGrowBox = true;
}
if ( bGrowBox )
{
boxmin[0] = bbox.m_min.x;
boxmin[1] = bbox.m_min.y;
boxmin[2] = bbox.m_min.z;
boxmax[0] = bbox.m_max.x;
boxmax[1] = bbox.m_max.y;
boxmax[2] = bbox.m_max.z;
}
return bGrowBox;
}
bool ON_OBSOLETE_V5_TextObject::GetTightBoundingBox(
ON_BoundingBox& tight_bbox,
bool bGrowBox,
const ON_Xform* xform
) const
{
if ( 1 == m_points.Count() )
{
ON_3dPointArray P(1);
P.Append( m_plane.PointAt(m_points[0].x,m_points[0].y) );
if ( P.GetTightBoundingBox( tight_bbox, bGrowBox, xform ) )
bGrowBox = true;
}
else if ( bGrowBox && !tight_bbox.IsValid() )
{
tight_bbox.Destroy();
bGrowBox = false;
}
return (0!=bGrowBox);
}
bool ON_OBSOLETE_V5_TextObject::Transform( const ON_Xform& xform )
{
// Dale Lear - this override fixes RR 11114 by correctly
// handling non uniform scaling.
bool rc = xform.IsIdentity();
if ( !rc)
{
ON_Plane xformed_plane = m_plane;
rc = xformed_plane.Transform(xform);
if (rc)
rc = ON_Geometry::Transform(xform)?true:false;
if (rc)
{
ON_3dPoint P0 = xform*m_plane.origin;
ON_3dPoint P1 = xform*(m_plane.origin + m_plane.xaxis);
double s = P0.DistanceTo(P1);
if ( s <= ON_ZERO_TOLERANCE )
{
P1 = xform*(m_plane.origin + m_plane.yaxis);
s = P0.DistanceTo(P1);
}
m_plane = xformed_plane;
if ( s > ON_ZERO_TOLERANCE && fabs(s-1.0) > ON_SQRT_EPSILON )
{
s *= m_textheight;
if ( s > ON_SQRT_EPSILON )
m_textheight = s;
}
}
}
return rc;
}
void ON_OBSOLETE_V5_TextObject::SetJustification( unsigned int justification)
{
m_justification = justification;
}
unsigned int ON_OBSOLETE_V5_TextObject::Justification() const
{
return m_justification;
}
bool ON_OBSOLETE_V5_TextObject::DrawTextMask() const
{
const ON_OBSOLETE_V5_TextExtra* pTE = ON_OBSOLETE_V5_TextExtra::TextExtension(this, false);
if(pTE)
return pTE->DrawTextMask();
else
return false;
}
void ON_OBSOLETE_V5_TextObject::SetDrawTextMask(bool bDraw)
{
ON_OBSOLETE_V5_TextExtra* pTE = ON_OBSOLETE_V5_TextExtra::TextExtension(this, true);
if(pTE)
pTE->SetDrawTextMask(bDraw);
}
int ON_OBSOLETE_V5_TextObject::MaskColorSource() const
{
const ON_OBSOLETE_V5_TextExtra* pTE = ON_OBSOLETE_V5_TextExtra::TextExtension(this, false);
if(pTE)
return pTE->MaskColorSource();
else
return 0;
}
void ON_OBSOLETE_V5_TextObject::SetMaskColorSource(int source)
{
ON_OBSOLETE_V5_TextExtra* pTE = ON_OBSOLETE_V5_TextExtra::TextExtension(this, true);
if(pTE)
pTE->SetMaskColorSource(source);
}
ON_Color ON_OBSOLETE_V5_TextObject::MaskColor() const
{
const ON_OBSOLETE_V5_TextExtra* pTE = ON_OBSOLETE_V5_TextExtra::TextExtension(this, false);
if(pTE)
return pTE->MaskColor();
else
return 0;
}
void ON_OBSOLETE_V5_TextObject::SetMaskColor(ON_Color color)
{
ON_OBSOLETE_V5_TextExtra* pTE = ON_OBSOLETE_V5_TextExtra::TextExtension(this, true);
if(pTE)
pTE->SetMaskColor(color);
}
double ON_OBSOLETE_V5_TextObject::MaskOffsetFactor() const
{
const ON_OBSOLETE_V5_TextExtra* pTE = ON_OBSOLETE_V5_TextExtra::TextExtension(this, false);
if(pTE)
return pTE->MaskOffsetFactor();
else
return 0;
}
void ON_OBSOLETE_V5_TextObject::SetMaskOffsetFactor(double offset)
{
ON_OBSOLETE_V5_TextExtra* pTE = ON_OBSOLETE_V5_TextExtra::TextExtension(this, true);
if(pTE)
pTE->SetMaskOffsetFactor(offset);
}
bool ON_OBSOLETE_V5_TextObject::AnnotativeScaling() const
{
return m_annotative_scale;
}
void ON_OBSOLETE_V5_TextObject::SetAnnotativeScaling(bool b)
{
m_annotative_scale = b;
}
//----- ON_OBSOLETE_V5_Leader ------------------------------------------
ON_OBSOLETE_V5_Leader::ON_OBSOLETE_V5_Leader()
{
m_type = ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader;
m_textdisplaymode = ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kInLine;
}
ON_OBSOLETE_V5_Leader::~ON_OBSOLETE_V5_Leader()
{
}
bool ON_OBSOLETE_V5_Leader::IsValid( ON_TextLog* text_log ) const
{
if ( m_type != ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_Leader - m_type != ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader\n");
}
return false;
}
if ( !ON_OBSOLETE_V5_Annotation::IsValid( text_log ))
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_Leader - invalid ON_OBSOLETE_V5_Annotation base class.\n");
}
return false;
}
if ( m_points.Count() < 2 )
{
if ( text_log )
{
text_log->Print("ON_OBSOLETE_V5_Leader - m_points.Count() = %d (should be >= 2)\n", m_points.Count() );
}
return false;
}
return true;
}
bool ON_OBSOLETE_V5_Leader::Write(ON_BinaryArchive& archive) const
{
// 18 October 2007 Dale Lear
// I added the chunk wrapping so V5 and future versions can
// add IO support for information specific to ON_OBSOLETE_V5_Leader
// V4 did not have a ON_OBSOLETE_V5_Leader::Write and simply called
// ON_OBSOLETE_V5_Leader::Write.
bool rc = false;
bool bInChunk = (archive.Archive3dmVersion() >= 5);
if ( bInChunk )
{
rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
if ( !rc )
return false;
}
else
{
rc = true;
}
while(rc)
{
rc = ON_OBSOLETE_V5_Annotation::Write(archive)?true:false;
if (!rc) break;
if ( !bInChunk )
break;
// To write new fields, increment minor version number
// and write values here. Ask Dale Lear for help.
break;
}
if ( bInChunk )
{
if (!archive.EndWrite3dmChunk())
rc = false;
}
return rc;
}
bool ON_OBSOLETE_V5_Leader::Read(ON_BinaryArchive& archive)
{
// 18 October 2007 Dale Lear
// I added the chunk wrapping so V5 and future versions can
// add IO support for information specific to ON_OBSOLETE_V5_Leader
int major_version = 0;
int minor_version = 0;
bool rc = false;
bool bInChunk = (archive.Archive3dmVersion() >= 5 && archive.ArchiveOpenNURBSVersion() >= 200710180);
if ( bInChunk )
{
rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
if ( !rc )
return false;
}
else
{
rc = true;
}
while(rc)
{
rc = ON_OBSOLETE_V5_Annotation::Read(archive)?true:false;
if (!rc) break;
if ( !bInChunk || minor_version <= 0 )
break;
// read future addition here
break;
}
if ( bInChunk )
{
if ( !archive.EndRead3dmChunk() )
rc = false;
}
return rc;
}
bool ON_OBSOLETE_V5_Leader::GetBBox(
double* boxmin,
double* boxmax,
bool bGrowBox
) const
{
ON_BoundingBox bbox;
if ( bGrowBox )
{
bbox.m_min.x = boxmin[0];
bbox.m_min.y = boxmin[1];
bbox.m_min.z = boxmin[2];
bbox.m_max.x = boxmax[0];
bbox.m_max.y = boxmax[1];
bbox.m_max.z = boxmax[2];
if ( !bbox.IsValid() )
{
bbox.Destroy();
bGrowBox = false;
}
}
const int point_count = m_points.Count();
if ( point_count > 0 )
{
ON_3dPointArray P(point_count);
int i;
for ( i = 0; i < point_count; i++ )
{
ON_2dPoint uv = m_points[i];
P.Append( m_plane.PointAt(uv.x,uv.y));
}
if ( P.GetBoundingBox(bbox,bGrowBox?true:false) )
bGrowBox = true;
}
if ( bGrowBox )
{
boxmin[0] = bbox.m_min.x;
boxmin[1] = bbox.m_min.y;
boxmin[2] = bbox.m_min.z;
boxmax[0] = bbox.m_max.x;
boxmax[1] = bbox.m_max.y;
boxmax[2] = bbox.m_max.z;
}
return bGrowBox;
}
bool ON_OBSOLETE_V5_Leader::GetTightBoundingBox(
ON_BoundingBox& tight_bbox,
bool bGrowBox,
const ON_Xform* xform
) const
{
const int point_count = m_points.Count();
if ( point_count >= 2 )
{
ON_3dPointArray P(point_count);
int i;
for ( i = 0; i < point_count; i++ )
{
ON_2dPoint uv = m_points[i];
P.Append( m_plane.PointAt(uv.x,uv.y));
}
if ( P.GetTightBoundingBox( tight_bbox, bGrowBox, xform ) )
bGrowBox = true;
}
else if ( bGrowBox && !tight_bbox.IsValid() )
{
tight_bbox.Destroy();
bGrowBox = false;
}
return (0!=bGrowBox);
}
ON_2dPoint ON_OBSOLETE_V5_Leader::Dim2dPoint(
int point_index
) const
{
ON_2dPoint p2;
int point_count = m_points.Count();
if ( point_index < 0 || point_count < 1 )
{
p2.x = p2.y = ON_UNSET_VALUE;
}
else
{
switch(point_index)
{
case arrow_pt_index:
p2 = m_points[0];
break;
case text_pivot_pt:
case tail_pt:
p2 = *m_points.Last();
break;
default:
if ( point_index < point_count )
{
p2 = m_points[point_index];
}
else
{
p2.x = p2.y = ON_UNSET_VALUE;
}
break;
}
}
return p2;
}
ON_3dPoint ON_OBSOLETE_V5_Leader::Dim3dPoint(
int point_index
) const
{
ON_2dPoint p2 = Dim2dPoint(point_index);
return (ON_UNSET_VALUE == p2.x) ? ON_3dPoint::UnsetPoint : m_plane.PointAt(p2.x,p2.y);
}
void ON_OBSOLETE_V5_Leader::AddPoint( const ON_2dPoint& point )
{
m_points.Append( point);
}
bool ON_OBSOLETE_V5_Leader::RemovePoint( int idx )
{
bool rc = true;
if( idx == -1) // -1 removes the last point
{
m_points.Remove();
}
else if( idx >= 0 && idx < m_points.Count())
{
m_points.Remove( idx);
}
else
{
rc = false;
}
return rc;
}
// April 22, 2010 Lowell - Added to support right justified text on left pointing leader tails rr64292
bool ON_OBSOLETE_V5_Leader::GetTextDirection( ON_2dVector& text_dir ) const
{
bool rc = false;
const int point_count = m_points.Count();
if ( point_count < 2 )
{
text_dir.Set(-1.0,0.0);
}
else
{
int i; // 20 June 2011 Fixed textdir for leaders with 2 points. rr86801
for(i = point_count-1; i >= 1; i--)
{
text_dir = m_points[point_count-1] - m_points[i-1];
if(text_dir.Unitize())
{
rc = true;
break;
}
text_dir.Set(-1.0,0.0);
}
}
return rc;
}
bool ON_OBSOLETE_V5_Leader::GetArrowHeadDirection( ON_2dVector& arrowhead_dir ) const
{
bool rc = false;
const int point_count = m_points.Count();
if ( point_count < 2 )
{
arrowhead_dir.Set(-1.0,0.0);
}
else
{
int i;
for ( i = 1; i < point_count; i++ )
{
arrowhead_dir = m_points[0] - m_points[i];
if ( arrowhead_dir.Unitize() )
{
rc = true;
break;
}
arrowhead_dir.Set(-1.0,0.0);
}
}
return rc;
}
bool ON_OBSOLETE_V5_Leader::GetArrowHeadTip( ON_2dPoint& arrowhead_tip ) const
{
bool rc = false;
switch( m_points.Count())
{
case 0:
arrowhead_tip.Set(0.0,0.0);
break;
case 1:
arrowhead_tip = m_points[0];
break;
default:
arrowhead_tip = m_points[0];
rc = true;
break;
}
return rc;
}
bool ON_OBSOLETE_V5_DimRadial::GetArrowHeadDirection( ON_2dVector& arrowhead_dir ) const
{
bool rc = false;
if ( m_points.Count() < 4 )
{
arrowhead_dir.Set(-1.0,0.0);
}
else
{
arrowhead_dir = m_points[1] - m_points[3];
if ( 0 == (rc=arrowhead_dir.Unitize()) )
{
arrowhead_dir = m_points[1] - m_points[2];
if ( 0 == (rc=arrowhead_dir.Unitize()) )
{
arrowhead_dir = m_points[0] - m_points[1];
rc = arrowhead_dir.Unitize();
}
}
}
return rc;
}
bool ON_OBSOLETE_V5_DimRadial::GetArrowHeadTip( ON_2dPoint& arrowhead_tip ) const
{
bool rc = false;
if ( m_points.Count() >= 2 )
{
arrowhead_tip = m_points[1];
rc = true;
}
else
{
arrowhead_tip.Set(0.0,0.0);
rc = false;
}
return rc;
}
// class ON_TextDot
//--------------------------------------------------------------------
ON_TextDot::ON_TextDot()
{}
ON_TextDot* ON_TextDot::CreateFromV2AnnotationTextDot(
const class ON_OBSOLETE_V2_TextDot& V2_text_dot,
const class ON_3dmAnnotationContext* annotation_context,
ON_TextDot* destination
)
{
ON_wString dot_text = V2_text_dot.m_text;
dot_text.TrimLeft();
dot_text.TrimRight();
ON_TextDot* text_dot
= (nullptr != destination)
? destination
: new ON_TextDot();
text_dot->SetPrimaryText(dot_text);
text_dot->SetCenterPoint(V2_text_dot.point);
return text_dot;
}
ON_TextDot::ON_TextDot(
ON_3dPoint center_point,
const wchar_t* primary_text,
const wchar_t* secondary_text
)
: m_center_point( center_point.IsValid() ? center_point : ON_3dPoint::UnsetPoint )
, m_primary_text(primary_text)
, m_secondary_text(secondary_text)
{
}
ON_TextDot::~ON_TextDot()
{}
void ON_TextDot::EmergencyDestroy()
{
m_center_point = ON_3dPoint::UnsetPoint;
m_primary_text.EmergencyDestroy();
m_secondary_text.EmergencyDestroy();
m_font_face.EmergencyDestroy();
m_height_in_points = ON_TextDot::DefaultHeightInPoints;
m_display_bits = 0;
}
bool ON_TextDot::IsValid(
ON_TextLog* text_log
) const
{
// 5/6/03 LW made dots with no text valid.
if ( !m_center_point.IsValid() )
{
if ( 0 != text_log )
{
text_log->Print("ON_TextDot::CenterPoint() is not valid\n");
}
return false;
}
return true;
}
void ON_TextDot::Dump( ON_TextLog& log) const
{
log.Print(L"Center: ");
log.Print( m_center_point);
log.Print(L"\n");
log.Print(L"Primary text: \"%ls\"\n", static_cast<const wchar_t*>(m_primary_text));
log.Print(L"Secondary text: \"%ls\"\n", static_cast<const wchar_t*>(m_secondary_text));
log.Print(L"Height in points: %d\n", m_height_in_points);
log.Print(L"Font face: \"%ls\"\n", static_cast<const wchar_t*>(m_font_face));
}
bool ON_TextDot::Write( ON_BinaryArchive& file) const
{
bool rc = false;
for (;;)
{
const int minor_version
= file.Archive3dmVersion() >= 60
? 1
: 0;
if (!file.Write3dmChunkVersion(1, minor_version))
break;
if (!file.WritePoint(m_center_point))
break;
if (!file.WriteInt(m_height_in_points))
break;
if (!file.WriteString(m_primary_text))
break;
if (!file.WriteString(m_font_face))
break;
// June 21, 2015
// Dale Lear cleaned this up so runtime bits and file format are independent.
// DO NOT modify this display_bits code for future bool values.
int display_bits = 0;
if ( AlwaysOnTop() )
display_bits |= 1;
if ( Transparent() )
display_bits |= 2;
if ( Bold() )
display_bits |= 4;
if (Italic() )
display_bits |= 8;
if (!file.WriteInt(display_bits))
break;
// DO NOT use display bits for future bool values
if (minor_version >= 1)
{
// version 1.1 fields June 21, 2015
if (!file.WriteString(m_secondary_text))
break;
}
rc = true;
break;
}
return rc;
}
bool ON_TextDot::Read( ON_BinaryArchive& file)
{
bool rc = false;
*this = ON_TextDot::Unset;
int major_version = 0;
int minor_version = 0;
while (file.Read3dmChunkVersion(&major_version, &minor_version))
{
if (1 != major_version)
break;
ON_3dPoint center_point;
if (!file.ReadPoint(center_point))
break;
SetCenterPoint(center_point);
int height;
if (!file.ReadInt(&height))
break;
SetHeightInPoints(height);
ON_wString str;
if (!file.ReadString( str))
break;
SetPrimaryText(str);
if (!file.ReadString( str))
break;
SetFontFace(str);
// June 21, 2015
// Dale Lear cleaned this up so runtime bits and file format are independent.
// DO NOT use display bits for future bool values
int display_bits = 0;
if (!file.ReadInt( &display_bits))
break;
SetAlwaysOnTop( 0 != (1 & display_bits) );
SetTransparent( 0 != (2 & display_bits) );
SetBold( 0 != (4 & display_bits) );
SetItalic( 0 != (8 & display_bits) );
// DO NOT use display bits for future bool values
if (minor_version >= 1)
{
// version 1.1 fields June 21, 2015
if (!file.ReadString(str))
break;
SetSecondaryText(str);
}
rc = true;
break;
}
return rc;
}
ON::object_type ON_TextDot::ObjectType() const
{
return ON::text_dot;
}
int ON_TextDot::Dimension() const
{
return 3;
}
bool ON_TextDot::GetBBox( double* box_min, double* box_max, bool grow_box /*= false*/) const
{
return ON_GetPointListBoundingBox( 3, 0, 1, 3, &m_center_point.x, box_min, box_max, grow_box?true:false );
}
bool ON_TextDot::Transform( const ON_Xform& xform)
{
TransformUserData( xform);
return ON_TransformPointList( 3, 0, 1, 3, &m_center_point.x, xform);
}
bool ON_TextDot::IsDeformable() const
{
return true;
}
bool ON_TextDot::MakeDeformable()
{
return true;
}
ON_3dPoint ON_TextDot::CenterPoint() const
{
return m_center_point;
}
void ON_TextDot::SetCenterPoint( ON_3dPoint center_point )
{
m_center_point = center_point;
}
int ON_TextDot::HeightInPoints() const
{
// in "points"
return m_height_in_points;
}
void ON_TextDot::SetHeightInPoints(
int height_in_points
)
{
if( height_in_points >= ON_TextDot::MinimumHeightInPoints )
m_height_in_points = height_in_points;
}
const wchar_t* ON_TextDot::PrimaryText() const
{
return static_cast< const wchar_t* >(m_primary_text);
}
const wchar_t* ON_TextDot::SecondaryText() const
{
return static_cast< const wchar_t* >(m_secondary_text);
}
static void SetDotText(
const wchar_t* dot_text,
bool bCRtoCRLF,
ON_wString& dot_string
)
{
if (nullptr != dot_text)
{
// strip leading white space
while ( dot_text[0] > 0 && dot_text[0] <= 0x20 )
dot_text++;
}
size_t len = ON_wString::Length(dot_text);
// strip trailing white space
while (len > 0 && dot_text[len-1] <= 0x20 && dot_text[len-1] > 0)
len--;
if( len > 0 )
{
wchar_t* buffer = (wchar_t*)onmalloc((2 * len + 1)*sizeof(wchar_t));
size_t j = 0;
for (size_t i = 0; i < len; i++)
{
if (bCRtoCRLF && '\r' == dot_text[i] && '\n' != dot_text[i+1])
{
// change \r to \r\n
buffer[j++] = '\r';
buffer[j++] = '\n';
}
else
{
buffer[j++] = dot_text[i];
}
}
buffer[j] = 0;
dot_string = buffer;
onfree(buffer);
}
else
{
dot_string = ON_wString::EmptyString;
}
}
void ON_TextDot::SetPrimaryText(const wchar_t* primary_dot_text)
{
SetDotText(primary_dot_text,true,m_primary_text);
}
void ON_TextDot::SetSecondaryText(const wchar_t* secondary_dot_text)
{
SetDotText(secondary_dot_text,true,m_secondary_text);
}
const wchar_t* ON_TextDot::FontFace() const
{
return
m_font_face.IsEmpty()
? ON_TextDot::DefaultFontFace
: static_cast< const wchar_t* >(m_font_face);
}
void ON_TextDot::SetFontFace( const wchar_t* font_face )
{
m_font_face = font_face;
m_font_face.TrimLeftAndRight();
}
static void SetDisplayBitsFromBool(
bool b,
unsigned int bit,
unsigned int& display_bits
)
{
if (b)
display_bits |= bit;
else
display_bits &= (~bit);
}
static bool DisplayBitsToBool(
unsigned int display_bits,
unsigned int bit
)
{
return (bit == (display_bits & bit) ? true : false);
}
void ON_TextDot::SetAlwaysOnTop(
bool bAlwaysOnTop
)
{
SetDisplayBitsFromBool(bAlwaysOnTop,1,m_display_bits);
}
bool ON_TextDot::AlwaysOnTop() const
{
return DisplayBitsToBool(m_display_bits,1);
}
void ON_TextDot::SetTransparent(
bool bTransparent
)
{
SetDisplayBitsFromBool(bTransparent,2,m_display_bits);
}
bool ON_TextDot::Transparent() const
{
return DisplayBitsToBool(m_display_bits,2);
}
void ON_TextDot::SetBold(
bool bBold
)
{
SetDisplayBitsFromBool(bBold,4,m_display_bits);
}
bool ON_TextDot::Bold() const
{
return DisplayBitsToBool(m_display_bits,4);
}
void ON_TextDot::SetItalic(bool bItalic)
{
SetDisplayBitsFromBool(bItalic,8,m_display_bits);
}
bool ON_TextDot::Italic() const
{
return DisplayBitsToBool(m_display_bits,8);
}
//////// deprecated functions /////////
const ON_3dPoint& ON_TextDot::Point() const
{
//Perform same functionality as CenterPoint
return m_center_point;
}
void ON_TextDot::SetPoint(const ON_3dPoint& point)
{
SetCenterPoint(point);
}
const wchar_t* ON_TextDot::TextString() const
{
return PrimaryText();
}
void ON_TextDot::SetTextString(const wchar_t* string)
{
SetPrimaryText(string);
}
////////////////////////////////////////
ON_OBSOLETE_V5_AnnotationText::ON_OBSOLETE_V5_AnnotationText()
{
memset(&m_rect,0,sizeof(m_rect));
}
ON_OBSOLETE_V5_AnnotationText::~ON_OBSOLETE_V5_AnnotationText()
{
}
ON_OBSOLETE_V5_AnnotationText& ON_OBSOLETE_V5_AnnotationText::operator=(const char* s)
{
SetText(s);
return *this;
}
ON_OBSOLETE_V5_AnnotationText& ON_OBSOLETE_V5_AnnotationText::operator=(const wchar_t* s)
{
SetText(s);
return *this;
}
void ON_OBSOLETE_V5_AnnotationText::SetText(const char* s)
{
ON_wString::operator=(s);
memset(&m_rect,0,sizeof(m_rect));
}
void ON_OBSOLETE_V5_AnnotationText::SetText(const wchar_t* s)
{
ON_wString::operator=(s);
memset(&m_rect,0,sizeof(m_rect));
}
bool ON_OBSOLETE_V5_Annotation::GetTextXform(
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& xform
) const
{
int gdi_height_of_I = font.FontMetrics().AscentOfI();
const double textheight = dimstyle ? dimstyle->TextHeight() : m_textheight;
double textgap = dimstyle ? dimstyle->TextGap() : 0.0;
const ON_INTERNAL_OBSOLETE::V5_TextDisplayMode textalignment
= dimstyle ? ON_INTERNAL_OBSOLETE::V5TextDisplayModeFromV6DimStyle(*dimstyle)
: ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kNormal;
const ON_3dVector cameraX = (vp) ? vp->CameraX() : m_plane.xaxis;
const ON_3dVector cameraY = (vp) ? vp->CameraY() : m_plane.yaxis;
if(dimstyle)
{
// - Oct 4, 07 LW Get correct text gap using
// multi-line tolerance text since GetTextXform doesn't do that.
if(
( ON_DimStyle::tolerance_format::Deviation == dimstyle->ToleranceFormat() || ON_DimStyle::tolerance_format::Limits == dimstyle->ToleranceFormat() )
&&
( Type() == ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear || Type() == ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAligned) )
textgap += textheight * 0.5;
}
return GetTextXform(
gdi_text_rect,
gdi_height_of_I,
textheight, textgap, textalignment,
dimscale,
cameraX, cameraY,
model_xform,
xform
);
}
static bool GetLeaderEndAndDirection( const ON_OBSOLETE_V5_Annotation* pAnn,
ON_2dPoint& E,
ON_2dVector& R )
{
bool rc = false;
ON_INTERNAL_OBSOLETE::V5_eAnnotationType ann_type = pAnn->m_type;
const ON_2dPointArray& ann_m_points = pAnn->m_points;
R.Set(1.0,0.0); // unit vector points to end
E.Set(0.0,0.0); // end point
if ( ann_m_points.Count() >= 4 && (ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter == ann_type || ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius == ann_type) )
{
E = ann_m_points[2]; // end of radial dimension
R = E - ann_m_points[3];
if ( !R.Unitize() )
{
R = E - ann_m_points[1];
if ( !R.Unitize() )
{
R = E - ann_m_points[0];
if ( !R.Unitize() )
{
R.Set(1.0,0.0);
}
}
}
rc = true;
}
else if ( ann_m_points.Count() >= 2 && ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader == ann_type )
{
int i;
E = *ann_m_points.Last();
for (i = ann_m_points.Count()-2; i >= 0; i-- )
{
R = E - ann_m_points[i];
if ( R.Unitize() )
{
break;
}
R.Set(1.0,0.0);
}
rc = true;
}
else if ( ann_m_points.Count() >= 2 && ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimOrdinate == ann_type )
{
E = ann_m_points[1];
int direction = (( ON_OBSOLETE_V5_DimOrdinate*)pAnn)->Direction();
if( direction == -1)
{
if( fabs( ann_m_points[1].x - ann_m_points[0].x)
<= fabs( ann_m_points[1].y - ann_m_points[0].y))
direction = 0;
else
direction = 1;
}
if( direction == 0)
R.Set( 0.0, ann_m_points[1].y - ann_m_points[0].y);
else
R.Set( ann_m_points[1].x - ann_m_points[0].x, 0.0);
if( !R.Unitize())
R.Set(1.0,0.0);
rc = true;
}
return rc;
}
// Oct 30, 07 - LW
// This function should not be used any longer
bool ON_OBSOLETE_V5_Annotation::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
{
ON_ERROR("This function should not be used. Use the version that takes a model transform argument.");
return false;
}
//const ON_OBSOLETE_V5_Annotation* ann = this;
//const ON_INTERNAL_OBSOLETE::V5_eAnnotationType ann_type = ann->m_type;
//if ( 0 == gdi_height_of_I )
//{
// // Default to height of Ariel 'I'
// gdi_height_of_I = (165*ON_Font::Constants::AnnotationFontCellHeight)/256;
//}
//if ( 0.0 == dimscale )
//{
// dimscale = 1.0;
//}
//dimstyle_textheight *= dimscale;
//dimstyle_textgap *= dimscale;
//double textheight = ( ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtTextBlock == ann_type )
// ? m_textheight*dimscale
// : dimstyle_textheight;
//if ( 0.0 == textheight )
// textheight = 1.0;
//ON_3dVector cameraZ = ON_CrossProduct( cameraX, cameraY );
//if ( fabs( 1.0 - cameraZ.Length() ) > ON_SQRT_EPSILON )
//{
// cameraZ.Unitize();
//}
//// This xform is a scale from Windows gdi coordinates
//// to annotation plane coordinates.
//const double gdi_to_plane_scale = textheight/gdi_height_of_I;
//ON_Xform gdi_to_plane(1.0);
//gdi_to_plane.m_xform[0][0] = gdi_to_plane_scale;
//gdi_to_plane.m_xform[1][1] = -gdi_to_plane_scale;
//// width and height of text line in Rhino units.
//const double text_line_width = gdi_to_plane_scale*(gdi_text_rect.right - gdi_text_rect.left);
////const double text_line_height = gdi_to_plane_scale*(gdi_text_rect.bottom - gdi_text_rect.top);
//if ( ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtTextBlock == ann_type )
//{
// // The orientation of the text is text blocks
// // does not depend on the view or text alignment
// // settings. The position and orientation of
// // the text in every other annotation depends on
// // the view and text alignment settings.
// //
// // It simplifies the code for the rest of the
// // annotation settings to quickly deal with text
// // blocks here.
// ON_Xform plane_to_world(1.0);
// plane_to_world.Rotation(ON_xy_plane,ann->m_plane);
// xform = plane_to_world*gdi_to_plane;
// return true;
//}
//// text_position_mode
//// 1 = linear, aligned, or anglular dimension
//// (dimension definition determines center point of text box)
//// 2 = radial, diameter, leader
//// (dimension definition determined end point of text box)
//int position_style = 0;
//switch( ann_type )
//{
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAligned:
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear:
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAngular:
// // dimension definition determines center point of text box
// position_style = 1;
// break;
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader:
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius:
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter:
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimOrdinate:
// // dimension definition determines end of text box
// position_style = 2;
// break;
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtTextBlock:
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtNothing:
// break;
//}
//// This translation puts the center of the fist line of text at
//// (0,0) in the annotation's plane.
//if ( ON::dtHorizontal != dimstyle_textalignment || 1 == position_style )
//{
// gdi_to_plane.m_xform[0][3] = -0.5*text_line_width;
// gdi_to_plane.m_xform[0][3] = -0.5*text_line_width;
//}
//gdi_to_plane.m_xform[1][3] = -0.5*textheight;
//if ( ON::dtHorizontal != dimstyle_textalignment )
//{
// if ( ((cameraZ*m_plane.zaxis) < -ON_SQRT_EPSILON) )
// {
// // Viewing dimension from the backside
// ON_Xform flip(1.0);
// switch ( position_style )
// {
// case 1: // ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear, ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAligned, ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAngular
// flip.m_xform[0][0] = -1.0;
// flip.m_xform[0][3] = gdi_text_rect.left + gdi_text_rect.right;
// break;
// case 2: // ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter, ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius, ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader
// flip.m_xform[1][1] = -1.0;
// flip.m_xform[1][3] = gdi_text_rect.top + gdi_text_rect.bottom;
// break;
// }
// gdi_to_plane = gdi_to_plane*flip;
// }
//}
//// text_centering_rotation rotates about the "center". Angular,
//// radial, and leader dimensions use this rotation.
//ON_2dVector text_centering_rotation(1.0,0.0);
//// text_centering_translation is a small translation deals with
//// text that is above or to the right of the "center" point.
//// It is no larger than dimstyle_gap + 1/2 the size of the
//// text's bounding box.
//ON_2dVector text_centering_translation(0.0,0.0);
//double x, y;
//if ( ON::dtHorizontal != dimstyle_textalignment )
//{
// if ( ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear == ann_type || ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAligned == ann_type )
// {
// if ( ON::dtAboveLine == dimstyle_textalignment )
// {
// text_centering_translation.y = 0.5*textheight+dimstyle_textgap;
// }
// y = ann->m_plane.yaxis*cameraY;
// x = -ann->m_plane.yaxis*cameraX;
// if ( fabs(y) <= ON_SQRT_EPSILON && fabs(x) > ON_SQRT_EPSILON )
// {
// y = x;
// }
// if ( y < 0.0 )
// {
// text_centering_translation.Reverse();
// text_centering_rotation.Reverse(); // rotate 180 degrees
// }
// }
// else if ( ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAngular == ann_type )
// {
// // This transform rotates the text in the annotation plane.
// const ON_OBSOLETE_V5_DimAngular* angular_dim = ON_OBSOLETE_V5_DimAngular::Cast(ann);
// if ( 0 != angular_dim )
// {
// double a = 0.5*angular_dim->m_angle;
// ON_2dVector R(cos(a),sin(a));
// a -= 0.5*ON_PI;
// text_centering_rotation.x = cos(a);
// text_centering_rotation.y = sin(a);
// ON_3dVector V = R.x*m_plane.xaxis + R.y*m_plane.yaxis;
// x = V*cameraX;
// y = V*cameraY;
// if ( fabs(y) <= ON_SQRT_EPSILON && fabs(x) > ON_SQRT_EPSILON )
// {
// y = -x;
// }
// if ( y < 0.0 )
// {
// text_centering_rotation.Reverse(); // add another 180 degrees of rotation
// }
// if ( ON::dtAboveLine == dimstyle_textalignment )
// {
// y = 0.5*textheight + dimstyle_textgap;
// text_centering_translation.x = -y*text_centering_rotation.y;
// text_centering_translation.y = y*text_centering_rotation.x;
// }
// }
// }
// else if ( ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter == ann_type
// || ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius == ann_type
// || ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader == ann_type
// || ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimOrdinate == ann_type)
// {
// ON_2dPoint E(0.0,0.0); // end point
// ON_2dVector R(1.0,0.0); // unit vector from penultimate point to end point
// GetLeaderEndAndDirection( this, E, R );
// text_centering_rotation = R;
// text_centering_translation = (dimstyle_textgap + 0.5*text_line_width)*text_centering_rotation;
// ON_3dVector V = text_centering_rotation.x*m_plane.xaxis + text_centering_rotation.y*m_plane.yaxis;
// x = V*cameraX;
// y = V*cameraY;
// if ( fabs(x) <= ON_SQRT_EPSILON && fabs(y) > ON_SQRT_EPSILON )
// {
// x = y;
// }
// if ( x < 0.0 )
// {
// text_centering_rotation.Reverse(); // rotate 180 degrees
// }
// }
//}
//ON_Xform text_centering_xform(1.0);
//text_centering_xform.m_xform[0][0] = text_centering_rotation.x;
//text_centering_xform.m_xform[0][1] = -text_centering_rotation.y;
//text_centering_xform.m_xform[1][0] = text_centering_rotation.y;
//text_centering_xform.m_xform[1][1] = text_centering_rotation.x;
//// Since the translation happens after the rotation about (0,0),
//// we can just tack it on here.
//text_centering_xform.m_xform[0][3] = text_centering_translation.x;
//text_centering_xform.m_xform[1][3] = text_centering_translation.y;
//// This transform translates the text in the annotation plane
//// It can be a large translation
//ON_2dVector text_offset_translation(0.0,0.0); // CRhinoText::Offset() = text->Offset()
//switch( ann_type )
//{
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear:
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAligned:
// if ( m_points.Count() >= ON_OBSOLETE_V5_DimLinear::dim_pt_count )
// {
// const ON_OBSOLETE_V5_DimLinear* linear_dim = ON_OBSOLETE_V5_DimLinear::Cast(ann);
// if ( linear_dim )
// {
// text_offset_translation = linear_dim->Dim2dPoint(ON_OBSOLETE_V5_DimLinear::text_pivot_pt);
// }
// }
// break;
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAngular:
// if ( m_points.Count() >= ON_OBSOLETE_V5_DimAngular::dim_pt_count )
// {
// const ON_OBSOLETE_V5_DimAngular* angular_dim = ON_OBSOLETE_V5_DimAngular::Cast(ann);
// if ( angular_dim )
// {
// text_offset_translation = angular_dim->Dim2dPoint(ON_OBSOLETE_V5_DimAngular::text_pivot_pt);
// }
// }
// break;
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter:
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius:
// if ( m_points.Count() >= ON_OBSOLETE_V5_DimRadial::dim_pt_count )
// {
// // No user positioned text on radial dimensions.
// text_offset_translation = m_points[ON_OBSOLETE_V5_DimRadial::tail_pt_index];
// }
// break;
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader:
// if ( m_points.Count() > 0 )
// {
// // No user positioned text on leaders.
// text_offset_translation = *m_points.Last();
// }
// break;
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimOrdinate:
// if ( m_points.Count() == 2 )
// {
// // No user positioned text on leaders.
// text_offset_translation = m_points[1];
// }
// break;
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtTextBlock:
//case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtNothing:
// break;
//}
//ON_Xform plane_translation(1.0);
//plane_translation.m_xform[0][3] = text_offset_translation.x;
//plane_translation.m_xform[1][3] = text_offset_translation.y;
//// this transform maps a point in the annotation plane to world coordinates
//ON_Xform plane_to_world(1.0);
//plane_to_world.Rotation(ON_xy_plane,ann->m_plane);
//ON_Xform horizonal_xform(1.0);
//if ( ON::dtHorizontal == dimstyle_textalignment )
//{
// ON_3dPoint fixed_point = ann->m_plane.PointAt(text_offset_translation.x,text_offset_translation.y);
// horizonal_xform.Rotation(
// fixed_point,
// ann->m_plane.xaxis,
// ann->m_plane.yaxis,
// ann->m_plane.zaxis,
// fixed_point,
// cameraX,
// cameraY,
// cameraZ
// );
// if ( 2 == position_style )
// {
// // leaders, radial, and diameter
// ON_2dPoint E(0.0,0.0); // end point
// ON_2dVector R(1.0,0.0); // unit vector from penultimate point to end point
// GetLeaderEndAndDirection( this, E, R );
// ON_3dVector V = R.x*m_plane.xaxis + R.y*m_plane.yaxis;
// x = V*cameraX;
// y = ( x > -ON_SQRT_EPSILON )
// ? dimstyle_textgap
// : -(dimstyle_textgap + text_line_width);
// V = y*cameraX;
// horizonal_xform.m_xform[0][3] += V.x;
// horizonal_xform.m_xform[1][3] += V.y;
// horizonal_xform.m_xform[2][3] += V.z;
// }
//}
//ON_Xform gdi_to_world;
//gdi_to_world = horizonal_xform
// * plane_to_world
// * plane_translation
// * text_centering_xform
// * gdi_to_plane;
//xform = gdi_to_world;
//return true;
//}
//static bool do_plane_translation = true;
//static bool do_text_centering_xform = true;
//static bool do_text_centering_rotation = true;
//static bool do_text_centering_translation = true;
//static bool do_mirror_flip = true;
//static bool do_flip_x = true;
//static bool do_flip_y = true;
// New function added Oct 30, 07 - LW
// To use model xform to draw annotation in blocks correctly
bool ON_OBSOLETE_V5_Annotation::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& xform
) const
{
ON_Xform mxi;
if( model_xform)
{
mxi = model_xform->Inverse();
cameraX.Transform( mxi);
cameraY.Transform( mxi);
}
const ON_OBSOLETE_V5_Annotation* ann = this;
const ON_INTERNAL_OBSOLETE::V5_eAnnotationType ann_type = ann->m_type;
if ( 0 == gdi_height_of_I )
{
// Default to height of Ariel 'I'
gdi_height_of_I = (165*ON_Font::Constants::AnnotationFontCellHeight)/256;
}
if ( 0.0 == dimscale )
{
dimscale = 1.0;
}
dimstyle_textheight *= dimscale;
dimstyle_textgap *= dimscale;
double textheight = ( ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtTextBlock == ann_type )
? m_textheight*dimscale
: dimstyle_textheight;
if ( 0.0 == textheight )
textheight = 1.0;
ON_3dVector cameraZ = ON_CrossProduct( cameraX, cameraY );
if ( fabs( 1.0 - cameraZ.Length() ) > ON_SQRT_EPSILON )
{
cameraZ.Unitize();
}
// This xform is a scale from Windows gdi coordinates
// to annotation plane coordinates.
const double gdi_to_plane_scale = textheight/gdi_height_of_I;
ON_Xform gdi_to_plane(ON_Xform::IdentityTransformation);
gdi_to_plane.m_xform[0][0] = gdi_to_plane_scale;
gdi_to_plane.m_xform[1][1] = -gdi_to_plane_scale;
// width and height of text line in Rhino units.
const double text_line_width = gdi_to_plane_scale*(gdi_text_rect.right - gdi_text_rect.left);
//const double text_line_height = gdi_to_plane_scale*(gdi_text_rect.bottom - gdi_text_rect.top);
if ( ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtTextBlock == ann_type )
{
// The orientation of the text is text blocks
// does not depend on the view or text alignment
// settings. The position and orientation of
// the text in every other annotation depends on
// the view and text alignment settings.
//
// It simplifies the code for the rest of the
// annotation settings to quickly deal with text
// blocks here.
ON_Xform plane_to_world(ON_Xform::IdentityTransformation);
plane_to_world.Rotation(ON_xy_plane,ann->m_plane);
xform = plane_to_world*gdi_to_plane;
return true;
}
// text_position_mode
// 1 = linear, aligned, or anglular dimension
// (dimension definition determines center point of text box)
// 2 = radial, diameter, leader
// (dimension definition determined end point of text box)
int position_style = 0;
switch( ann_type )
{
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAligned:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAngular:
// dimension definition determines center point of text box
position_style = 1;
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader:
if (ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kHorizontalToScreen == dimstyle_textalignment)
position_style = 1;
else
position_style = 2;
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimOrdinate:
// dimension definition determines end of text box
position_style = 2;
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtTextBlock:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtNothing:
break;
}
// This translation puts the center of the fist line of text at
// (0,0) in the annotation's plane.
if (ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kHorizontalToScreen != dimstyle_textalignment || 1 == position_style)
{
if((m_justification & tjRight) == tjRight)
gdi_to_plane.m_xform[0][3] = 0.5*text_line_width;
else
gdi_to_plane.m_xform[0][3] = -0.5*text_line_width;
}
gdi_to_plane.m_xform[1][3] = -0.5*textheight;
if (ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kHorizontalToScreen != dimstyle_textalignment)
{
if ( ((cameraZ*m_plane.zaxis) < -ON_SQRT_EPSILON) )
{
// Viewing dimension from the backside
ON_Xform flip(ON_Xform::IdentityTransformation);
switch ( position_style )
{
case 1: // ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear, ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAligned, ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAngular
flip.m_xform[0][0] = -1.0;
flip.m_xform[0][3] = gdi_text_rect.left + gdi_text_rect.right;
break;
case 2: // ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter, ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius, ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader
//flip.m_xform[1][1] = -1.0;
//flip.m_xform[1][3] = -(gdi_text_rect.top + gdi_text_rect.bottom);
break;
}
gdi_to_plane = gdi_to_plane*flip;
}
}
// text_centering_rotation rotates about the "center". Angular,
// radial, and leader dimensions use this rotation.
ON_2dVector text_centering_rotation(1.0,0.0);
// text_centering_translation is a small translation deals with
// text that is above or to the right of the "center" point.
// It is no larger than dimstyle_gap + 1/2 the size of the
// text's bounding box.
ON_2dVector text_centering_translation(0.0,0.0);
double x = 1.0, y = 1.0;
ON_Xform xfs(ON_Xform::IdentityTransformation);
if (ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kHorizontalToScreen != dimstyle_textalignment)
{
if ( ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear == ann_type || ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAligned == ann_type )
{
if (ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kAboveLine == dimstyle_textalignment)
{
text_centering_translation.y = 0.5*textheight+dimstyle_textgap;
}
y = ann->m_plane.yaxis*cameraY;
x = -ann->m_plane.yaxis*cameraX;
if ( fabs(y) <= ON_SQRT_EPSILON && fabs(x) > ON_SQRT_EPSILON )
{
y = x;
}
if ( y < 0.0 )
{
text_centering_translation = -text_centering_translation;
text_centering_rotation = -text_centering_rotation; // rotate 180 degrees
}
}
else if ( ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAngular == ann_type )
{
// This transform rotates the text in the annotation plane.
const ON_OBSOLETE_V5_DimAngular* angular_dim = ON_OBSOLETE_V5_DimAngular::Cast(ann);
if ( 0 != angular_dim )
{
double a = 0.5*angular_dim->m_angle;
ON_2dVector R(cos(a),sin(a));
a -= 0.5*ON_PI;
text_centering_rotation.x = cos(a);
text_centering_rotation.y = sin(a);
ON_3dVector V = R.x*m_plane.xaxis + R.y*m_plane.yaxis;
x = V*cameraX;
y = V*cameraY;
if ( fabs(y) <= ON_SQRT_EPSILON && fabs(x) > ON_SQRT_EPSILON )
{
y = -x;
}
if ( y < 0.0 )
{
text_centering_rotation = -text_centering_rotation; // add another 180 degrees of rotation
}
if (ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kAboveLine == dimstyle_textalignment)
{
y = 0.5*textheight + dimstyle_textgap;
text_centering_translation.x = -y*text_centering_rotation.y;
text_centering_translation.y = y*text_centering_rotation.x;
}
}
}
else if ( ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter == ann_type
|| ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius == ann_type
|| ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader == ann_type
|| ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimOrdinate == ann_type)
{
// 30 Jan, 2015 - redid this again rh-29493, rh-29540
ON_2dPoint E(0.0,0.0); // end point
ON_2dVector R(1.0,0.0); // unit vector from penultimate point to end point
GetLeaderEndAndDirection( this, E, R );
text_centering_rotation = R;
text_centering_translation = (dimstyle_textgap + 0.5*text_line_width)*text_centering_rotation;
ON_3dPoint p0 = m_plane.origin;
ON_3dPoint prx = m_plane.PointAt(R.x, R.y);
ON_3dPoint pry = m_plane.PointAt(-R.y, R.x);
ON_3dVector xr = prx - p0; // 3d direction of text x
ON_3dVector yr = pry - p0; // 3d direction of text y
if (xr * cameraX <= ON_ZERO_TOLERANCE) // 22 April 2015 - Lowell - Fixed rh-30239
xfs.m_xform[0][0] = -1.0;
if (yr * cameraY <= ON_ZERO_TOLERANCE)
xfs.m_xform[1][1] = -1.0;
}
}
else if(ann_type == ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader)
{
if((m_justification & tjRight) == tjRight)
text_centering_translation.Set(-(dimstyle_textgap + 0.5*text_line_width), 0.0);
else if((m_justification & tjLeft) == tjLeft)
text_centering_translation.Set(dimstyle_textgap + 0.5*text_line_width, 0.0);
}
ON_Xform text_centering_xform(ON_Xform::IdentityTransformation);
text_centering_xform.m_xform[0][0] = text_centering_rotation.x;
text_centering_xform.m_xform[0][1] = -text_centering_rotation.y;
text_centering_xform.m_xform[1][0] = text_centering_rotation.y;
text_centering_xform.m_xform[1][1] = text_centering_rotation.x;
text_centering_xform = text_centering_xform * xfs;
// Since the translation happens after the rotation about (0,0),
// we can just tack it on here.
text_centering_xform.m_xform[0][3] = text_centering_translation.x;
text_centering_xform.m_xform[1][3] = text_centering_translation.y;
// This transform translates the text in the annotation plane
// from the plane origin to the final location of the annotation text
// It can be a large translation
ON_2dVector text_offset_translation(0.0,0.0); // CRhinoText::Offset() = text->Offset()
switch( ann_type )
{
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAligned:
if ( m_points.Count() >= ON_OBSOLETE_V5_DimLinear::dim_pt_count )
{
const ON_OBSOLETE_V5_DimLinear* linear_dim = ON_OBSOLETE_V5_DimLinear::Cast(ann);
if ( linear_dim )
{
text_offset_translation = linear_dim->Dim2dPoint(ON_OBSOLETE_V5_DimLinear::text_pivot_pt);
}
}
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAngular:
if ( m_points.Count() >= ON_OBSOLETE_V5_DimAngular::dim_pt_count )
{
const ON_OBSOLETE_V5_DimAngular* angular_dim = ON_OBSOLETE_V5_DimAngular::Cast(ann);
if ( angular_dim )
{
text_offset_translation = angular_dim->Dim2dPoint(ON_OBSOLETE_V5_DimAngular::text_pivot_pt);
}
}
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius:
if ( m_points.Count() >= ON_OBSOLETE_V5_DimRadial::dim_pt_count )
{
// No user positioned text on radial dimensions.
text_offset_translation = m_points[ON_OBSOLETE_V5_DimRadial::tail_pt_index];
}
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader:
if ( m_points.Count() > 0 )
{
// No user positioned text on leaders.
text_offset_translation = *m_points.Last();
}
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimOrdinate:
if ( m_points.Count() == 2 )
{
// No user positioned text on leaders.
text_offset_translation = m_points[1];
}
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtTextBlock:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtNothing:
break;
}
ON_Xform plane_translation(ON_Xform::IdentityTransformation);
plane_translation.m_xform[0][3] = text_offset_translation.x;
plane_translation.m_xform[1][3] = text_offset_translation.y;
// this transform maps a point in the annotation plane to world coordinates
ON_Xform plane_to_world(ON_Xform::IdentityTransformation);
plane_to_world.Rotation(ON_xy_plane,ann->m_plane);
ON_Xform horizonal_xform(ON_Xform::IdentityTransformation);
if (ON_INTERNAL_OBSOLETE::V5_TextDisplayMode::kHorizontalToScreen == dimstyle_textalignment)
{
ON_3dPoint fixed_point = ann->m_plane.PointAt(text_offset_translation.x,text_offset_translation.y);
horizonal_xform.Rotation(
fixed_point,
ann->m_plane.xaxis,
ann->m_plane.yaxis,
ann->m_plane.zaxis,
fixed_point,
cameraX,
cameraY,
cameraZ
);
if ( 2 == position_style )
{
// leaders, radial, and diameter
ON_2dPoint E(0.0,0.0); // end point
ON_2dVector R(1.0,0.0); // unit vector from penultimate point to end point
GetLeaderEndAndDirection( this, E, R );
ON_3dVector V = R.x*m_plane.xaxis + R.y*m_plane.yaxis;
x = V*cameraX;
y = ( x > -ON_SQRT_EPSILON )
? dimstyle_textgap
: -(dimstyle_textgap + text_line_width);
V = y*cameraX;
horizonal_xform.m_xform[0][3] += V.x;
horizonal_xform.m_xform[1][3] += V.y;
horizonal_xform.m_xform[2][3] += V.z;
}
}
ON_Xform gdi_to_world;
gdi_to_world = horizonal_xform
* plane_to_world
* plane_translation
* text_centering_xform
* gdi_to_plane;
xform = gdi_to_world;
return true;
}
bool ON_OBSOLETE_V5_Annotation::GetTextPoint( ON_2dPoint& text_2d_point ) const
{
bool rc = false;
switch ( m_type )
{
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtTextBlock:
text_2d_point.Set(0.0,0.0);
rc = true;
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimLinear:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAligned:
if ( m_userpositionedtext )
{
if ( m_points.Count() >= 5 )
{
text_2d_point = m_points[4];
rc = true;
}
}
else if ( m_points.Count() >= 3 )
{
text_2d_point.x = 0.5*(m_points[0].x + m_points[2].x);
text_2d_point.y = m_points[2].y;
rc = true;
}
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtLeader:
if ( m_points.Count() > 0 )
{
text_2d_point = *m_points.Last();
rc = true;
}
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimAngular:
{
const ON_OBSOLETE_V5_DimAngular* angular_dim = ON_OBSOLETE_V5_DimAngular::Cast(this);
if ( angular_dim )
{
if ( m_userpositionedtext )
{
if ( m_points.Count() >= 0 )
{
text_2d_point = m_points[0];
}
}
else
{
text_2d_point.x = angular_dim->m_radius*cos(angular_dim->m_angle);
text_2d_point.y = angular_dim->m_radius*sin(angular_dim->m_angle);
rc = true;
}
}
}
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimRadius:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimDiameter:
// no user positioned text
if ( m_points.Count() >= 3 )
{
text_2d_point = m_points[2];
rc = true;
}
break;
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtDimOrdinate:
case ON_INTERNAL_OBSOLETE::V5_eAnnotationType::dtNothing:
break;
}
return rc;
}
////////////////////////////////////////////////////////////
//
// do not copy or export this class definition.
//
class /*NEVER PUT THIS CLASS IN THE SDK*/ ON_AnnotationTextFormula : public ON_UserData
{
#if !defined(BOZO_VACCINE_699FCC4262D4488c9109F1B7A37CE926)
#error Never copy this class definition or put this definition in a header file!
#endif
ON_OBJECT_DECLARE(ON_AnnotationTextFormula);
public:
ON_AnnotationTextFormula();
~ON_AnnotationTextFormula();
// NO! - do not add IO support to this userdata! // bool Write(ON_BinaryArchive&) const;
// NO! - do not add IO support to this userdata! // bool Read(ON_BinaryArchive&);
bool GetDescription(ON_wString&) override;
// NO! - do not add IO support to this userdata! // bool Archive() const;
static ON_AnnotationTextFormula* Get(const ON_OBSOLETE_V5_Annotation*);
static void Set(ON_OBSOLETE_V5_Annotation*,const wchar_t* text_formula);
ON_wString m_text_formula;
};
#undef BOZO_VACCINE_699FCC4262D4488c9109F1B7A37CE926
ON_OBJECT_IMPLEMENT(ON_AnnotationTextFormula,ON_UserData,"699FCC42-62D4-488c-9109-F1B7A37CE926");
ON_AnnotationTextFormula::~ON_AnnotationTextFormula()
{}
ON_AnnotationTextFormula::ON_AnnotationTextFormula()
{
m_userdata_uuid = ON_CLASS_ID(ON_AnnotationTextFormula);
m_application_uuid = ON_opennurbs5_id;
m_userdata_copycount = 1;
}
bool ON_AnnotationTextFormula::GetDescription( ON_wString& description )
{
description = "Annotation Text Formula";
return true;
}
ON_AnnotationTextFormula* ON_AnnotationTextFormula::Get(const ON_OBSOLETE_V5_Annotation* p)
{
return (0 != p)
? ON_AnnotationTextFormula::Cast(p->GetUserData(ON_CLASS_ID(ON_AnnotationTextFormula)))
: 0;
}
void ON_AnnotationTextFormula::Set(ON_OBSOLETE_V5_Annotation* p,const wchar_t* text_formula)
{
if ( 0 != p )
{
ON_AnnotationTextFormula* tf = Get(p);
if ( 0 == text_formula || 0 == text_formula[0] )
{
if (0 != tf )
delete tf;
}
else
{
if ( 0 == tf )
{
tf = new ON_AnnotationTextFormula();
p->AttachUserData(tf);
}
tf->m_text_formula = text_formula;
}
}
}
//
// do not copy or export this class definition.
//
////////////////////////////////////////////////////////////
void ON_OBSOLETE_V5_Annotation::SetTextValue( const wchar_t* text_value )
{
m_usertext = text_value;
}
const wchar_t* ON_OBSOLETE_V5_Annotation::TextValue() const
{
return ((const wchar_t*)m_usertext);
}
void ON_OBSOLETE_V5_Annotation::SetTextFormula( const wchar_t* text_formula )
{
ON_AnnotationTextFormula::Set(this,text_formula);
}
const wchar_t* ON_OBSOLETE_V5_Annotation::TextFormula() const
{
const ON_AnnotationTextFormula* tf = ON_AnnotationTextFormula::Get(this);
return (0 != tf) ? ((const wchar_t*)tf->m_text_formula) : TextValue();
}
bool ON_BinaryArchive::Internal_WriteV2AnnotationObject(
const ON_OBSOLETE_V5_Annotation& V5_annotation,
const ON_3dmAnnotationContext* annotation_context
)
{
if (m_3dm_version != 1 && m_3dm_version != 2)
{
ON_ERROR("m_3dm_version must be 1 or 2");
return false;
}
const ON_DimStyle* dim_style = nullptr;
int archive_dim_style_index = V5_annotation.V5_3dmArchiveDimStyleIndex();
if ( archive_dim_style_index >= 0 && archive_dim_style_index < m_archive_dim_style_table.Count())
dim_style = m_archive_dim_style_table[archive_dim_style_index];
if (nullptr == dim_style)
{
dim_style = &ArchiveCurrentDimStyle();
archive_dim_style_index = ArchiveCurrentDimStyleIndex();
}
//const int V5_3dm_archive_dim_style_index = m_manifest.ItemFromId(ON_ModelComponent::Type::DimStyle, dim_style->Id()).Index();
m_annotation_context.SetReferencedDimStyle(dim_style,nullptr,archive_dim_style_index);
if (nullptr == annotation_context)
annotation_context = &m_annotation_context;
ON_OBSOLETE_V2_Annotation* V2_annotation = ON_OBSOLETE_V2_Annotation::CreateFromV5Annotation(
V5_annotation,
annotation_context
);
bool rc
= (nullptr != V2_annotation)
? Internal_WriteObject(*V2_annotation)
: Internal_WriteObject(V5_annotation);
if (nullptr != V2_annotation)
delete V2_annotation;
return rc;
}
ON_INTERNAL_OBSOLETE::V5_vertical_alignment ON_INTERNAL_OBSOLETE::V5VerticalAlignmentFromV5Justification(
unsigned int v5_justification_bits
)
{
ON_INTERNAL_OBSOLETE::V5_vertical_alignment valign = ON_INTERNAL_OBSOLETE::V5_vertical_alignment::Bottom;
const unsigned int v5_valign_mask
= ON_OBSOLETE_V5_TextObject::eTextJustification::tjBottom
| ON_OBSOLETE_V5_TextObject::eTextJustification::tjMiddle
| ON_OBSOLETE_V5_TextObject::eTextJustification::tjTop;
if (ON_OBSOLETE_V5_TextObject::eTextJustification::tjTop == (v5_justification_bits & v5_valign_mask))
valign = ON_INTERNAL_OBSOLETE::V5_vertical_alignment::Top;
else if (ON_OBSOLETE_V5_TextObject::eTextJustification::tjMiddle == (v5_justification_bits & v5_valign_mask))
valign = ON_INTERNAL_OBSOLETE::V5_vertical_alignment::Middle;
return valign;
}
ON_INTERNAL_OBSOLETE::V5_horizontal_alignment ON_INTERNAL_OBSOLETE::V5HorizontalAlignmentFromV5Justification(
unsigned int v5_justification_bits
)
{
ON_INTERNAL_OBSOLETE::V5_horizontal_alignment halign = ON_INTERNAL_OBSOLETE::V5_horizontal_alignment::Left;
const unsigned int v5_halign_mask
= ON_OBSOLETE_V5_TextObject::eTextJustification::tjLeft
| ON_OBSOLETE_V5_TextObject::eTextJustification::tjCenter
| ON_OBSOLETE_V5_TextObject::eTextJustification::tjRight;
if (ON_OBSOLETE_V5_TextObject::eTextJustification::tjCenter == (v5_justification_bits & v5_halign_mask))
halign = ON_INTERNAL_OBSOLETE::V5_horizontal_alignment::Center;
else if (ON_OBSOLETE_V5_TextObject::eTextJustification::tjRight == (v5_justification_bits & v5_halign_mask))
halign = ON_INTERNAL_OBSOLETE::V5_horizontal_alignment::Right;
return halign;
}