00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015
00016
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018
00019
00020
00021 #define BOZO_VACCINE_699FCC4262D4488c9109F1B7A37CE926
00022
00023
00024 ON_OBJECT_IMPLEMENT(ON_TextExtra,ON_UserData,"D90490A5-DB86-49f8-BDA1-9080B1F4E976");
00025
00026 ON_TextExtra::ON_TextExtra()
00027 {
00028 m_userdata_uuid = ON_TextExtra::m_ON_TextExtra_class_id.Uuid();
00029 m_application_uuid = ON_opennurbs5_id;
00030
00031
00032
00033 m_userdata_copycount = 1;
00034 SetDefaults();
00035 }
00036
00037 ON_TextExtra::~ON_TextExtra()
00038 {
00039 }
00040
00041 ON_TextExtra* ON_TextExtra::TextExtension(ON_TextEntity2* pText, bool bCreate)
00042 {
00043 ON_TextExtra* pExtra = 0;
00044 if(pText)
00045 {
00046 pExtra = ON_TextExtra::Cast(pText->GetUserData(ON_TextExtra::m_ON_TextExtra_class_id.Uuid()));
00047 if(pExtra == 0 && bCreate)
00048 {
00049 pExtra = new ON_TextExtra;
00050 if(pExtra)
00051 {
00052 if(!pText->AttachUserData(pExtra))
00053 {
00054 delete pExtra;
00055 pExtra = 0;
00056 }
00057 }
00058 }
00059 }
00060 return pExtra;
00061 }
00062
00063 const
00064 ON_TextExtra* ON_TextExtra::TextExtension(const ON_TextEntity2* pText, bool bCreate)
00065 {
00066 return TextExtension((ON_TextEntity2*)pText, bCreate);
00067 }
00068
00069 void ON_TextExtra::SetDefaults()
00070 {
00071 m_parent_uuid = ON_nil_uuid;
00072
00073 m_color_source = 0;
00074 m_mask_color = 0;
00075 m_border_offset = 0.1;
00076 }
00077
00078 void ON_TextExtra::Dump( ON_TextLog& text_log ) const
00079 {
00080
00081 }
00082
00083 unsigned int ON_TextExtra::SizeOf() const
00084 {
00085 unsigned int sz = ON_UserData::SizeOf();
00086 sz += sizeof(*this) - sizeof(ON_UserData);
00087 return sz;
00088 }
00089
00090 ON_BOOL32 ON_TextExtra::Write(ON_BinaryArchive& archive) const
00091 {
00092 bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
00093
00094 if(rc) rc = archive.WriteUuid(m_parent_uuid);
00095 if(rc) rc = archive.WriteBool(m_bDrawMask);
00096 if(rc) rc = archive.WriteInt(m_color_source);
00097 if(rc) rc = archive.WriteColor(m_mask_color);
00098 if(rc) rc = archive.WriteDouble(m_border_offset);
00099
00100 if(!archive.EndWrite3dmChunk())
00101 rc = false;
00102
00103 return rc;
00104 }
00105
00106 ON_BOOL32 ON_TextExtra::Read(ON_BinaryArchive& archive)
00107 {
00108 int major_version = 1;
00109 int minor_version = 0;
00110 bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
00111 if(!rc)
00112 return false;
00113 if(major_version != 1)
00114 return false;
00115
00116 if(rc) rc = archive.ReadUuid(m_parent_uuid);
00117 if(rc) rc = archive.ReadBool(&m_bDrawMask);
00118 if(rc) rc = archive.ReadInt(&m_color_source);
00119 if(rc) rc = archive.ReadColor(m_mask_color);
00120 if(rc) rc = archive.ReadDouble(&m_border_offset);
00121
00122 if ( !archive.EndRead3dmChunk() )
00123 rc = false;
00124
00125 return rc;
00126 }
00127
00128 ON_BOOL32 ON_TextExtra::GetDescription( ON_wString& description)
00129 {
00130 description.Format( "Userdata extension of ON_TextEntity");
00131 return true;
00132 }
00133
00134 ON_BOOL32 ON_TextExtra::Archive() const
00135 {
00136
00137 return true;
00138 }
00139
00140
00141 ON_UUID ON_TextExtra::ParentUUID() const
00142 {
00143 return m_parent_uuid;
00144 }
00145
00146 void ON_TextExtra::SetParentUUID( ON_UUID parent_uuid)
00147 {
00148 m_parent_uuid = parent_uuid;
00149 }
00150
00151 bool ON_TextExtra::DrawTextMask() const
00152 {
00153 return m_bDrawMask;
00154 }
00155
00156 void ON_TextExtra::SetDrawTextMask(bool bDraw)
00157 {
00158 m_bDrawMask = bDraw;
00159 }
00160
00161 int ON_TextExtra::MaskColorSource() const
00162 {
00163 return m_color_source;
00164 }
00165
00166 void ON_TextExtra::SetMaskColorSource(int source)
00167 {
00168 if(source == 1)
00169 m_color_source = 1;
00170 else
00171 m_color_source = 0;
00172 }
00173
00174 ON_Color ON_TextExtra::MaskColor() const
00175 {
00176 return m_mask_color;
00177 }
00178
00179 void ON_TextExtra::SetMaskColor(ON_Color color)
00180 {
00181 m_mask_color = color;
00182 }
00183
00184 double ON_TextExtra::MaskOffsetFactor() const
00185 {
00186 return m_border_offset;
00187 }
00188
00189 void ON_TextExtra::SetMaskOffsetFactor(double offset)
00190 {
00191 m_border_offset = offset;
00192 }
00193
00194
00195
00196
00197
00198
00199 ON_OBJECT_IMPLEMENT(ON_DimensionExtra,ON_UserData,"8AD5B9FC-0D5C-47fb-ADFD-74C28B6F661E");
00200
00201 ON_DimensionExtra::ON_DimensionExtra()
00202 {
00203 m_userdata_uuid = ON_DimensionExtra::m_ON_DimensionExtra_class_id.Uuid();
00204 m_application_uuid = ON_opennurbs5_id;
00205
00206
00207
00208 m_userdata_copycount = 1;
00209 SetDefaults();
00210 }
00211
00212 ON_DimensionExtra::~ON_DimensionExtra()
00213 {
00214 }
00215
00216 static ON_DimensionExtra* AnnotationExtension(ON_Annotation2* pDim, bool bCreate)
00217 {
00218 ON_DimensionExtra* pExtra = 0;
00219 if(pDim)
00220 {
00221 pExtra = ON_DimensionExtra::Cast(pDim->GetUserData(ON_DimensionExtra::m_ON_DimensionExtra_class_id.Uuid()));
00222 if(pExtra == 0 && bCreate)
00223 {
00224 pExtra = new ON_DimensionExtra;
00225 if( pExtra)
00226 {
00227 if(!pDim->AttachUserData(pExtra))
00228 {
00229 delete pExtra;
00230 pExtra = 0;
00231 }
00232 }
00233 }
00234 }
00235 return pExtra;
00236 }
00237
00238 ON_DimensionExtra* ON_DimensionExtra::DimensionExtension(ON_LinearDimension2* pDim, bool bCreate)
00239 {
00240 return AnnotationExtension((ON_Annotation2*)pDim, bCreate);
00241 }
00242
00243 const
00244 ON_DimensionExtra* ON_DimensionExtra::DimensionExtension(const ON_LinearDimension2* pDim, bool bCreate)
00245 {
00246 return DimensionExtension((ON_LinearDimension2*)pDim, bCreate);
00247 }
00248
00249 ON_DimensionExtra* ON_DimensionExtra::DimensionExtension(ON_RadialDimension2* pDim, bool bCreate)
00250 {
00251 return AnnotationExtension((ON_Annotation2*)pDim, bCreate);
00252 }
00253
00254 const
00255 ON_DimensionExtra* ON_DimensionExtra::DimensionExtension(const ON_RadialDimension2* pDim, bool bCreate)
00256 {
00257 return DimensionExtension((ON_RadialDimension2*)pDim, bCreate);
00258 }
00259
00260 ON_DimensionExtra* ON_DimensionExtra::DimensionExtension(ON_OrdinateDimension2* pDim, bool bCreate)
00261 {
00262 return AnnotationExtension((ON_Annotation2*)pDim, bCreate);
00263 }
00264
00265 const
00266 ON_DimensionExtra* ON_DimensionExtra::DimensionExtension(const ON_OrdinateDimension2* pDim, bool bCreate)
00267 {
00268 return DimensionExtension((ON_OrdinateDimension2*)pDim, bCreate);
00269 }
00270
00271 void ON_DimensionExtra::SetDefaults()
00272 {
00273 m_partent_uuid = ON_nil_uuid;
00274
00275 m_arrow_position = 0;
00276 m_text_rects = 0;
00277 m_distance_scale = 1.0;
00278 m_modelspace_basepoint = ON_origin;
00279 }
00280
00281 void ON_DimensionExtra::Dump( ON_TextLog& text_log ) const
00282 {
00283
00284 }
00285
00286 unsigned int ON_DimensionExtra::SizeOf() const
00287 {
00288 unsigned int sz = ON_UserData::SizeOf();
00289 sz += sizeof(*this) - sizeof(ON_UserData);
00290 return sz;
00291 }
00292
00293 ON_BOOL32 ON_DimensionExtra::Write(ON_BinaryArchive& archive) const
00294 {
00295 int major_version = 1;
00296 int minor_version = 1;
00297 bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,major_version,minor_version);
00298
00299 if(rc) rc = archive.WriteUuid( m_partent_uuid);
00300 if(rc) rc = archive.WriteInt( m_arrow_position);
00301 if(rc)
00302 {
00303 if( m_text_rects)
00304 {
00305 rc = archive.WriteInt( 7);
00306 rc = archive.WriteInt( 28, (const int*)m_text_rects);
00307 }
00308 else
00309 rc = archive.WriteInt( 0);
00310
00311 }
00312
00313 if(rc) rc = archive.WriteDouble(m_distance_scale);
00314
00315 if(!archive.EndWrite3dmChunk())
00316 rc = false;
00317
00318 return rc;
00319 }
00320
00321 ON_BOOL32 ON_DimensionExtra::Read(ON_BinaryArchive& archive)
00322 {
00323 int major_version = 1;
00324 int minor_version = 0;
00325 bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
00326 if(!rc)
00327 return false;
00328 if(major_version != 1)
00329 return false;
00330
00331 if(rc) rc = archive.ReadUuid(m_partent_uuid);
00332 if(rc) rc = archive.ReadInt(&m_arrow_position);
00333
00334 int rect_count = 0;
00335 if(rc) rc = archive.ReadInt( &rect_count);
00336 if( rc && rect_count)
00337 rc = archive.ReadInt( rect_count, (int*)m_text_rects);
00338
00339
00340 if(minor_version > 0)
00341 {
00342 if(rc) rc = archive.ReadDouble(&m_distance_scale);
00343 }
00344
00345 if ( !archive.EndRead3dmChunk() )
00346 rc = false;
00347
00348 return rc;
00349 }
00350
00351 ON_BOOL32 ON_DimensionExtra::GetDescription( ON_wString& description)
00352 {
00353 description.Format( "Userdata extension of ON_Dimensions");
00354 return true;
00355 }
00356
00357 ON_BOOL32 ON_DimensionExtra::Archive() const
00358 {
00359
00360 return true;
00361 }
00362
00363
00364 ON_UUID ON_DimensionExtra::ParentUUID() const
00365 {
00366 return m_partent_uuid;
00367 }
00368
00369 void ON_DimensionExtra::SetParentUUID( ON_UUID partent_uuid)
00370 {
00371 m_partent_uuid = partent_uuid;
00372 }
00373
00374 int ON_DimensionExtra::ArrowPosition() const
00375 {
00376 return m_arrow_position;
00377 }
00378
00379 void ON_DimensionExtra::SetArrowPosition( int position)
00380 {
00381 if( position > 0)
00382 m_arrow_position = 1;
00383 else if( position < 0)
00384 m_arrow_position = -1;
00385 else
00386 m_arrow_position = 0;
00387 }
00388
00389 double ON_DimensionExtra::DistanceScale() const
00390 {
00391 return m_distance_scale;
00392 }
00393
00394 void ON_DimensionExtra::SetDistanceScale(double s)
00395 {
00396 m_distance_scale = s;
00397 }
00398
00399 void ON_DimensionExtra::SetModelSpaceBasePoint(ON_3dPoint basepoint)
00400 {
00401 m_modelspace_basepoint = basepoint;
00402 }
00403
00404 ON_3dPoint ON_DimensionExtra::ModelSpaceBasePoint() const
00405 {
00406 return m_modelspace_basepoint;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 ON_VIRTUAL_OBJECT_IMPLEMENT( ON_Annotation2, ON_Geometry, "8D820224-BC6C-46b4-9066-BF39CC13AEFB");
00517 ON_OBJECT_IMPLEMENT( ON_LinearDimension2, ON_Annotation2, "BD57F33B-A1B2-46e9-9C6E-AF09D30FFDDE");
00518 ON_OBJECT_IMPLEMENT( ON_RadialDimension2, ON_Annotation2, "B2B683FC-7964-4e96-B1F9-9B356A76B08B");
00519 ON_OBJECT_IMPLEMENT( ON_AngularDimension2, ON_Annotation2, "841BC40B-A971-4a8e-94E5-BBA26D67348E");
00520 ON_OBJECT_IMPLEMENT( ON_TextEntity2, ON_Annotation2, "46F75541-F46B-48be-AA7E-B353BBE068A7");
00521 ON_OBJECT_IMPLEMENT( ON_Leader2, ON_Annotation2, "14922B7A-5B65-4f11-8345-D415A9637129");
00522 ON_OBJECT_IMPLEMENT( ON_TextDot, ON_Geometry, "74198302-CDF4-4f95-9609-6D684F22AB37");
00523 ON_OBJECT_IMPLEMENT( ON_OrdinateDimension2,ON_Annotation2, "C8288D69-5BD8-4f50-9BAF-525A0086B0C3");
00524
00525
00526
00527
00528 int ON_Annotation2::Index() const
00529 {
00530 return m_index;
00531 }
00532
00533 void ON_Annotation2::SetIndex( int index)
00534 {
00535 m_index = index;
00536 }
00537
00538
00539
00540 void ON_Annotation2::Create()
00541 {
00542 m_textdisplaymode = ON::dtAboveLine;
00543 m_index = -1;
00544 m_textheight = 1.0;
00545 Destroy();
00546 }
00547
00548 void ON_Annotation2::Destroy()
00549 {
00550
00551 m_points.Empty();
00552 SetTextValue(0);
00553 SetTextFormula(0);
00554 m_type = ON::dtNothing;
00555 m_plane = ON_xy_plane;
00556 m_userpositionedtext = false;
00557 m_justification = 0;
00558 m_annotative_scale = true;
00559 }
00560
00561 void ON_Annotation2::EmergencyDestroy()
00562 {
00563 m_points.EmergencyDestroy();
00564 m_usertext.EmergencyDestroy();
00565 }
00566
00567 ON_Annotation2::ON_Annotation2()
00568 {
00569 Create();
00570 }
00571
00572 ON_Annotation2::~ON_Annotation2()
00573 {
00574 Destroy();
00575 }
00576
00577 bool ON_Annotation2::EvaluatePoint( const ON_ObjRef& objref, ON_3dPoint& P) const
00578 {
00579 bool rc = false;
00580 switch( objref.m_component_index.m_type )
00581 {
00582 case ON_COMPONENT_INDEX::dim_linear_point:
00583 case ON_COMPONENT_INDEX::dim_radial_point:
00584 case ON_COMPONENT_INDEX::dim_angular_point:
00585 case ON_COMPONENT_INDEX::dim_ordinate_point:
00586 case ON_COMPONENT_INDEX::dim_text_point:
00587 {
00588 ON_2dPoint uv = Point(objref.m_component_index.m_index);
00589 if ( uv.IsValid() )
00590 {
00591 P = m_plane.PointAt(uv.x,uv.y);
00592 rc = true;
00593 }
00594 }
00595 break;
00596 default:
00597
00598 break;
00599 }
00600 if (!rc)
00601 {
00602 P = ON_UNSET_POINT;
00603 }
00604 return rc;
00605 }
00606
00607
00608 ON_Annotation2& ON_Annotation2::operator=(const ON_Annotation& src)
00609 {
00610
00611 Destroy();
00612 Create();
00613 ON_Geometry::operator=(src);
00614
00615 m_type = src.Type();
00616 m_textdisplaymode = src.TextDisplayMode();
00617 m_plane = src.Plane();
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629 m_points.Reserve(5);
00630 for( int i = 0; i < 5; i++)
00631 SetPoint( 0, src.Point( i));
00632
00633
00634 SetTextValue(src.UserText());
00635 SetTextFormula(0);
00636 m_userpositionedtext = src.UserPositionedText()?true:false;
00637 m_index = 0;
00638 m_textheight = 1.0;
00639
00640 return *this;
00641 }
00642
00643 ON_Annotation2::ON_Annotation2(const ON_Annotation& src)
00644 {
00645 Create();
00646 *this = src;
00647 }
00648
00649
00650 ON_BOOL32 ON_Annotation2::IsValid( ON_TextLog* text_log ) const
00651 {
00652 if ( !m_plane.IsValid() )
00653 {
00654 if ( text_log )
00655 {
00656 text_log->Print("ON_Annotation2 - m_plane is not valid\n");
00657 }
00658 return false;
00659 }
00660
00661 const int points_count = m_points.Count();
00662
00663 int i;
00664 for ( i = 0; i < points_count; i++ )
00665 {
00666 if ( !m_points[i].IsValid() )
00667 {
00668 if ( text_log )
00669 {
00670 text_log->Print("ON_Annotation2 - m_points[%d] is not valid.\n");
00671 }
00672 return false;
00673 }
00674 }
00675
00676 switch ( m_type )
00677 {
00678 case ON::dtDimLinear:
00679 case ON::dtDimAligned:
00680 case ON::dtDimAngular:
00681 case ON::dtDimDiameter:
00682 case ON::dtDimRadius:
00683 case ON::dtLeader:
00684 case ON::dtTextBlock:
00685 case ON::dtDimOrdinate:
00686 break;
00687
00688 default:
00689 if ( text_log )
00690 {
00691 text_log->Print("ON_Annotation2 - m_type = %d is not a valid enum value\n",m_type);
00692 }
00693 return false;
00694 break;
00695 }
00696
00697 return true;
00698 }
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773 static bool WriteAnnotation2UserText_V4( ON_BinaryArchive& file, const ON_wString& s )
00774 {
00775 bool rc;
00776 ON_wString s4;
00777 int len = s.Length();
00778
00779 for(int i = 0; i < len; i++)
00780 {
00781 if(s[i] == '\r' || s[i] == '\n')
00782 {
00783 s4 += L'\r';
00784 s4 += L'\n';
00785
00786
00787
00788
00789
00790 if(i < len-1 && (s[i+1] == L'\r' || s[i+1] == L'\n'))
00791 i++;
00792 continue;
00793 }
00794 s4 += s[i];
00795 }
00796 rc = file.WriteString(s4);
00797 return rc;
00798 }
00799
00800 static bool WriteAnnotation2UserText_V5( ON_BinaryArchive& file, const ON_wString& s )
00801 {
00802 bool rc;
00803 rc = file.WriteString( s);
00804 return rc;
00805 }
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823 ON_BOOL32 ON_Annotation2::Write( ON_BinaryArchive& file ) const
00824 {
00825 int i;
00826 bool rc = false;
00827 bool bInChunk = (file.Archive3dmVersion() >= 5 );
00828 if ( bInChunk )
00829 {
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843 rc = file.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,2);
00844 if (!rc)
00845 return false;
00846 }
00847 else
00848 {
00849
00850
00851
00852 rc = file.Write3dmChunkVersion( 1, 0 );
00853 }
00854
00855 while(rc)
00856 {
00857 i = m_type;
00858 rc = file.WriteInt( i);
00859 if ( !rc) break;
00860
00861 i = m_textdisplaymode;
00862 rc = file.WriteInt( i);
00863 if ( !rc) break;
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903 rc = file.WritePlane(m_plane);
00904 if ( !rc) break;
00905
00906 ON_2dPointArray points = m_points;
00907 int bUserPositionedText = m_userpositionedtext?1:0;
00908 switch( m_type )
00909 {
00910 case ON::dtDimAligned:
00911 case ON::dtDimLinear:
00912 if ( 4 == points.Count() )
00913 {
00914
00915 points.AppendNew();
00916 points[4].Set(0.5*(points[0].x + points[2].x),points[1].y);
00917 bUserPositionedText = false;
00918 }
00919 break;
00920
00921 case ON::dtDimAngular:
00922
00923 break;
00924
00925 case ON::dtDimRadius:
00926 case ON::dtDimDiameter:
00927
00928
00929
00930 if ( 4 == points.Count() )
00931 {
00932
00933 points.AppendNew();
00934 }
00935 if ( points.Count() >= 5 )
00936 {
00937 points[4] = points[2];
00938 }
00939 bUserPositionedText = false;
00940 break;
00941
00942 default:
00943 bUserPositionedText = false;
00944 break;
00945 }
00946
00947 rc = file.WriteArray( points);
00948 if ( !rc) break;
00949
00950
00951
00952 rc = ( file.Archive3dmVersion() <= 4 )
00953 ? WriteAnnotation2UserText_V4(file,m_usertext)
00954 : WriteAnnotation2UserText_V5(file,m_usertext);
00955 if ( !rc) break;
00956
00957
00958 rc = file.WriteInt( bUserPositionedText );
00959 if ( !rc) break;
00960
00961 rc = file.WriteInt( m_index);
00962 if ( !rc) break;
00963
00964 rc = file.WriteDouble( m_textheight);
00965 if ( !rc) break;
00966
00967 if ( !bInChunk )
00968 break;
00969
00970
00971
00972
00973
00974
00975
00976 rc = file.WriteInt(m_justification);
00977 if ( !rc)
00978 break;
00979
00980
00981 rc = file.WriteBool(m_annotative_scale);
00982 if(!rc)
00983 break;
00984
00985
00986
00987 ON_wString text_formula = TextFormula();
00988 rc = file.WriteString(text_formula);
00989 if(!rc)
00990 break;
00991
00992
00993
00994
00995
00996
00997 break;
00998 }
00999
01000 if ( bInChunk )
01001 {
01002 if ( !file.EndWrite3dmChunk() )
01003 rc = false;
01004 }
01005
01006 return rc;
01007 }
01008
01009 ON_BOOL32 ON_Annotation2::Read( ON_BinaryArchive& file )
01010 {
01011
01012
01013
01014
01015
01016
01017 Destroy();
01018
01019
01020
01021
01022
01023
01024 m_annotative_scale = false;
01025
01026 int major_version = 0;
01027 int minor_version = 0;
01028 bool rc = false;
01029
01030 bool bInChunk = (file.Archive3dmVersion() >= 5 && file.ArchiveOpenNURBSVersion() >= 200710180);
01031
01032 if ( bInChunk )
01033 {
01034 rc = file.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
01035 if ( !rc )
01036 return false;
01037 }
01038 else
01039 {
01040 rc = file.Read3dmChunkVersion(&major_version,&minor_version);
01041 }
01042
01043 while(rc)
01044 {
01045 if ( 1 != major_version )
01046 {
01047 rc = false;
01048 break;
01049 }
01050
01051 int i;
01052 rc = file.ReadInt( &i);
01053 if (!rc) break;
01054 m_type = ON::AnnotationType( i);
01055
01056 rc = file.ReadInt( &i);
01057 if (!rc) break;
01058 m_textdisplaymode = ON::eTextDisplayMode( i);
01059
01060 rc = file.ReadPlane( m_plane);
01061 if (!rc) break;
01062
01063 rc = file.ReadArray( m_points);
01064 if (!rc) break;
01065
01066 rc = file.ReadString( m_usertext);
01067 if (!rc) break;
01068
01069 i = 0;
01070 rc = file.ReadInt( &i );
01071 if (!rc) break;
01072 m_userpositionedtext = i ? true : false;
01073
01074 rc = file.ReadInt( &m_index);
01075 if (!rc) break;
01076
01077 rc = file.ReadDouble( &m_textheight);
01078 if (!rc) break;
01079
01080 switch( m_type )
01081 {
01082 case ON::dtDimAligned:
01083 case ON::dtDimLinear:
01084 if ( m_points.Count() < 5 )
01085 {
01086 m_userpositionedtext = false;
01087 }
01088 break;
01089
01090 case ON::dtDimAngular:
01091 if ( m_points.Count() <= 0 )
01092 {
01093 m_userpositionedtext = false;
01094 }
01095 break;
01096
01097 case ON::dtDimRadius:
01098 case ON::dtDimDiameter:
01099
01100
01101
01102 if ( 5 == m_points.Count() )
01103 {
01104 m_points.SetCount(4);
01105 }
01106 m_userpositionedtext = false;
01107 break;
01108
01109 default:
01110 m_userpositionedtext = false;
01111 break;
01112 }
01113
01114 if ( !bInChunk )
01115 break;
01116
01117
01118 rc = file.ReadInt( &m_justification );
01119 if (!rc) break;
01120
01121 if ( minor_version <= 0 )
01122 break;
01123
01124 if(minor_version >= 1)
01125 {
01126
01127 rc = file.ReadBool(&m_annotative_scale);
01128 if (!rc) break;
01129
01130 if ( minor_version >= 2 )
01131 {
01132
01133
01134 ON_wString text_formula;
01135 rc = file.ReadString(text_formula);
01136 if(!rc) break;
01137 SetTextFormula(text_formula);
01138 }
01139
01140 }
01141
01142
01143
01144 break;
01145 }
01146
01147 if ( bInChunk )
01148 {
01149 if (!file.EndRead3dmChunk() )
01150 rc = false;
01151 }
01152
01153
01154 return rc;
01155 }
01156
01157 ON::object_type ON_Annotation2::ObjectType() const
01158 {
01159 return ON::annotation_object;
01160 }
01161
01162 int ON_Annotation2::Dimension() const
01163 {
01164 return 3;
01165 }
01166
01167 ON_BOOL32 ON_Annotation2::Transform( const ON_Xform& xform )
01168 {
01169 ON_Geometry::Transform(xform);
01170
01171 ON_2dPoint p;
01172 ON_Xform scalexf;
01173 double scale = xform.Determinant();
01174 scale = fabs( scale);
01175 if( fabs( scale - 1.0) > ON_SQRT_EPSILON && fabs( scale) > ON_SQRT_EPSILON)
01176 {
01177 scale = pow( scale, 1.0/3.0);
01178 scalexf.Scale( scale, scale, scale);
01179 for( int i = 0; i < m_points.Count(); i++)
01180 {
01181 p = Point( i);
01182 p.Transform( scalexf);
01183 SetPoint( i, p);
01184 }
01185
01186 if( ON_Annotation2::IsText())
01187 {
01188 SetHeight( scale * Height());
01189 }
01190 }
01191
01192 return m_plane.Transform( xform );
01193
01194 }
01195
01196 int ON_Plane_Repair(ON_Plane& plane)
01197 {
01198 int rc;
01199 if ( plane.IsValid() )
01200 {
01201 rc = 1;
01202 }
01203 else
01204 {
01205 rc = 2;
01206 if (!plane.origin.IsValid())
01207 {
01208 plane.origin.Set(0.0,0.0,0.0);
01209 }
01210
01211 bool bGoodX = (plane.xaxis.IsValid() && !plane.xaxis.IsZero() );
01212 bool bGoodY = (plane.yaxis.IsValid() && !plane.yaxis.IsZero() );
01213 bool bGoodZ = (plane.zaxis.IsValid() && !plane.zaxis.IsZero() );
01214 if ( bGoodX )
01215 {
01216 if ( fabs(plane.xaxis.Length()-1.0) > ON_SQRT_EPSILON )
01217 plane.xaxis.Unitize();
01218 }
01219 if ( bGoodY )
01220 {
01221 if ( fabs(plane.yaxis.Length()-1.0) > ON_SQRT_EPSILON )
01222 plane.yaxis.Unitize();
01223 }
01224 if ( bGoodZ )
01225 {
01226 if ( fabs(plane.zaxis.Length()-1.0) > ON_SQRT_EPSILON )
01227 plane.zaxis.Unitize();
01228 }
01229
01230 if ( bGoodZ )
01231 {
01232 double x = bGoodX ? fabs(plane.zaxis*plane.xaxis) : 99.0;
01233 double y = bGoodX ? fabs(plane.zaxis*plane.yaxis) : 99.0;
01234 if ( x <= ON_SQRT_EPSILON )
01235 {
01236 if ( y > ON_SQRT_EPSILON )
01237 {
01238 plane.yaxis = ON_CrossProduct(plane.zaxis,plane.xaxis);
01239 plane.yaxis.Unitize();
01240 }
01241 }
01242 else if ( y <= ON_SQRT_EPSILON )
01243 {
01244 plane.xaxis = ON_CrossProduct(plane.yaxis,plane.zaxis);
01245 plane.xaxis.Unitize();
01246 }
01247 else if ( x <= y && x < 1.0 )
01248 {
01249 plane.yaxis = ON_CrossProduct(plane.zaxis,plane.xaxis);
01250 if( plane.yaxis.Unitize() )
01251 {
01252 plane.xaxis = ON_CrossProduct(plane.yaxis,plane.zaxis);
01253 plane.xaxis.Unitize();
01254 }
01255 else if ( y < 1.0 )
01256 {
01257 plane.CreateFromNormal( plane.origin, plane.zaxis );
01258 }
01259 }
01260 else if ( y < 1.0 )
01261 {
01262 plane.xaxis = ON_CrossProduct(plane.yaxis,plane.zaxis);
01263 if( plane.xaxis.Unitize() )
01264 {
01265 plane.yaxis = ON_CrossProduct(plane.zaxis,plane.xaxis);
01266 plane.yaxis.Unitize();
01267 }
01268 else
01269 {
01270 plane.CreateFromNormal( plane.origin, plane.zaxis );
01271 }
01272 }
01273 }
01274 else if ( bGoodX )
01275 {
01276 if ( bGoodY )
01277 {
01278 plane.zaxis = ON_CrossProduct(plane.xaxis,plane.yaxis);
01279 if ( plane.zaxis.Unitize() )
01280 {
01281 if ( fabs(plane.yaxis*plane.xaxis) > ON_SQRT_EPSILON )
01282 {
01283 plane.yaxis = ON_CrossProduct(plane.zaxis,plane.xaxis);
01284 plane.yaxis.Unitize();
01285 }
01286 }
01287 else
01288 {
01289 plane.yaxis.PerpendicularTo(plane.xaxis);
01290 plane.yaxis.Unitize();
01291 plane.zaxis = ON_CrossProduct(plane.xaxis,plane.yaxis);
01292 plane.zaxis.Unitize();
01293 }
01294 }
01295 else
01296 {
01297 plane.yaxis.PerpendicularTo(plane.xaxis);
01298 plane.yaxis.Unitize();
01299 plane.zaxis = ON_CrossProduct(plane.xaxis,plane.yaxis);
01300 plane.zaxis.Unitize();
01301 }
01302 }
01303 else if ( bGoodY )
01304 {
01305 plane.zaxis.PerpendicularTo(plane.yaxis);
01306 plane.zaxis.Unitize();
01307 plane.xaxis = ON_CrossProduct(plane.yaxis,plane.zaxis);
01308 plane.xaxis.Unitize();
01309 }
01310 else
01311 {
01312 plane.xaxis.Set(1.0,0.0,0.0);
01313 plane.yaxis.Set(0.0,1.0,0.0);
01314 plane.zaxis.Set(0.0,0.0,1.0);
01315 }
01316 plane.UpdateEquation();
01317 }
01318 return rc;
01319 }
01320
01321
01322 ON_BOOL32 ON_RadialDimension2::Transform( const ON_Xform& xform )
01323 {
01324
01325 return ON_Annotation2::Transform(xform);
01326 }
01327
01328 ON_BOOL32 ON_Leader2::Transform( const ON_Xform& xform )
01329 {
01330 bool rc = xform.IsIdentity();
01331 if ( !rc)
01332 {
01333 ON_Plane plane = m_plane;
01334 rc = plane.Transform(xform);
01335 if ( rc )
01336 {
01337 int i;
01338 const int point_count = m_points.Count();
01339 ON_2dPointArray q(point_count);
01340 ON_2dPoint p2, q2;
01341 ON_3dPoint P, Q;
01342 bool bUpdatePoints = false;
01343 for ( i = 0; i < point_count && rc; i++ )
01344 {
01345 p2 = m_points[i];
01346 P = m_plane.PointAt( p2.x, p2.y );
01347 Q = xform*P;
01348 if( !plane.ClosestPointTo(Q,&q2.x,&q2.y) )
01349 rc = false;
01350 if ( fabs(p2.x - q2.x) <= ON_SQRT_EPSILON )
01351 q2.x = p2.x;
01352 else
01353 bUpdatePoints = true;
01354 if ( fabs(p2.y - q2.y) <= ON_SQRT_EPSILON )
01355 q2.y = p2.y;
01356 else
01357 bUpdatePoints = true;
01358 q.Append(q2);
01359 }
01360
01361 if(rc)
01362 {
01363 ON_Geometry::Transform(xform);
01364 m_plane = plane;
01365
01366 if ( bUpdatePoints )
01367 m_points = q;
01368
01369 if ( m_points[0].x != 0.0 || m_points[0].y != 0.0 )
01370 {
01371 ON_2dVector v = m_points[0];
01372 if ( !v.IsZero() )
01373 {
01374 m_plane.origin = m_plane.PointAt(v.x,v.y);
01375 m_plane.UpdateEquation();
01376 v.Reverse();
01377 for ( i = 1; i < point_count; i++ )
01378 {
01379 m_points[i] += v;
01380 }
01381 m_points[0].Set(0.0,0.0);
01382 }
01383 }
01384 }
01385 }
01386 }
01387 return rc;
01388 }
01389
01390 ON_BOOL32 ON_AngularDimension2::Transform( const ON_Xform& xform )
01391 {
01392
01393
01394 bool rc = xform.IsIdentity();
01395 if ( !rc)
01396 {
01397 ON_Plane plane = m_plane;
01398 if ( dim_pt_count == m_points.Count() && plane.Transform( xform ) )
01399 {
01400 rc = true;
01401 ON_3dPoint P[dim_pt_count], Q[dim_pt_count], A[3], B[3];
01402 ON_2dVector p2[dim_pt_count], q2[dim_pt_count], a[3], b[3];
01403 double r[3];
01404 int i;
01405 bool bUpdatePoints = false;
01406 double a0 = 0.0;
01407 double a1 = m_angle;
01408 a[0].Set( m_radius*cos(a0), m_radius*sin(a0) );
01409 a[1].Set( m_radius*cos(0.5*(a0+a1)), m_radius*sin(0.5*(a0+a1)) );
01410 a[2].Set( m_radius*cos(a1), m_radius*sin(a1) );
01411 for ( i = 0; i < dim_pt_count && rc; i++ )
01412 {
01413 p2[i] = m_points[i];
01414 P[i] = m_plane.PointAt( p2[i].x, p2[i].y );
01415 Q[i] = xform*P[i];
01416 if( !plane.ClosestPointTo(Q[i],&q2[i].x,&q2[i].y) )
01417 rc = false;
01418 if ( fabs(p2[i].x - q2[i].x) > ON_SQRT_EPSILON
01419 || fabs(p2[i].y - q2[i].y) > ON_SQRT_EPSILON )
01420 {
01421
01422 bUpdatePoints = true;
01423 }
01424 }
01425
01426 for ( i = 0; i < 3 && rc; i++ )
01427 {
01428 A[i] = m_plane.PointAt( a[i].x, a[i].y );
01429 B[i] = xform*A[i];
01430 if( !plane.ClosestPointTo(B[i],&b[i].x,&b[i].y) )
01431 rc = false;
01432 r[i] = B[i].DistanceTo(plane.origin);
01433 if ( fabs(a[i].x - b[i].x) > ON_SQRT_EPSILON
01434 || fabs(a[i].y - b[i].y) > ON_SQRT_EPSILON )
01435 {
01436
01437 bUpdatePoints = true;
01438 }
01439 if ( r[i] < ON_SQRT_EPSILON )
01440 rc = false;
01441 else if ( r[i] > m_radius*(1.0+ON_SQRT_EPSILON) )
01442 bUpdatePoints = true;
01443 else if ( r[i] < m_radius*(1.0-ON_SQRT_EPSILON) )
01444 bUpdatePoints = true;
01445 }
01446
01447 if (rc)
01448 {
01449 if ( bUpdatePoints )
01450 {
01451 ON_3dVector X = B[0] - plane.origin;
01452 X.Unitize();
01453
01454 ON_3dVector Y1 = B[1] - plane.origin;
01455 Y1.Unitize();
01456 ON_3dVector Z1 = ON_CrossProduct(X,Y1);
01457 double z1 = Z1.Length();
01458 Z1.Unitize();
01459
01460 ON_3dVector Y2 = B[2] - plane.origin;
01461 Y2.Unitize();
01462 ON_3dVector Z2 = ON_CrossProduct(X,Y2);
01463 double z2 = Z2.Length();
01464 Z2.Unitize();
01465
01466 if ( z2 >= z1 && z2 >= 0.05 )
01467 {
01468 plane.xaxis = X;
01469 plane.zaxis = Z2;
01470 if ( Z1*Z2 < 0.0 )
01471 plane.zaxis.Reverse();
01472 plane.yaxis = ON_CrossProduct(plane.zaxis,plane.xaxis);
01473 plane.yaxis.Unitize();
01474 }
01475 else if ( z1 >= 0.05 )
01476 {
01477 plane.xaxis = X;
01478 plane.zaxis = Z1;
01479 plane.yaxis = ON_CrossProduct(plane.zaxis,plane.xaxis);
01480 plane.yaxis.Unitize();
01481 }
01482 else
01483 {
01484 rc = false;
01485 }
01486
01487 if (rc)
01488 {
01489 plane.UpdateEquation();
01490 ON_3dVector V = B[2] - plane.origin;
01491 double x = V*plane.xaxis;
01492 double y = V*plane.yaxis;
01493 double angle = atan2(y,x);
01494 if ( angle < 0.0 )
01495 angle += 2.0*ON_PI;
01496 double radius = (r[0]+r[1]+r[2])/3.0;
01497
01498 double arc_pt_angle = 1.0/3.0;
01499 if ( m_angle > 0.0 && m_points[arc_pt_index].IsValid() )
01500 {
01501 arc_pt_angle = atan2(m_points[arc_pt_index].y,m_points[arc_pt_index].x);
01502 if ( arc_pt_angle < 0.0 ) arc_pt_angle += 2.0*ON_PI;
01503 if ( arc_pt_angle > m_angle )
01504 arc_pt_angle = 1.0/3.0;
01505 else
01506 arc_pt_angle /= m_angle;
01507
01508 if ( arc_pt_angle < 0.0 )
01509 arc_pt_angle = 0.0;
01510 else if ( arc_pt_angle > 1.0 )
01511 arc_pt_angle = 1.0;
01512 }
01513 arc_pt_angle *= angle;
01514
01515
01516 ON_Geometry::Transform(xform);
01517 m_plane = plane;
01518 m_radius = radius;
01519 m_angle = angle;
01520 m_points[start_pt_index].Set(m_radius,0.0);
01521 m_points[end_pt_index].Set(m_radius*cos(m_angle),m_radius*sin(m_angle));
01522 m_points[arc_pt_index].Set(m_radius*cos(arc_pt_angle),m_radius*sin(arc_pt_angle));
01523 if ( m_userpositionedtext )
01524 {
01525 m_plane.ClosestPointTo(Q[userpositionedtext_pt_index],
01526 &m_points[userpositionedtext_pt_index].x,
01527 &m_points[userpositionedtext_pt_index].y
01528 );
01529 }
01530 else
01531 {
01532 m_points[userpositionedtext_pt_index].Set(m_radius*cos(0.5*m_angle),m_radius*sin(0.5*m_angle));
01533 }
01534
01535 }
01536 }
01537 else
01538 {
01539 ON_Geometry::Transform(xform);
01540 m_plane = plane;
01541 }
01542 }
01543 }
01544 }
01545
01546 return rc;
01547 }
01548
01549 bool ON_Annotation2::IsText() const
01550 { return (ON::dtTextBlock == m_type); }
01551
01552 bool ON_Annotation2::IsLeader() const
01553 { return (ON::dtLeader == m_type); }
01554
01555 bool ON_Annotation2::IsDimension() const
01556 { return (ON::dtTextBlock != m_type && ON::dtLeader != m_type); }
01557
01558 double ON_Annotation2::NumericValue() const
01559 { return ON_UNSET_VALUE; }
01560
01561 void ON_Annotation2::SetHeight( double ht)
01562 { if( ht > ON_SQRT_EPSILON) m_textheight = ht; }
01563
01564 double ON_Annotation2::Height() const
01565 { return m_textheight; }
01566
01567 void ON_Annotation2::SetType( ON::eAnnotationType type )
01568 {
01569 m_type = type;
01570 if(type == ON::dtDimRadius)
01571 SetTextValue(ON_RadialDimension2::DefaultRadiusText());
01572 else if(type == ON::dtDimDiameter)
01573 SetTextValue(ON_RadialDimension2::DefaultDiameterText());
01574 else
01575 SetTextValue(0);
01576
01577 SetTextFormula(0);
01578 }
01579
01580 ON::eAnnotationType ON_Annotation2::Type() const
01581 { return m_type; }
01582
01583 void ON_Annotation2::SetPlane( const ON_Plane& plane )
01584 { m_plane = plane; }
01585
01586 const ON_Plane& ON_Annotation2::Plane() const
01587 { return m_plane; }
01588
01589 void ON_Annotation2::SetPointCount( int count)
01590 {
01591 if( m_points.Count() < count)
01592 {
01593 m_points.Reserve( count);
01594 for( int i = m_points.Count(); i < count; i++)
01595 m_points.Append( ON_2dPoint());
01596 }
01597 }
01598
01599 int ON_Annotation2::PointCount() const
01600 { return m_points.Count(); }
01601
01602 void ON_Annotation2::SetPoints( const ON_2dPointArray& points )
01603 { m_points = points; }
01604
01605 const ON_2dPointArray& ON_Annotation2::Points() const
01606 { return m_points; }
01607
01608 void ON_Annotation2::SetPoint( int idx, const ON_2dPoint& point )
01609 {
01610 if ( idx >= 0 )
01611 {
01612 if ( idx < m_points.Count() )
01613 m_points[idx] = point;
01614 else if ( idx == m_points.Count() )
01615 m_points.Append(point);
01616 }
01617 }
01618
01619 ON_2dPoint ON_Annotation2::Point( int idx ) const
01620 {
01621 return ( idx >= 0 && idx < m_points.Count() )
01622 ? m_points[idx]
01623 : ON_2dPoint( 0.0, 0.0 );
01624 }
01625
01626 void ON_Annotation2::SetUserText( const wchar_t* text_value )
01627
01628 {
01629 SetTextValue( text_value );
01630 }
01631
01632 const ON_wString& ON_Annotation2::UserText() const
01633
01634 {
01635 return m_usertext;
01636 }
01637
01638 void ON_Annotation2::SetUserPositionedText( int bMoved )
01639 { m_userpositionedtext = bMoved?true:false; }
01640 bool ON_Annotation2::UserPositionedText() const
01641 { return m_userpositionedtext; }
01642
01643
01644
01645 ON_BOOL32 ON_Annotation2::GetECStoWCSXform( ON_Xform& xform ) const
01646 {
01647 ON_3dVector z = ON_CrossProduct( m_plane.xaxis, m_plane.yaxis );
01648 return xform.ChangeBasis( m_plane.origin, m_plane.xaxis, m_plane.yaxis, z,
01649 ON_origin, ON_xaxis, ON_yaxis, ON_zaxis );
01650 }
01651
01652
01653 ON_BOOL32 ON_Annotation2::GetWCStoECSXform( ON_Xform& xform ) const
01654 {
01655 ON_3dVector z = ON_CrossProduct( m_plane.xaxis, m_plane.yaxis );
01656 return xform.ChangeBasis( ON_origin, ON_xaxis, ON_yaxis, ON_zaxis,
01657 m_plane.origin, m_plane.xaxis, m_plane.yaxis, z );
01658 }
01659
01660 void ON_Annotation2::ReservePoints( int count)
01661 {
01662 m_points.SetCapacity( count);
01663 m_points.SetCount( count);
01664 }
01665
01666 const wchar_t* ON_Annotation2::DefaultText() { return L""; }
01667
01668
01669 void ON_Annotation2::SetTextDisplayMode( ON::eTextDisplayMode mode)
01670 {
01671 m_textdisplaymode = mode;
01672 }
01673
01674 ON::eTextDisplayMode ON_Annotation2::TextDisplayMode() const
01675 {
01676 return m_textdisplaymode;
01677 }
01678
01679
01680 void ON_Annotation2::ConvertBack( ON_Annotation& target)
01681 {
01682 target.SetType( Type());
01683 target.SetTextDisplayMode( TextDisplayMode());
01684 target.SetPlane( Plane());
01685 target.SetPoints( Points());
01686 target.SetUserText( TextValue());
01687 target.SetDefaultText( DefaultText());
01688 target.SetUserPositionedText( UserPositionedText());
01689 }
01690
01691 void ON_Annotation2::SetJustification( unsigned int justification)
01692 {
01693
01694 if(this->IsLeader())
01695 m_justification = justification;
01696 }
01697
01698 unsigned int ON_Annotation2::Justification()
01699 {
01700
01701 if(this->IsLeader())
01702 return m_justification;
01703 else
01704 return 0;
01705 }
01706
01707
01708
01709 ON_LinearDimension2::ON_LinearDimension2()
01710 {
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720 m_type = ON::dtDimLinear;
01721 m_textdisplaymode = ON::dtAboveLine;
01722 m_plane = ON_xy_plane;
01723 SetTextValue(DefaultText());
01724 SetTextFormula(0);
01725 m_points.Reserve(ON_LinearDimension2::dim_pt_count);
01726 m_points.SetCount(ON_LinearDimension2::dim_pt_count);
01727 m_points.Zero();
01728 }
01729
01730 ON_LinearDimension2::~ON_LinearDimension2()
01731 {
01732 }
01733
01734 ON_BOOL32 ON_LinearDimension2::IsValid( ON_TextLog* text_log ) const
01735 {
01736 if ( m_type != ON::dtDimLinear && m_type != ON::dtDimAligned )
01737 {
01738 if ( text_log )
01739 {
01740 text_log->Print("ON_LinearDimension2 - m_type != ON::dtDimLinear or ON::dtDimAligned.\n");
01741 }
01742 return false;
01743 }
01744
01745 if ( !ON_Annotation2::IsValid( text_log ))
01746 {
01747 if ( text_log )
01748 {
01749 text_log->Print("ON_LinearDimension2 - invalid ON_Annotation2 base class.\n");
01750 }
01751 return false;
01752 }
01753
01754 if ( m_points.Count() != 5 )
01755 {
01756 if ( text_log )
01757 {
01758 text_log->Print("ON_LinearDimension2 - m_points.Count() = %d (should be 5).\n",m_points.Count());
01759 }
01760 return false;
01761 }
01762
01763 if ( m_points[1].x != m_points[0].x )
01764 {
01765 if ( text_log )
01766 {
01767 text_log->Print("ON_LinearDimension2 - m_points[1].x = %g != %g = m_points[0].x (should be equal)\n",
01768 m_points[1].x, m_points[0].x
01769 );
01770 }
01771 return false;
01772 }
01773
01774 if ( m_points[3].x != m_points[2].x )
01775 {
01776 if ( text_log )
01777 {
01778 text_log->Print("ON_LinearDimension2 - m_points[3].x = %g != %g = m_points[2].x\n",
01779 m_points[3].x, m_points[2].x
01780 );
01781 }
01782 return false;
01783 }
01784
01785 if ( m_points[3].y != m_points[1].y )
01786 {
01787 if ( text_log )
01788 {
01789 text_log->Print("ON_LinearDimension2 - m_points[3].y = %g != %g = m_points[1].y\n",
01790 m_points[3].y, m_points[1].y
01791 );
01792 }
01793 return false;
01794 }
01795
01796 return true;
01797 }
01798
01799 ON_BOOL32 ON_LinearDimension2::Write(ON_BinaryArchive& archive) const
01800 {
01801
01802
01803
01804
01805
01806 bool rc = false;
01807 bool bInChunk = (archive.Archive3dmVersion() >= 5);
01808 if ( bInChunk )
01809 {
01810 rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
01811 if ( !rc )
01812 return false;
01813 }
01814 else
01815 {
01816 rc = true;
01817 }
01818
01819 while(rc)
01820 {
01821 rc = ON_Annotation2::Write(archive)?true:false;
01822 if (!rc) break;
01823 if ( !bInChunk )
01824 break;
01825
01826
01827
01828
01829 break;
01830 }
01831
01832 if ( bInChunk )
01833 {
01834 if (!archive.EndWrite3dmChunk())
01835 rc = false;
01836 }
01837 return rc;
01838 }
01839
01840 ON_BOOL32 ON_LinearDimension2::Read(ON_BinaryArchive& archive)
01841 {
01842
01843
01844
01845 int major_version = 0;
01846 int minor_version = 0;
01847 bool rc = false;
01848 bool bInChunk = (archive.Archive3dmVersion() >= 5 && archive.ArchiveOpenNURBSVersion() >= 200710180);
01849 if ( bInChunk )
01850 {
01851 rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
01852 if ( !rc )
01853 return false;
01854 }
01855 else
01856 {
01857 rc = true;
01858 }
01859
01860 while(rc)
01861 {
01862 rc = ON_Annotation2::Read(archive)?true:false;
01863 if (!rc) break;
01864 if ( !bInChunk || minor_version <= 0 )
01865 break;
01866
01867
01868
01869 break;
01870 }
01871
01872 if ( bInChunk )
01873 {
01874 if ( !archive.EndRead3dmChunk() )
01875 rc = false;
01876 }
01877 return rc;
01878 }
01879
01880 ON_BOOL32 ON_LinearDimension2::GetBBox(
01881 double* boxmax,
01882 double* boxmin,
01883 ON_BOOL32 bGrowBox
01884 ) const
01885 {
01886 ON_BoundingBox bbox;
01887 if ( bGrowBox )
01888 {
01889 bbox.m_min.x = boxmin[0];
01890 bbox.m_min.y = boxmin[1];
01891 bbox.m_min.z = boxmin[2];
01892 bbox.m_max.x = boxmax[0];
01893 bbox.m_max.y = boxmax[1];
01894 bbox.m_max.z = boxmax[2];
01895 if ( !bbox.IsValid() )
01896 {
01897 bbox.Destroy();
01898 bGrowBox = false;
01899 }
01900 }
01901
01902 if ( 5 == m_points.Count() )
01903 {
01904 ON_3dPointArray P(5);
01905 ON_2dPoint uv;
01906 if ( m_userpositionedtext )
01907 {
01908 uv = m_points[0];
01909 P.Append( m_plane.PointAt(uv.x,uv.y) );
01910 }
01911
01912 P.Append( m_plane.origin );
01913
01914 uv.x = 0.0;
01915 uv.y = m_points[1].y;
01916 P.Append( m_plane.PointAt(uv.x,uv.y) );
01917
01918 uv = m_points[2];
01919 P.Append( m_plane.PointAt(uv.x,uv.y) );
01920
01921 uv.y = m_points[1].y;
01922 P.Append( m_plane.PointAt(uv.x,uv.y) );
01923 bGrowBox = P.GetBBox(&bbox.m_min.x, &bbox.m_max.x, bGrowBox);
01924 }
01925
01926 if ( bGrowBox )
01927 {
01928 boxmin[0] = bbox.m_min.x;
01929 boxmin[1] = bbox.m_min.y;
01930 boxmin[2] = bbox.m_min.z;
01931 boxmax[0] = bbox.m_max.x;
01932 boxmax[1] = bbox.m_max.y;
01933 boxmax[2] = bbox.m_max.z;
01934 }
01935
01936 return bGrowBox;
01937 }
01938
01939
01940
01941
01942 bool ON_LinearDimension2::GetTightBoundingBox(
01943 ON_BoundingBox& tight_bbox,
01944 int bGrowBox,
01945 const ON_Xform* xform
01946 ) const
01947 {
01948 if ( 5 == m_points.Count() )
01949 {
01950 ON_3dPointArray P(5);
01951 ON_2dPoint uv;
01952 if ( m_userpositionedtext )
01953 {
01954 uv = m_points[0];
01955 P.Append( m_plane.PointAt(uv.x,uv.y) );
01956 }
01957
01958 P.Append( m_plane.origin );
01959
01960 uv.x = 0.0;
01961 uv.y = m_points[1].y;
01962 P.Append( m_plane.PointAt(uv.x,uv.y) );
01963
01964 uv = m_points[2];
01965 P.Append( m_plane.PointAt(uv.x,uv.y) );
01966
01967 uv.y = m_points[1].y;
01968 P.Append( m_plane.PointAt(uv.x,uv.y) );
01969
01970 if ( P.GetTightBoundingBox( tight_bbox, bGrowBox, xform ) )
01971 bGrowBox = true;
01972 }
01973 else if ( bGrowBox && !tight_bbox.IsValid() )
01974 {
01975 tight_bbox.Destroy();
01976 bGrowBox = false;
01977 }
01978
01979 return (0!=bGrowBox);
01980 }
01981
01982 int ON_LinearDimension2::Repair()
01983 {
01984
01985
01986
01987
01988 const int ext0_pt_index = ON_LinearDimension2::ext0_pt_index;
01989 const int arrow0_pt_index = ON_LinearDimension2::arrow0_pt_index;
01990 const int ext1_pt_index = ON_LinearDimension2::ext1_pt_index;
01991 const int arrow1_pt_index = ON_LinearDimension2::arrow1_pt_index;
01992 const int userpositionedtext_pt_index = ON_LinearDimension2::userpositionedtext_pt_index;
01993 const int dim_pt_count = ON_LinearDimension2::dim_pt_count;
01994
01995 int rc = 0;
01996 if ( m_points.Count() >= dim_pt_count
01997 && m_points[ext0_pt_index].IsValid()
01998 && m_points[ext1_pt_index].IsValid() )
01999 {
02000 rc = 1;
02001 if ( !m_plane.IsValid() )
02002 {
02003 rc = ON_Plane_Repair(m_plane);
02004 }
02005
02006 if ( m_points.Count() > dim_pt_count )
02007 {
02008 rc = 2;
02009 m_points.SetCount(dim_pt_count);
02010 }
02011
02012
02013 ON_2dVector v = m_points[ext0_pt_index];
02014 double d;
02015 int i;
02016 if ( !v.IsZero() )
02017 {
02018 rc = 2;
02019 m_plane.origin = m_plane.PointAt(v.x,v.y);
02020 m_plane.UpdateEquation();
02021 v.Reverse();
02022 for ( i = 0; i < dim_pt_count; i++ )
02023 {
02024 m_points[i] += v;
02025 }
02026 m_points[ext0_pt_index].Set(0.0,0.0);
02027 }
02028
02029 if ( ON::dtDimAligned == m_type && (m_points[ext1_pt_index].x < 0.0 || m_points[ext1_pt_index].y != 0.0) )
02030 {
02031 rc = 2;
02032
02033 if ( m_points[ext1_pt_index].x > 100.0*ON_SQRT_EPSILON
02034 && fabs(m_points[ext1_pt_index].y) <= ON_SQRT_EPSILON )
02035 {
02036 m_points[ext1_pt_index].y = 0.0;
02037 }
02038 else
02039 {
02040
02041
02042 v = m_points[ext1_pt_index];
02043 d = v.Length();
02044 v.Unitize();
02045 m_plane.Rotate(v.y,v.x,m_plane.zaxis,m_plane.origin);
02046
02047
02048 v.y = -v.y;
02049 for ( i = 0; i < dim_pt_count; i++ )
02050 {
02051 ON_2dPoint p = m_points[i];
02052 m_points[i].Set( v.x*p.x - v.y*p.y, v.y*p.x + v.x*p.y );
02053 }
02054 m_points[ext0_pt_index].Set(0.0,0.0);
02055 m_points[ext1_pt_index].Set(d,0.0);
02056 }
02057 }
02058 else if ( ON::dtDimLinear != m_type )
02059 {
02060 rc = 2;
02061 m_type = ON::dtDimLinear;
02062 }
02063
02064 if ( m_points[arrow0_pt_index].x != m_points[ext0_pt_index].x )
02065 {
02066 rc = 2;
02067 m_points[arrow0_pt_index].x = m_points[ext0_pt_index].x;
02068 }
02069
02070 if ( m_points[arrow1_pt_index].x != m_points[ext1_pt_index].x )
02071 {
02072 rc = 2;
02073 m_points[arrow1_pt_index].x = m_points[ext1_pt_index].x;
02074 }
02075
02076 if ( !ON_IsValid(m_points[arrow0_pt_index].y) )
02077 {
02078 rc = 2;
02079 if ( !ON_IsValid(m_points[arrow1_pt_index].y) )
02080 m_points[arrow1_pt_index].y = 0.5*(m_points[ext0_pt_index].y + m_points[ext1_pt_index].y);
02081 m_points[arrow0_pt_index].y = m_points[arrow1_pt_index].y;
02082 }
02083 else if ( !ON_IsValid(m_points[arrow1_pt_index].y) )
02084 {
02085 rc = 2;
02086 m_points[arrow1_pt_index].y = m_points[arrow0_pt_index].y;
02087 }
02088 else if ( m_points[arrow0_pt_index].y != m_points[arrow1_pt_index].y )
02089 {
02090 rc = 2;
02091 d = 0.5*(m_points[arrow0_pt_index].y + m_points[arrow1_pt_index].y);
02092 m_points[arrow0_pt_index].y = d;
02093 m_points[arrow1_pt_index].y = d;
02094 }
02095
02096 if ( m_userpositionedtext )
02097 {
02098 if ( !m_points[userpositionedtext_pt_index].IsValid() )
02099 {
02100 rc = 2;
02101 m_userpositionedtext = false;
02102 }
02103 }
02104
02105 if ( !m_userpositionedtext )
02106 {
02107 if ( m_points[userpositionedtext_pt_index].y != m_points[arrow0_pt_index].y
02108 || m_points[userpositionedtext_pt_index].x != 0.5*(m_points[arrow0_pt_index].x + m_points[arrow1_pt_index].x) )
02109 {
02110 rc = 2;
02111 m_points[userpositionedtext_pt_index].y = m_points[arrow0_pt_index].y;
02112 m_points[userpositionedtext_pt_index].x = 0.5*(m_points[arrow0_pt_index].x + m_points[arrow1_pt_index].x);
02113 }
02114 }
02115
02116 if ( !m_plane.IsValid() )
02117 {
02118 rc = 2;
02119 ON_Plane_Repair(m_plane);
02120 }
02121 }
02122 return rc;
02123 }
02124
02125 ON_BOOL32 ON_LinearDimension2::Transform( const ON_Xform& xform )
02126 {
02127
02128
02129 bool rc = xform.IsIdentity();
02130 if ( !rc)
02131 {
02132 ON_Plane plane = m_plane;
02133 if ( dim_pt_count == m_points.Count() && plane.Transform( xform ) )
02134 {
02135 rc = true;
02136 ON_3dPoint P[dim_pt_count], Q[dim_pt_count];
02137 ON_2dVector p2[dim_pt_count], q2[dim_pt_count];
02138 int i;
02139 bool bUpdatePoints = false;
02140 for ( i = 0; i < dim_pt_count && rc; i++ )
02141 {
02142 p2[i] = m_points[i];
02143 P[i] = m_plane.PointAt( p2[i].x, p2[i].y );
02144 Q[i] = xform*P[i];
02145 if( !plane.ClosestPointTo(Q[i],&q2[i].x,&q2[i].y) )
02146 rc = false;
02147 if ( fabs(p2[i].x - q2[i].x) > ON_SQRT_EPSILON
02148 || fabs(p2[i].y - q2[i].y) > ON_SQRT_EPSILON )
02149 {
02150
02151 bUpdatePoints = true;
02152 }
02153 }
02154
02155 if (rc)
02156 {
02157 ON_Geometry::Transform(xform);
02158 m_plane = plane;
02159 if ( bUpdatePoints )
02160 {
02161 for ( i = 0; i < dim_pt_count && rc; i++ )
02162 {
02163 m_points[i] = q2[i];
02164 }
02165
02166 Repair();
02167 }
02168 }
02169 }
02170 }
02171
02172 return rc;
02173 }
02174
02175 double ON_LinearDimension2::NumericValue() const
02176 {
02177
02178
02179 return (m_points.Count() >= dim_pt_count)
02180 ? fabs(m_points[ext0_pt_index].x - m_points[ext1_pt_index].x)
02181 : 0.0;
02182 }
02183
02184 int ON_LinearDimension2::StyleIndex() const
02185 {
02186 return ON_Annotation2::Index();
02187 }
02188
02189 void ON_LinearDimension2::SetStyleIndex( int i)
02190 {
02191 ON_Annotation2::SetIndex( i);
02192 }
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208 ON_2dPoint ON_LinearDimension2::Dim2dPoint( int point_index ) const
02209 {
02210 ON_2dPoint p2;
02211 if ( m_points.Count() < dim_pt_count )
02212 {
02213 p2.x = p2.y = ON_UNSET_VALUE;
02214 }
02215 else
02216 {
02217 if ( text_pivot_pt == point_index )
02218 {
02219 point_index = m_userpositionedtext ? userpositionedtext_pt_index : dim_mid_pt;
02220 }
02221
02222 const ON_2dPoint* points = m_points.Array();
02223 switch(point_index)
02224 {
02225 case ext0_pt_index:
02226 p2 = points[0];
02227 break;
02228
02229 case arrow0_pt_index:
02230 p2.x = points[0].x;
02231 p2.y = points[1].y;
02232 break;
02233
02234 case ext1_pt_index:
02235 p2 = points[2];
02236 break;
02237
02238 case arrow1_pt_index:
02239 p2.x = points[2].x;
02240 p2.y = points[1].y;
02241 break;
02242
02243 case userpositionedtext_pt_index:
02244 p2.x = points[4].x;
02245 p2.y = points[4].y;
02246 break;
02247
02248 case dim_mid_pt:
02249 p2.x = 0.5*(points[0].x + points[2].x);
02250 p2.y = points[1].y;
02251 break;
02252
02253 default:
02254 p2.x = p2.y = ON_UNSET_VALUE;
02255 break;
02256 }
02257 }
02258 return p2;
02259 }
02260
02261 ON_3dPoint ON_LinearDimension2::Dim3dPoint( int point_index ) const
02262 {
02263 ON_2dPoint p2 = Dim2dPoint(point_index);
02264 return (ON_UNSET_VALUE == p2.x) ? ON_UNSET_POINT : m_plane.PointAt(p2.x,p2.y);
02265 }
02266
02267
02268
02269 void ON_LinearDimension2::GetV2Form( ON_LinearDimension& dim)
02270 {
02271 ON_Annotation2::ConvertBack( dim);
02272 }
02273
02274
02275
02276 bool ON_LinearDimension2::CreateFromV2(
02277 const ON_Annotation& v2_ann,
02278 const ON_3dmAnnotationSettings& settings,
02279 int dimstyle_index
02280 )
02281 {
02282 bool rc = false;
02283 if ( ON::dtDimLinear == v2_ann.m_type || ON::dtDimAligned == v2_ann.m_type )
02284 {
02285 if ( v2_ann.m_points.Count() >= ON_LinearDimension2::dim_pt_count )
02286 {
02287 m_points.Reserve(ON_LinearDimension2::dim_pt_count);
02288 m_points.SetCount(0);
02289 m_points.Append(ON_LinearDimension2::dim_pt_count,v2_ann.Points().Array());
02290 m_userpositionedtext = v2_ann.UserPositionedText();
02291 m_type = v2_ann.m_type;
02292 SetTextValue(v2_ann.UserText());
02293 SetTextFormula(0);
02294
02295 m_plane = v2_ann.m_plane;
02296 m_plane.UpdateEquation();
02297
02298 switch( settings.m_textalign)
02299 {
02300 case 1:
02301 m_textdisplaymode = ON::dtInLine;
02302 break;
02303 case 2:
02304 m_textdisplaymode = ON::dtHorizontal;
02305 break;
02306 default:
02307 m_textdisplaymode = ON::dtAboveLine;
02308 break;
02309 }
02310
02311 ON_2dVector v = m_points[0];
02312 if ( !v.IsZero() )
02313 {
02314 m_plane.origin = m_plane.PointAt(v.x,v.y);
02315 m_plane.UpdateEquation();
02316 m_points[0].Set(0.0,0.0);
02317 v.Reverse();
02318 int i;
02319 for ( i = 1; i < ON_LinearDimension2::dim_pt_count; i++ )
02320 {
02321 m_points[i] += v;
02322 }
02323 }
02324
02325 m_index = dimstyle_index;
02326 rc = true;
02327 }
02328 }
02329 return rc;
02330 }
02331
02332 int ON_LinearDimension2::GetDimensionLineSegments(
02333 ON_RECT gdi_text_rect,
02334 int gdi_height_of_I,
02335 ON_Xform gdi_to_world,
02336 const ON_DimStyle& dimstyle,
02337 double dimscale,
02338 const ON_Viewport* vp,
02339 double x[6],
02340 bool& bInside
02341 ) const
02342 {
02343 int rc = 0;
02344
02345 x[0] = 0.0;
02346 x[1] = 0.0;
02347 x[2] = 0.0;
02348 x[3] = 0.0;
02349 x[4] = 0.0;
02350 x[5] = 0.0;
02351 bInside = true;
02352
02353 if ( m_points.Count() < 3 )
02354 return 0;
02355
02356 int i = (m_points[ext0_pt_index].x <= m_points[ext1_pt_index].x)
02357 ? ext0_pt_index
02358 : ext1_pt_index;
02359 const double x0 = m_points[i].x;
02360 const double x1 = m_points[(ext0_pt_index==i) ? ext1_pt_index : ext0_pt_index].x;
02361 x[0] = x0;
02362 x[1] = x1;
02363 x[2] = x0;
02364 x[3] = x1;
02365 x[4] = x0;
02366 x[5] = x1;
02367
02368 if ( 0 == gdi_height_of_I )
02369 {
02370
02371 gdi_height_of_I = (165*ON_Font::normal_font_height)/256;
02372 }
02373
02374 if ( 0.0 == dimscale )
02375 {
02376 dimscale = 1.0;
02377 }
02378
02379 double t;
02380
02381 ON::eTextDisplayMode textdisplay = ON::TextDisplayMode(dimstyle.TextAlignment());
02382 if ( ON::dtHorizontal == textdisplay && !vp )
02383 textdisplay = ON::dtInLine;
02384
02385 const double text_height_of_I = dimscale*dimstyle.TextHeight();
02386 const double textgap = fabs(dimscale*dimstyle.TextGap());
02387 const double gdi_to_plane_scale = text_height_of_I/gdi_height_of_I;
02388 const double textwidth = fabs(gdi_to_plane_scale*(gdi_text_rect.right - gdi_text_rect.left));
02389 const double arrowwidth = dimscale*dimstyle.ArrowSize();
02390 const double tailwidth = 0.5*arrowwidth;
02391 const double dimwidth = x1 - x0;
02392 const double mindimwidth = (ON::dtInLine == textdisplay)
02393 ? (2.0*(arrowwidth + tailwidth + textgap) + textwidth)
02394 : (2.0*arrowwidth + tailwidth);
02395 const double dimextension = dimscale*dimstyle.DimExtension();
02396
02397 int ForceArrows = 0;
02398 const ON_DimensionExtra* pDE = ON_DimensionExtra::DimensionExtension(this,false);
02399 if( pDE)
02400 ForceArrows = pDE->ArrowPosition();
02401
02402
02403
02404 if(ForceArrows == -1 ||
02405 (dimwidth < mindimwidth && ForceArrows != 1))
02406 {
02407 t = arrowwidth + tailwidth;
02408 x[0] = x0;
02409 x[1] = x0-t;
02410 x[2] = x1+t;
02411 x[3] = x1;
02412 x[4] = x0;
02413 x[5] = x1;
02414 if( dimextension != 0.0)
02415 {
02416 x[0] += dimextension;
02417 x[3] -= dimextension;
02418 }
02419 bInside = false;
02420 rc = 2;
02421 }
02422
02423 else if ( (ON::dtHorizontal == textdisplay && vp) || m_userpositionedtext )
02424 {
02425
02426 double xx0, xx1, xx, y0, y1, t;
02427 ON_3dPoint P, R;
02428 ON_2dPoint corners[4];
02429 ON_Line ray;
02430
02431 ON_3dVector vp_zaxis = (ON::dtHorizontal == textdisplay && vp)
02432 ? vp->CameraZ()
02433 : m_plane.zaxis;
02434
02435
02436
02437
02438 double gdi_gap = fabs(textgap/gdi_to_plane_scale)-12;
02439 if(gdi_gap < 0.0) gdi_gap = 0.0;
02440
02441 R.Set(gdi_text_rect.left-gdi_gap,gdi_text_rect.bottom+gdi_gap,0.0);
02442 ray.from = gdi_to_world*R; ray.to = ray.from + vp_zaxis;
02443 P = ( ON_Intersect(ray,m_plane,&t) ) ? ray.PointAt(t) : ray.from;
02444 m_plane.ClosestPointTo(P,&corners[0].x,&corners[0].y);
02445
02446 R.Set(gdi_text_rect.right+gdi_gap,gdi_text_rect.bottom+gdi_gap,0.0);
02447 ray.from = gdi_to_world*R; ray.to = ray.from + vp_zaxis;
02448 P = ( ON_Intersect(ray,m_plane,&t) ) ? ray.PointAt(t) : ray.from;
02449 m_plane.ClosestPointTo(P,&corners[1].x,&corners[1].y);
02450
02451 R.Set(gdi_text_rect.right+gdi_gap,gdi_text_rect.top-gdi_gap,0.0);
02452 ray.from = gdi_to_world*R; ray.to = ray.from + vp_zaxis;
02453 P = ( ON_Intersect(ray,m_plane,&t) ) ? ray.PointAt(t) : ray.from;
02454 m_plane.ClosestPointTo(P,&corners[2].x,&corners[2].y);
02455
02456 R.Set(gdi_text_rect.left-gdi_gap,gdi_text_rect.top-gdi_gap,0.0);
02457 ray.from = gdi_to_world*R; ray.to = ray.from + vp_zaxis;
02458 P = ( ON_Intersect(ray,m_plane,&t) ) ? ray.PointAt(t) : ray.from;
02459 m_plane.ClosestPointTo(P,&corners[3].x,&corners[3].y);
02460
02461
02462 xx0 = xx1 = ON_UNSET_VALUE;
02463 for ( i = 0; i < 4; i++ )
02464 {
02465 y0 = corners[i].y - m_points[1].y;
02466 y1 = corners[(i+1)%4].y - m_points[1].y;
02467
02468 if ( (y0 > 0.0 && y1 > 0.0) || (y0 < 0.0 && y1 < 0.0) || y0 == y1 )
02469 continue;
02470
02471
02472
02473 t = y0/(y0-y1);
02474 xx = (1.0-t)*corners[i].x + t*corners[(i+1)%4].x;
02475 if ( ON_UNSET_VALUE == xx0 )
02476 {
02477 xx0 = xx1 = xx;
02478 }
02479 else if ( xx < xx0 )
02480 {
02481 xx0 = xx;
02482 }
02483 else if ( xx > xx1 )
02484 {
02485 xx1 = xx;
02486 }
02487 }
02488
02489
02490
02491 if(xx0 != ON_UNSET_VALUE && xx1 != ON_UNSET_VALUE)
02492 {
02493
02494
02495 t = arrowwidth + tailwidth;
02496 if ( x0 + t <= xx0 && xx0 < xx1 && xx1 <= x1 - t )
02497 {
02498
02499 x[0] = x0;
02500 x[1] = xx0;
02501 x[2] = xx1;
02502 x[3] = x1;
02503 x[4] = x0;
02504 x[5] = x1;
02505 if( dimextension != 0.0)
02506 {
02507 x[0] -= dimextension;
02508 x[3] += dimextension;
02509 }
02510 rc = 2;
02511 }
02512 else
02513 {
02514 x[0] = x0;
02515 x[1] = x0 - t;
02516 x[2] = x1 + t;
02517 x[3] = x1;
02518 x[4] = x0;
02519 x[5] = x1;
02520 if( dimextension != 0.0)
02521 {
02522 x[0] += dimextension;
02523 x[3] -= dimextension;
02524 }
02525 bInside = false;
02526 rc = 2;
02527 }
02528 }
02529 else
02530 {
02531
02532 x[0] = x0;
02533 x[1] = x1;
02534 x[2] = x0;
02535 x[3] = x1;
02536 x[4] = x0;
02537 x[5] = x1;
02538 if( dimextension != 0.0)
02539 {
02540 x[0] -= dimextension;
02541 x[1] += dimextension;
02542 }
02543 rc = 1;
02544 }
02545 }
02546
02547 else if ( ON::dtAboveLine == textdisplay || m_userpositionedtext )
02548 {
02549
02550 x[0] = x0;
02551 x[1] = x1;
02552 x[2] = x0;
02553 x[3] = x1;
02554 x[4] = x0;
02555 x[5] = x1;
02556 if( dimextension != 0.0)
02557 {
02558 x[0] -= dimextension;
02559 x[1] += dimextension;
02560 }
02561 rc = 1;
02562 }
02563
02564 else if ( ON::dtInLine == textdisplay )
02565 {
02566
02567 t = 0.5*(dimwidth - textwidth - 2.0*textgap);
02568 x[0] = x0;
02569 x[1] = x0+t;
02570 x[2] = x1-t;
02571 x[3] = x1;
02572 x[4] = x0;
02573 x[5] = x1;
02574 if( dimextension != 0.0)
02575 {
02576 x[0] -= dimextension;
02577 x[3] += dimextension;
02578 }
02579
02580 rc = 2;
02581 }
02582
02583 return rc;
02584 }
02585
02586
02587 const wchar_t* ON_LinearDimension2::DefaultText() { return L"<>"; }
02588
02589
02590
02591
02592
02593 ON_RadialDimension2::ON_RadialDimension2()
02594 {
02595 m_type = ON::dtDimDiameter;
02596 m_textdisplaymode = ON::dtInLine;
02597 SetTextValue(DefaultDiameterText());
02598 SetTextFormula(0);
02599 m_points.Reserve(ON_RadialDimension2::dim_pt_count);
02600 m_points.SetCount(ON_RadialDimension2::dim_pt_count);
02601 m_points.Zero();
02602 }
02603
02604 ON_RadialDimension2::~ON_RadialDimension2()
02605 {
02606 }
02607
02608 ON_BOOL32 ON_RadialDimension2::IsValid( ON_TextLog* text_log ) const
02609 {
02610 if ( m_type != ON::dtDimRadius && m_type != ON::dtDimDiameter )
02611 {
02612 if ( text_log )
02613 {
02614 text_log->Print("ON_RadialDimension2 - m_type != ON::dtDimRadius or ON::dtDimDiameter\n");
02615 }
02616 return false;
02617 }
02618
02619 if ( !ON_Annotation2::IsValid( text_log ))
02620 {
02621 if ( text_log )
02622 {
02623 text_log->Print("ON_RadialDimension2 - invalid ON_Annotation2 base class.\n");
02624 }
02625 return false;
02626 }
02627
02628 if ( 4 != m_points.Count() )
02629 {
02630 if ( text_log )
02631 {
02632 text_log->Print("ON_RadialDimension2 - m_points.Count() = %d (should be 4 or 5)\n", m_points.Count() );
02633 }
02634 return false;
02635 }
02636
02637 return true;
02638 }
02639
02640
02641 ON_BOOL32 ON_RadialDimension2::Write(ON_BinaryArchive& archive) const
02642 {
02643
02644
02645
02646
02647
02648 bool rc = false;
02649 bool bInChunk = (archive.Archive3dmVersion() >= 5);
02650 if ( bInChunk )
02651 {
02652 rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
02653 if ( !rc )
02654 return false;
02655 }
02656 else
02657 {
02658 rc = true;
02659 }
02660
02661 while(rc)
02662 {
02663 rc = ON_Annotation2::Write(archive)?true:false;
02664 if (!rc) break;
02665 if ( !bInChunk )
02666 break;
02667
02668
02669
02670
02671 break;
02672 }
02673
02674 if ( bInChunk )
02675 {
02676 if (!archive.EndWrite3dmChunk())
02677 rc = false;
02678 }
02679 return rc;
02680 }
02681
02682 ON_BOOL32 ON_RadialDimension2::Read(ON_BinaryArchive& archive)
02683 {
02684
02685
02686
02687 int major_version = 0;
02688 int minor_version = 0;
02689 bool rc = false;
02690 bool bInChunk = (archive.Archive3dmVersion() >= 5 && archive.ArchiveOpenNURBSVersion() >= 200710180);
02691 if ( bInChunk )
02692 {
02693 rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
02694 if ( !rc )
02695 return false;
02696 }
02697 else
02698 {
02699 rc = true;
02700 }
02701
02702 while(rc)
02703 {
02704 rc = ON_Annotation2::Read(archive)?true:false;
02705 if (!rc) break;
02706 if ( !bInChunk || minor_version <= 0 )
02707 break;
02708
02709
02710
02711 break;
02712 }
02713
02714 if ( bInChunk )
02715 {
02716 if ( !archive.EndRead3dmChunk() )
02717 rc = false;
02718 }
02719 return rc;
02720 }
02721
02722
02723 ON_BOOL32 ON_RadialDimension2::GetBBox(
02724 double* boxmax,
02725 double* boxmin,
02726 ON_BOOL32 bGrowBox
02727 ) const
02728 {
02729 ON_BoundingBox bbox;
02730 if ( bGrowBox )
02731 {
02732 bbox.m_min.x = boxmin[0];
02733 bbox.m_min.y = boxmin[1];
02734 bbox.m_min.z = boxmin[2];
02735 bbox.m_max.x = boxmax[0];
02736 bbox.m_max.y = boxmax[1];
02737 bbox.m_max.z = boxmax[2];
02738 if ( !bbox.IsValid() )
02739 {
02740 bbox.Destroy();
02741 bGrowBox = false;
02742 }
02743 }
02744
02745 if ( 4 == m_points.Count() )
02746 {
02747 ON_3dPointArray P(4);
02748 ON_2dPoint uv;
02749 if ( m_userpositionedtext )
02750 {
02751 uv = m_points[0];
02752 P.Append( m_plane.PointAt(uv.x,uv.y) );
02753 }
02754
02755 P.Append( m_plane.origin );
02756
02757 uv = m_points[1];
02758 P.Append( m_plane.PointAt(uv.x,uv.y) );
02759
02760 uv = m_points[2];
02761 P.Append( m_plane.PointAt(uv.x,uv.y) );
02762
02763 uv = m_points[3];
02764 P.Append( m_plane.PointAt(uv.x,uv.y) );
02765 bGrowBox = P.GetBBox(&bbox.m_min.x, &bbox.m_max.x, bGrowBox);
02766 }
02767
02768 if ( bGrowBox )
02769 {
02770 boxmin[0] = bbox.m_min.x;
02771 boxmin[1] = bbox.m_min.y;
02772 boxmin[2] = bbox.m_min.z;
02773 boxmax[0] = bbox.m_max.x;
02774 boxmax[1] = bbox.m_max.y;
02775 boxmax[2] = bbox.m_max.z;
02776 }
02777
02778 return bGrowBox;
02779 }
02780
02781
02782
02783
02784
02785 bool ON_RadialDimension2::GetTightBoundingBox(
02786 ON_BoundingBox& tight_bbox,
02787 int bGrowBox,
02788 const ON_Xform* xform
02789 ) const
02790 {
02791 if ( 4 == m_points.Count() )
02792 {
02793 ON_3dPointArray P(4);
02794 ON_2dPoint uv;
02795
02796 uv = m_points[0];
02797 P.Append( m_plane.PointAt(uv.x,uv.y) );
02798
02799 uv = m_points[1];
02800 P.Append( m_plane.PointAt(uv.x,uv.y) );
02801
02802 uv = m_points[2];
02803 P.Append( m_plane.PointAt(uv.x,uv.y) );
02804
02805 uv = m_points[3];
02806 P.Append( m_plane.PointAt(uv.x,uv.y) );
02807
02808 if ( P.GetTightBoundingBox( tight_bbox, bGrowBox, xform ) )
02809 bGrowBox = true;
02810 }
02811 else if ( bGrowBox && !tight_bbox.IsValid() )
02812 {
02813 tight_bbox.Destroy();
02814 bGrowBox = false;
02815 }
02816
02817 return (0!=bGrowBox);
02818 }
02819
02820 ON_2dPoint ON_RadialDimension2::Dim2dPoint(
02821 int point_index
02822 ) const
02823 {
02824 ON_2dPoint p2;
02825 if ( m_points.Count() < dim_pt_count || point_index < 0 )
02826 {
02827 p2.x = p2.y = ON_UNSET_VALUE;
02828 }
02829 else
02830 {
02831 if ( text_pivot_pt == point_index )
02832 {
02833 point_index = tail_pt_index;
02834 }
02835 if ( point_index < dim_pt_count )
02836 {
02837 p2 = m_points[point_index];
02838 }
02839 else
02840 {
02841 p2.x = p2.y = ON_UNSET_VALUE;
02842 }
02843 }
02844 return p2;
02845 }
02846
02847 ON_3dPoint ON_RadialDimension2::Dim3dPoint(
02848 int point_index
02849 ) const
02850 {
02851 ON_2dPoint p2 = Dim2dPoint(point_index);
02852 return (ON_UNSET_VALUE == p2.x) ? ON_UNSET_POINT : m_plane.PointAt(p2.x,p2.y);
02853 }
02854
02855
02856
02857 bool ON_RadialDimension2::CreateFromPoints(
02858 ON_3dPoint center,
02859 ON_3dPoint arrowtip,
02860 ON_3dVector xaxis,
02861 ON_3dVector normal,
02862 double offset_distance)
02863 {
02864 if ( m_type != ON::dtDimDiameter )
02865 m_type = ON::dtDimRadius;
02866 bool rc = false;
02867 if ( center.IsValid() && arrowtip.IsValid() && normal.IsValid() && !normal.IsZero() && xaxis.IsValid() && !xaxis.IsZero() )
02868 {
02869 ON_Plane plane( center, normal);
02870 double c = xaxis*plane.xaxis;
02871 double s = xaxis*plane.yaxis;
02872 if ( c != 0.0 || s != 0.0 )
02873 {
02874 if ( c <= 0.0 || s != 0.0 )
02875 {
02876 plane.Rotate( s, c, plane.zaxis );
02877 }
02878 m_plane = plane;
02879 ON_2dVector tip;
02880 if ( m_plane.ClosestPointTo(arrowtip,&tip.x,&tip.y) )
02881 {
02882
02883 m_points.SetCapacity(dim_pt_count);
02884 m_points.SetCount(dim_pt_count);
02885
02886 m_points[center_pt_index].Set(0.0,0.0);
02887 m_points[arrow_pt_index] = tip;
02888 tip.Unitize();
02889
02890 m_points[knee_pt_index] = m_points[arrow_pt_index] + offset_distance*tip;
02891 m_points[tail_pt_index] = m_points[knee_pt_index];
02892 if ( m_points[arrow_pt_index].x < 0.0 )
02893 m_points[tail_pt_index].x -= offset_distance;
02894 else
02895 m_points[tail_pt_index].x += offset_distance;
02896 m_plane = plane;
02897 m_userpositionedtext = false;
02898
02899 rc = true;
02900 }
02901 }
02902 }
02903 return rc;
02904 }
02905
02906
02907 double ON_RadialDimension2::NumericValue() const
02908 {
02909 double d = 0.0;
02910 if ( m_points.Count() >= dim_pt_count )
02911 {
02912 d = (m_points[center_pt_index] - m_points[arrow_pt_index]).Length();
02913 if( ON::dtDimDiameter == m_type )
02914 d *= 2.0;
02915 }
02916 return d;
02917 }
02918
02919 int ON_RadialDimension2::StyleIndex() const
02920 {
02921 return ON_Annotation2::Index();
02922 }
02923
02924 void ON_RadialDimension2::SetStyleIndex( int i)
02925 {
02926 ON_Annotation2::SetIndex( i);
02927 }
02928
02929
02930 const wchar_t* ON_RadialDimension2::DefaultRadiusText()
02931 {
02932 static wchar_t defstr[4] = { radiussym,L'<',L'>',0 };
02933 return defstr;
02934 }
02935
02936 const wchar_t* ON_RadialDimension2::DefaultDiameterText()
02937 {
02938 static wchar_t defstr[4] = { diametersym,L'<',L'>',0 };
02939 return defstr;
02940 }
02941
02942
02943 void ON_RadialDimension2::GetV2Form( ON_RadialDimension& dim)
02944 {
02945 ON_Annotation2::ConvertBack( dim);
02946 }
02947
02948
02949 bool ON_RadialDimension2::CreateFromV2(
02950 const ON_Annotation& v2_ann,
02951 const ON_3dmAnnotationSettings& settings,
02952 int dimstyle_index
02953 )
02954 {
02955 bool rc = false;
02956 if( ON::dtDimRadius == v2_ann.m_type || ON::dtDimDiameter == v2_ann.m_type )
02957 {
02958 const ON_SimpleArray<ON_2dPoint>& points = v2_ann.Points();
02959 if ( points.Count() >= 4 )
02960 {
02961 m_points.Reserve(4);
02962 m_points.SetCount(0);
02963 m_points.Append(4,points.Array());
02964 m_plane = v2_ann.m_plane;
02965 m_plane.UpdateEquation();
02966 SetTextValue(v2_ann.UserText());
02967 SetTextFormula(0);
02968 m_userpositionedtext = false;
02969 m_type = v2_ann.Type();
02970 m_textdisplaymode = ( 2 == settings.m_textalign )
02971 ? ON::dtHorizontal
02972 : ON::dtInLine;
02973 m_index = dimstyle_index;
02974 ON_2dVector v = m_points[0];
02975 if ( !v.IsZero() )
02976 {
02977 m_plane.origin = m_plane.PointAt(v.x,v.y);
02978 m_plane.UpdateEquation();
02979 v.Reverse();
02980 m_points[0].Set(0.0,0.0);
02981 m_points[1] += v;
02982 m_points[2] += v;
02983 m_points[3] += v;
02984 }
02985
02986 rc = true;
02987 }
02988 }
02989 return rc;
02990 }
02991
02992
02993
02994
02995
02996 class ON_AngularDimension2Extra : public ON_UserData
02997 {
02998 ON_OBJECT_DECLARE(ON_AngularDimension2Extra);
02999 public:
03000 static ON_AngularDimension2Extra* AngularDimensionExtra(ON_AngularDimension2* pDim);
03001 static const ON_AngularDimension2Extra* AngularDimensionExtra(const ON_AngularDimension2* pDim);
03002
03003 ON_AngularDimension2Extra();
03004 ~ON_AngularDimension2Extra();
03005
03006
03007 void Dump( ON_TextLog& text_log ) const;
03008
03009
03010 unsigned int SizeOf() const;
03011
03012
03013 ON_BOOL32 Write(ON_BinaryArchive& binary_archive) const;
03014
03015
03016 ON_BOOL32 Read(ON_BinaryArchive& binary_archive);
03017
03018
03019 ON_BOOL32 GetDescription( ON_wString& description );
03020
03021
03022 ON_BOOL32 Archive() const;
03023
03024
03025 void Scale( double scale);
03026
03027
03028 double DimpointOffset(int index) const;
03029 void SetDimpointOffset(int index, double offset);
03030
03031
03032
03033
03034
03035 double m_dimpoint_offset[2];
03036 };
03037
03038 ON_OBJECT_IMPLEMENT(ON_AngularDimension2Extra,ON_UserData,"A68B151F-C778-4a6e-BCB4-23DDD1835677");
03039
03040 ON_AngularDimension2Extra* ON_AngularDimension2Extra::AngularDimensionExtra(ON_AngularDimension2* pDim)
03041 {
03042 ON_AngularDimension2Extra* pExtra = 0;
03043 if(pDim)
03044 {
03045 pExtra = ON_AngularDimension2Extra::Cast(pDim->GetUserData(ON_AngularDimension2Extra::m_ON_AngularDimension2Extra_class_id.Uuid()));
03046 if(pExtra == 0)
03047 {
03048 pExtra = new ON_AngularDimension2Extra;
03049 if( pExtra)
03050 {
03051 if(!pDim->AttachUserData(pExtra))
03052 {
03053 delete pExtra;
03054 pExtra = 0;
03055 }
03056 }
03057 }
03058 }
03059 return pExtra;
03060 }
03061
03062 const ON_AngularDimension2Extra* ON_AngularDimension2Extra::AngularDimensionExtra(const ON_AngularDimension2* pDim)
03063 {
03064 return AngularDimensionExtra((ON_AngularDimension2*)pDim);
03065 }
03066
03067 ON_AngularDimension2Extra::ON_AngularDimension2Extra()
03068 {
03069 m_userdata_uuid = ON_AngularDimension2Extra::m_ON_AngularDimension2Extra_class_id.Uuid();
03070 m_application_uuid = ON_opennurbs5_id;
03071
03072
03073
03074 m_userdata_copycount = 1;
03075
03076 m_dimpoint_offset[0] = 0;
03077 m_dimpoint_offset[1] = 0;
03078 }
03079
03080 ON_AngularDimension2Extra::~ON_AngularDimension2Extra()
03081 {
03082 }
03083
03084 void ON_AngularDimension2Extra::Dump( ON_TextLog& text_log ) const
03085 {
03086
03087 }
03088
03089 unsigned int ON_AngularDimension2Extra::SizeOf() const
03090 {
03091 unsigned int sz = ON_UserData::SizeOf();
03092 sz += sizeof(*this) - sizeof(ON_UserData);
03093 return sz;
03094 }
03095
03096 ON_BOOL32 ON_AngularDimension2Extra::Write(ON_BinaryArchive& archive) const
03097 {
03098 int major_version = 1;
03099 int minor_version = 0;
03100 bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,major_version,minor_version);
03101
03102 if(rc) rc = archive.WriteDouble(m_dimpoint_offset[0]);
03103 if(rc) rc = archive.WriteDouble(m_dimpoint_offset[1]);
03104
03105 if(!archive.EndWrite3dmChunk())
03106 rc = false;
03107
03108 return rc;
03109 }
03110
03111 ON_BOOL32 ON_AngularDimension2Extra::Read(ON_BinaryArchive& archive)
03112 {
03113 int major_version = 1;
03114 int minor_version = 0;
03115 bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
03116 if(major_version != 1)
03117 rc = false;
03118
03119 if(rc) rc = archive.ReadDouble(&m_dimpoint_offset[0]);
03120 if(rc) rc = archive.ReadDouble(&m_dimpoint_offset[1]);
03121
03122 if ( !archive.EndRead3dmChunk() )
03123 rc = false;
03124
03125 return rc;
03126 }
03127
03128 ON_BOOL32 ON_AngularDimension2Extra::GetDescription( ON_wString& description)
03129 {
03130 description.Format( "Userdata extension of ON_AngularDimension2");
03131 return true;
03132 }
03133
03134 ON_BOOL32 ON_AngularDimension2Extra::Archive() const
03135 {
03136
03137 return true;
03138 }
03139
03140 void ON_AngularDimension2Extra::Scale(double scale)
03141 {
03142 if( ON_IsValid(scale) && scale > ON_SQRT_EPSILON)
03143 {
03144 m_dimpoint_offset[0] *= scale;
03145 m_dimpoint_offset[1] *= scale;
03146 }
03147 }
03148
03149 double ON_AngularDimension2Extra::DimpointOffset(int index) const
03150 {
03151 if(index == 0)
03152 return m_dimpoint_offset[0];
03153 if(index == 1)
03154 return m_dimpoint_offset[1];
03155 return -1;
03156 }
03157 void ON_AngularDimension2Extra::SetDimpointOffset(int index, double offset)
03158 {
03159 if(index >= 0 && index <= 1)
03160 m_dimpoint_offset[index] = offset;
03161 }
03162
03163
03164 ON_AngularDimension2::ON_AngularDimension2() : m_angle(0.0), m_radius(1.0)
03165 {
03166 m_type = ON::dtDimAngular;
03167 m_textdisplaymode = ON::dtAboveLine;
03168 SetTextValue(DefaultText());
03169 SetTextFormula(0);
03170 m_points.Reserve(ON_AngularDimension2::dim_pt_count);
03171 m_points.SetCount(ON_AngularDimension2::dim_pt_count);
03172 m_points.Zero();
03173
03174
03175
03176
03177
03178
03179
03180
03181 }
03182
03183 ON_AngularDimension2::~ON_AngularDimension2()
03184 {
03185 }
03186
03187
03188 ON_BOOL32 ON_AngularDimension2::IsValid( ON_TextLog* text_log ) const
03189 {
03190 if ( m_type != ON::dtDimAngular )
03191 {
03192 if ( text_log )
03193 {
03194 text_log->Print("ON_AngularDimension2 - m_type != ON::dtDimAngular\n");
03195 }
03196 return false;
03197 }
03198
03199 if ( !ON_Annotation2::IsValid( text_log ))
03200 {
03201 if ( text_log )
03202 {
03203 text_log->Print("ON_AngularDimension2 - invalid ON_Annotation2 base class.\n");
03204 }
03205 return false;
03206 }
03207
03208 if ( 4 != m_points.Count() )
03209 {
03210 if ( text_log )
03211 {
03212 text_log->Print("ON_AngularDimension2 - m_points.Count() = %d (should be 4)\n", m_points.Count() );
03213 }
03214 return false;
03215 }
03216
03217 if ( !ON_IsValid(m_angle) || m_angle <= 0.0 || m_angle > 2.0*ON_PI )
03218 {
03219 if ( text_log )
03220 {
03221 text_log->Print("ON_AngularDimension2 - bogus m_angle = %g\n",m_angle);
03222 }
03223 return false;
03224 }
03225
03226 if ( !ON_IsValid(m_radius) || m_radius <= 0.0 )
03227 {
03228 if ( text_log )
03229 {
03230 text_log->Print("ON_AngularDimension2 - bogus m_radius = %g\n",m_radius);
03231 }
03232 return false;
03233 }
03234
03235 if ( 0.0 == m_points[1].x && 0.0 == m_points[1].y )
03236 {
03237 if ( text_log )
03238 {
03239 text_log->Print("ON_AngularDimension2 - angle dim m_points[1] = center (should be on start ray).\n");
03240 }
03241 return false;
03242 }
03243
03244 if ( 0.0 == m_points[2].x && 0.0 == m_points[2].y )
03245 {
03246 if ( text_log )
03247 {
03248 text_log->Print("ON_AngularDimension2 - angle dim m_points[2] = center (should be on end ray).\n");
03249 }
03250 return false;
03251 }
03252
03253 if ( 0.0 == m_points[3].x && 0.0 == m_points[3].y )
03254 {
03255 if ( text_log )
03256 {
03257 text_log->Print("ON_AngularDimension2 - angle dim m_points[3] = center (should be on interior of arc).\n");
03258 }
03259 return false;
03260 }
03261
03262 double a1 = atan2(m_points[1].y, m_points[1].x);
03263 double a2 = atan2(m_points[2].y, m_points[2].x);
03264 double a3 = atan2(m_points[3].y, m_points[3].x);
03265 if ( a1 < 0.0 )
03266 a1 += 2.0*ON_PI;
03267 while ( a2 <= a1 )
03268 a2 += 2.0*ON_PI;
03269 while ( a3 < a1 )
03270 a3 += 2.0*ON_PI;
03271
03272 if ( fabs(m_angle - (a2-a1)) > ON_ZERO_TOLERANCE + m_angle*ON_SQRT_EPSILON )
03273 {
03274 if ( text_log )
03275 {
03276 text_log->Print("ON_AngularDimension2 - m_angle = %g != %g = (end angle - start angle)\n",m_angle,a2-a1);
03277 }
03278 return false;
03279 }
03280
03281 double r = ON_2dVector(m_points[3]).Length();
03282 if ( fabs(r - m_radius) > ON_ZERO_TOLERANCE + m_radius*ON_SQRT_EPSILON )
03283 {
03284 if ( text_log )
03285 {
03286 text_log->Print("ON_AngularDimension2 - m_radius = %g != %g = |m_point[3])|\n",m_radius,r);
03287 }
03288 return false;
03289 }
03290
03291
03292 if ( a3 > a2 )
03293 {
03294 if ( text_log )
03295 {
03296 text_log->Print("ON_AngularDimension2 - angle dim m_points[3] = not on arc interior.\n");
03297 }
03298 return false;
03299 }
03300
03301 return true;
03302 }
03303
03304
03305
03306 ON_BOOL32 ON_AngularDimension2::GetBBox(
03307 double* boxmax,
03308 double* boxmin,
03309 ON_BOOL32 bGrowBox
03310 ) const
03311 {
03312 ON_BoundingBox bbox;
03313 if ( bGrowBox )
03314 {
03315 bbox.m_min.x = boxmin[0];
03316 bbox.m_min.y = boxmin[1];
03317 bbox.m_min.z = boxmin[2];
03318 bbox.m_max.x = boxmax[0];
03319 bbox.m_max.y = boxmax[1];
03320 bbox.m_max.z = boxmax[2];
03321 if ( !bbox.IsValid() )
03322 {
03323 bbox.Destroy();
03324 bGrowBox = false;
03325 }
03326 }
03327
03328 ON_Arc arc;
03329 if ( GetArc(arc) )
03330 {
03331 if ( arc.GetTightBoundingBox(bbox,bGrowBox?true:false,0) )
03332 bGrowBox = true;
03333 }
03334
03335 if ( bGrowBox )
03336 {
03337 boxmin[0] = bbox.m_min.x;
03338 boxmin[1] = bbox.m_min.y;
03339 boxmin[2] = bbox.m_min.z;
03340 boxmax[0] = bbox.m_max.x;
03341 boxmax[1] = bbox.m_max.y;
03342 boxmax[2] = bbox.m_max.z;
03343 }
03344
03345 return bGrowBox;
03346 }
03347
03348
03349
03350
03351
03352 bool ON_AngularDimension2::GetTightBoundingBox(
03353 ON_BoundingBox& tight_bbox,
03354 int bGrowBox,
03355 const ON_Xform* xform
03356 ) const
03357 {
03358 ON_Arc arc;
03359 if ( GetArc(arc) )
03360 {
03361 if ( arc.GetTightBoundingBox(tight_bbox,bGrowBox,xform) )
03362 bGrowBox = true;
03363 }
03364 else if ( bGrowBox && !tight_bbox.IsValid() )
03365 {
03366 tight_bbox.Destroy();
03367 bGrowBox = false;
03368 }
03369
03370 return (0!=bGrowBox);
03371
03372 }
03373
03374 ON_2dPoint ON_AngularDimension2::Dim2dPoint( int point_index ) const
03375 {
03376 ON_2dPoint p2;
03377 if ( m_points.Count() < dim_pt_count || point_index < 0 )
03378 {
03379 p2.x = p2.y = ON_UNSET_VALUE;
03380 }
03381 else
03382 {
03383 if ( text_pivot_pt == point_index )
03384 {
03385 point_index = m_userpositionedtext
03386 ? userpositionedtext_pt_index
03387 : arcmid_pt;
03388 }
03389
03390 if ( point_index < dim_pt_count )
03391 {
03392 p2 = m_points[point_index];
03393 }
03394 else
03395 {
03396 switch(point_index)
03397 {
03398 case arcstart_pt:
03399 p2.x = m_radius;
03400 p2.y = 0.0;
03401 break;
03402 case arcend_pt:
03403 p2.x = m_radius*cos(m_angle);
03404 p2.y = m_radius*sin(m_angle);
03405 break;
03406 case arccenter_pt:
03407 p2.x = 0.0;
03408 p2.y = 0.0;
03409 break;
03410 case arcmid_pt:
03411 p2.x = m_radius*cos(0.5*m_angle);
03412 p2.y = m_radius*sin(0.5*m_angle);
03413 break;
03414 case extension0_pt:
03415 {
03416 p2 = m_points[start_pt_index];
03417 double dp0 = DimpointOffset(0);
03418 if(dp0 >= 0)
03419 {
03420 ON_2dVector v2 = (ON_2dVector)p2;
03421 v2.Unitize();
03422 p2 = (ON_2dPoint)v2 * dp0;
03423 }
03424 }
03425 break;
03426 case extension1_pt:
03427 {
03428 p2 = m_points[end_pt_index];
03429 double dp1 = DimpointOffset(1);
03430 if(dp1 >= 0)
03431 {
03432 ON_2dVector v2 = (ON_2dVector)p2;
03433 v2.Unitize();
03434 p2 = (ON_2dPoint)v2 * dp1;
03435 }
03436 }
03437 break;
03438 default:
03439 p2.x = p2.y = ON_UNSET_VALUE;
03440 break;
03441 }
03442 }
03443 }
03444 return p2;
03445 }
03446
03447 ON_3dPoint ON_AngularDimension2::Dim3dPoint( int point_index ) const
03448 {
03449 ON_2dPoint p2 = Dim2dPoint(point_index);
03450 return (ON_UNSET_VALUE == p2.x) ? ON_UNSET_POINT : m_plane.PointAt(p2.x,p2.y);
03451 }
03452
03453
03454 ON_BOOL32 ON_AngularDimension2::Write( ON_BinaryArchive& file ) const
03455 {
03456
03457
03458
03459
03460
03461 bool rc = false;
03462 bool bInChunk = (file.Archive3dmVersion() >= 5);
03463 if ( bInChunk )
03464 {
03465 rc = file.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
03466 if ( !rc )
03467 return false;
03468 }
03469 else
03470 {
03471 rc = true;
03472 }
03473
03474 while(rc)
03475 {
03476 rc = ON_Annotation2::Write(file)?true:false;
03477 if (!rc) break;
03478 rc = file.WriteDouble( m_angle);
03479 if (!rc) break;
03480 rc = file.WriteDouble( m_radius);
03481 if (!rc) break;
03482 if ( !bInChunk )
03483 break;
03484
03485
03486
03487
03488 break;
03489 }
03490
03491 if ( bInChunk )
03492 {
03493 if (!file.EndWrite3dmChunk())
03494 rc = false;
03495 }
03496
03497 return rc;
03498 }
03499
03500 ON_BOOL32 ON_AngularDimension2::Read( ON_BinaryArchive& file )
03501 {
03502
03503
03504
03505 int major_version = 0;
03506 int minor_version = 0;
03507 bool rc = false;
03508 bool bInChunk = (file.Archive3dmVersion() >= 5 && file.ArchiveOpenNURBSVersion() >= 200710180);
03509 if ( bInChunk )
03510 {
03511 rc = file.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
03512 if ( !rc )
03513 return false;
03514 }
03515 else
03516 {
03517 rc = true;
03518 }
03519
03520 while(rc)
03521 {
03522 rc = ON_Annotation2::Read(file)?true:false;
03523 if (!rc) break;
03524 rc = file.ReadDouble( &m_angle);
03525 if (!rc) break;
03526 rc = file.ReadDouble( &m_radius);
03527 if (!rc) break;
03528 if ( !bInChunk || minor_version <= 0 )
03529 break;
03530
03531
03532
03533
03534 break;
03535 }
03536
03537 if ( bInChunk )
03538 {
03539
03540
03541
03542
03543 if ( !file.EndRead3dmChunk() )
03544 rc = false;
03545 }
03546 return rc;
03547 }
03548
03549 static ON_BOOL32 VectorAngle( const ON_2dVector& v, double& angle)
03550 {
03551 if( v.IsTiny())
03552 return false;
03553
03554 angle = atan2( v.y, v.x);
03555
03556 if( angle < 0.0)
03557 angle += 2.0 * ON_PI;
03558
03559 if( angle > 2.0 * ON_PI)
03560 angle -= 2.0 * ON_PI;
03561
03562 return true;
03563 }
03564
03565 bool ON_AngularDimension2::CreateFromV2(
03566 const ON_Annotation& v2_ann,
03567 const ON_3dmAnnotationSettings& settings,
03568 int dimstyle_index
03569 )
03570 {
03571 if( ON::dtDimAngular != v2_ann.Type() )
03572 return false;
03573
03574 if ( v2_ann.m_points.Count() < 3 )
03575 return false;
03576
03577 ON_Plane plane = v2_ann.m_plane;
03578 plane.UpdateEquation();
03579 if ( !plane.IsValid() )
03580 return false;
03581
03582 ON_2dVector p0 = v2_ann.m_points[0];
03583 ON_2dVector p1 = v2_ann.m_points[1];
03584 ON_2dPoint tp = v2_ann.m_points[2];
03585 if ( !p0.IsValid() || !p1.IsValid() || p0.IsZero() || p1.IsZero() )
03586 return false;
03587
03588 bool bUserPositionedText = v2_ann.UserPositionedText() && tp.IsValid();
03589
03590 if ( p0.x <= 0.0 && 0.0 != p0.y )
03591 {
03592 bUserPositionedText = false;
03593 ON_3dPoint P0 = plane.PointAt(p0.x,p0.y);
03594 ON_3dPoint P1 = plane.PointAt(p1.x,p1.y);
03595 plane.xaxis = P0-plane.origin;
03596 if ( !plane.xaxis.Unitize() )
03597 return false;
03598 plane.yaxis = ON_CrossProduct( plane.zaxis, plane.xaxis );
03599 plane.yaxis.Unitize();
03600 if ( !plane.IsValid() )
03601 return false;
03602 p0.x = p0.Length();
03603 p0.y = 0.0;
03604 if ( !plane.ClosestPointTo(P1,&p1.x,&p1.y) )
03605 return false;
03606 }
03607
03608 if ( p1.x >= 0.0 && p1.y == 0.0 )
03609 return false;
03610
03611 double angle = atan2(p1.y,p1.x);
03612 if ( angle < 0.0 )
03613 angle += 2.0*ON_PI;
03614
03615 double radius = 0.5*(p0.Length() + p1.Length());
03616
03617 const ON_AngularDimension* v2_angdim = ON_AngularDimension::Cast(&v2_ann);
03618 if ( v2_angdim && v2_angdim->Radius() > 0.0 )
03619 radius = v2_angdim->Radius();
03620
03621 if ( !bUserPositionedText )
03622 {
03623 tp.x = radius*cos(0.5*angle);
03624 tp.y = radius*sin(0.5*angle);
03625 }
03626
03627 ON_2dPoint arcpt( radius*cos(angle/3.0), radius*sin(angle/3.0) );
03628
03629 m_plane = plane;
03630 m_points.SetCapacity(4);
03631 m_points.SetCount(4);
03632 m_points[0] = tp;
03633 m_points[1] = p0;
03634 m_points[2] = p1;
03635 m_points[3] = arcpt;
03636 m_angle = angle;
03637 m_radius = radius;
03638
03639 SetTextValue(v2_ann.UserText());
03640 SetTextFormula(0);
03641 m_userpositionedtext = bUserPositionedText;
03642
03643 switch( settings.m_textalign)
03644 {
03645 case 1:
03646 m_textdisplaymode = ON::dtInLine;
03647 break;
03648 case 2:
03649 m_textdisplaymode = ON::dtHorizontal;
03650 break;
03651 default:
03652 m_textdisplaymode = ON::dtAboveLine;
03653 break;
03654 }
03655
03656 m_index = dimstyle_index;
03657
03658 return true;
03659 }
03660
03661 bool ON_AngularDimension2::CreateFromArc( const ON_Arc& arc )
03662 {
03663
03664 bool rc = arc.IsValid();
03665 if (rc)
03666 {
03667 ON_3dPoint C = arc.Center();
03668 ON_3dPoint S = arc.StartPoint();
03669 ON_3dPoint E = arc.EndPoint();
03670 ON_3dPoint M = arc.MidPoint();
03671 ON_3dVector N = arc.Plane().zaxis;
03672
03673 rc = CreateFromPoints(C, S, E, M, N);
03674 }
03675
03676 return rc;
03677 }
03678
03679 bool ON_AngularDimension2::GetArc( ON_Arc& arc ) const
03680 {
03681 bool rc = false;
03682
03683
03684 if ( ON_IsValid(m_radius) && m_radius > ON_SQRT_EPSILON
03685 && ON_IsValid(m_angle) && m_angle > 0.0 && m_angle <= 2.0*ON_PI
03686 && m_plane.origin.IsValid()
03687 && m_plane.xaxis.IsValid()
03688 && m_plane.yaxis.IsValid()
03689 && m_plane.zaxis.IsValid()
03690 && fabs( m_plane.zaxis.Length() - 1.0 ) <= ON_SQRT_EPSILON
03691 && 4 == m_points.Count()
03692 )
03693 {
03694 ON_3dVector X = m_plane.PointAt( m_points[start_pt_index].x, m_points[start_pt_index].y ) - m_plane.origin;
03695 if ( fabs(X.Length()-1.0) <= ON_SQRT_EPSILON || X.Unitize() )
03696 {
03697 if ( fabs(X*m_plane.zaxis) <= ON_SQRT_EPSILON )
03698 {
03699 ON_3dVector Y = ON_CrossProduct( m_plane.zaxis, X );
03700 if ( fabs(Y.Length()-1.0) <= ON_SQRT_EPSILON || Y.Unitize() )
03701 {
03702 arc.plane = m_plane;
03703 arc.plane.xaxis = X;
03704 arc.plane.yaxis = Y;
03705 arc.plane.UpdateEquation();
03706 arc.SetAngleIntervalRadians( ON_Interval(0.0,m_angle) );
03707 arc.radius = m_radius;
03708 rc = true;
03709 }
03710 }
03711 }
03712 }
03713
03714 return rc;
03715 }
03716
03717 bool ON_AngularDimension2::GetExtensionLines(ON_Line extensions[2]) const
03718 {
03719 bool rc = false;
03720
03721 if ( ON_IsValid(m_radius) && m_radius > ON_SQRT_EPSILON
03722 && ON_IsValid(m_angle) && m_angle > 0.0 && m_angle <= 2.0*ON_PI
03723 && m_plane.origin.IsValid()
03724 && m_plane.xaxis.IsValid()
03725 && m_plane.yaxis.IsValid()
03726 && m_plane.zaxis.IsValid()
03727 && fabs( m_plane.zaxis.Length() - 1.0 ) <= ON_SQRT_EPSILON
03728 && 4 == m_points.Count()
03729 )
03730 {
03731 const ON_AngularDimension2Extra* pDE = ON_AngularDimension2Extra::AngularDimensionExtra(this);
03732 if(pDE != 0)
03733 {
03734 double exoffset0 = pDE->DimpointOffset(0);
03735 double exoffset1 = pDE->DimpointOffset(1);
03736 ON_3dPoint e00, e01, e10, e11;
03737 e00 = m_plane.PointAt(m_points[start_pt_index].x, m_points[start_pt_index].y);
03738 e10 = m_plane.PointAt(m_points[end_pt_index].x, m_points[end_pt_index].y);
03739 ON_3dVector X = e00 - m_plane.origin;
03740 ON_3dVector Y = e10 - m_plane.origin;
03741 if((fabs(X.Length()-1.0) <= ON_SQRT_EPSILON || X.Unitize()) &&
03742 (fabs(Y.Length()-1.0) <= ON_SQRT_EPSILON || Y.Unitize()))
03743 {
03744 if((fabs(X*m_plane.zaxis) <= ON_SQRT_EPSILON) &&
03745 (fabs(Y*m_plane.zaxis) <= ON_SQRT_EPSILON))
03746 {
03747 e00 = m_plane.origin + X * exoffset0;
03748 e10 = m_plane.origin + Y * exoffset1;
03749 e01 = m_plane.origin + X * m_radius;
03750 e11 = m_plane.origin + Y * m_radius;
03751
03752 extensions[0].from = e00;
03753 extensions[0].to = e01;
03754 extensions[1].from = e10;
03755 extensions[1].to = e11;
03756 rc = true;
03757 }
03758 }
03759 }
03760 }
03761 return rc;
03762 }
03763
03764
03765 bool ON_AngularDimension2::CreateFromPoints(
03766 const ON_3dPoint& pc,
03767 const ON_3dPoint& p0in,
03768 const ON_3dPoint& p1in,
03769 ON_3dPoint& arcpt,
03770 ON_3dVector& Normal)
03771 {
03772 ON_3dPoint p0, p1;
03773 p0 = p0in;
03774 p1 = p1in;
03775
03776 ON_Plane plane( pc, Normal);
03777
03778 ON_2dPoint pa, pp0, pp1;
03779
03780 if( !plane.ClosestPointTo( p0, &pp0.x, &pp0.y))
03781 return false;
03782
03783
03784 ON_2dVector v0( pp0);
03785 v0.Unitize();
03786 plane.Rotate( v0.y, v0.x, plane.Normal());
03787
03788 if( !plane.ClosestPointTo( p0, &pp0.x, &pp0.y))
03789 return false;
03790
03791 if( !plane.ClosestPointTo( arcpt, &pa.x, &pa.y))
03792 return false;
03793
03794 if( !plane.ClosestPointTo( p1, &pp1.x, &pp1.y))
03795 return false;
03796
03797 double a1, aa;
03798 if( !VectorAngle( ON_2dVector( pp1), a1) || !VectorAngle( ON_2dVector( pa), aa))
03799 return false;
03800
03801 if( aa > a1)
03802 {
03803
03804 v0.Set( pp1.x, pp1.y);
03805 v0.Unitize();
03806 plane.Rotate( v0.y, v0.x, plane.Normal());
03807
03808 if( !plane.ClosestPointTo( arcpt, &pa.x, &pa.y))
03809 return false;
03810 if( !plane.ClosestPointTo( p1, &pp0.x, &pp0.y))
03811 return false;
03812 if( !plane.ClosestPointTo( p0, &pp1.x, &pp1.y))
03813 return false;
03814 }
03815
03816 VectorAngle( ON_2dVector( pp1), a1);
03817
03818 SetAngle( a1);
03819 SetRadius( ON_2dVector( pa).Length());
03820
03821 ON_AngularDimension2Extra* pDE = ON_AngularDimension2Extra::AngularDimensionExtra(this);
03822 if(pDE != 0)
03823 {
03824 double os = ((ON_2dVector)pp0).Length();
03825 pDE->SetDimpointOffset(0, os);
03826 os = ((ON_2dVector)pp1).Length();
03827 pDE->SetDimpointOffset(1, os);
03828 }
03829
03830 ReservePoints( 4);
03831 SetPlane( plane);
03832 SetPoint( 1, pp0);
03833 SetPoint( 2, pp1);
03834 SetPoint( 3, pa);
03835
03836
03837 return true;
03838 }
03839
03840 void ON_AngularDimension2::SetAngle( double angle)
03841 {
03842 m_angle = angle;
03843 }
03844
03845 double ON_AngularDimension2::Angle() const
03846 {
03847 return m_angle;
03848 }
03849
03850 void ON_AngularDimension2::SetRadius( double radius)
03851 {
03852 m_radius = radius;
03853 }
03854
03855 double ON_AngularDimension2::Radius() const
03856 {
03857 return m_radius;
03858 }
03859
03860 double ON_AngularDimension2::NumericValue() const
03861 {
03862
03863 return (m_angle*180.0/ON_PI);
03864 }
03865
03866 int ON_AngularDimension2::StyleIndex() const
03867 {
03868 return ON_Annotation2::Index();
03869 }
03870
03871 void ON_AngularDimension2::SetStyleIndex( int i)
03872 {
03873 ON_Annotation2::SetIndex( i);
03874 }
03875
03876 const wchar_t* ON_AngularDimension2::DefaultText()
03877 {
03878 return L"<>";
03879 }
03880
03881 void ON_AngularDimension2::ConvertBack(
03882 ON_AngularDimension2&
03883 )
03884 {
03885 }
03886
03887
03888 void ON_AngularDimension2::GetV2Form( ON_AngularDimension& dim)
03889 {
03890 ON_Annotation2::ConvertBack( dim);
03891 dim.SetPoint(0, Point(1));
03892 dim.SetPoint(1, Point(2));
03893 dim.SetPoint(2, Point(3));
03894 dim.SetPoint(3, Point(0));
03895 dim.SetAngle( Angle());
03896 dim.SetRadius( Radius());
03897 }
03898
03899
03900
03901 static void OrientRectHelper( ON_2dVector corners[4] )
03902 {
03903 double twice_area = 0.0;
03904 ON_2dVector p0, p1;
03905 int i;
03906 p1 = corners[3];
03907 for ( i = 0; i < 4; i++ )
03908 {
03909 p0 = p1;
03910 p1 = corners[i];
03911 twice_area += (p0.x-p1.x)*(p0.y+p1.y);
03912 }
03913 if ( twice_area < 0.0 )
03914 {
03915 p1 = corners[1];
03916 corners[1] = corners[3];
03917 corners[3] = p1;
03918 }
03919 }
03920
03921 int ON_AngularDimension2::GetDimensionArcSegments(
03922 ON_RECT gdi_text_rect,
03923 int gdi_height_of_I,
03924 ON_Xform gdi_to_world,
03925 const ON_DimStyle& dimstyle,
03926 double dimscale,
03927 const ON_Viewport* vp,
03928 double a[6],
03929 bool& bInside
03930 ) const
03931 {
03932 int rc = 0;
03933
03934 a[0] = 0.0;
03935 a[1] = 0.0;
03936
03937 if ( m_angle <= 0.0 || !ON_IsValid(m_angle) )
03938 return 0;
03939
03940 a[1] = m_angle;
03941
03942 if ( m_radius <= 0.0 || !ON_IsValid(m_radius) || m_angle >= 2.0*ON_PI )
03943 return 0;
03944
03945 if ( 0 == gdi_height_of_I )
03946 {
03947
03948 gdi_height_of_I = (165*ON_Font::normal_font_height)/256;
03949 }
03950
03951 if ( 0.0 == dimscale )
03952 {
03953 dimscale = 1.0;
03954 }
03955
03956 double t;
03957
03958 ON::eTextDisplayMode textdisplay = ON::TextDisplayMode(dimstyle.TextAlignment());
03959 if ( ON::dtHorizontal == textdisplay && !vp )
03960 textdisplay = ON::dtInLine;
03961
03962 const double text_height_of_I = dimscale*dimstyle.TextHeight();
03963 const double textgap = dimscale*dimstyle.TextGap();
03964 const double gdi_to_plane_scale = text_height_of_I/gdi_height_of_I;
03965 const double textwidth = fabs(gdi_to_plane_scale*(gdi_text_rect.right - gdi_text_rect.left));
03966 const double arrowwidth = fabs(dimscale*dimstyle.ArrowSize());
03967 const double tailwidth = 0.5*arrowwidth;
03968 const double dimextension = fabs(dimscale*dimstyle.DimExtension());
03969 const double a0 = 0.0;
03970 const double a1 = m_angle;
03971
03972 double sin_angle = 0.5*dimextension/m_radius;
03973 if ( sin_angle > 1.0 ) sin_angle = 1.0; else if (sin_angle < -1.0) sin_angle = -1.0;
03974 const double dimextension_angle = 2.0*asin(sin_angle);
03975
03976 sin_angle = 0.5*arrowwidth/m_radius;
03977 if ( sin_angle > 1.0 ) sin_angle = 1.0; else if (sin_angle < -1.0) sin_angle = -1.0;
03978 const double arrowangle = 2.0*asin(sin_angle);
03979
03980 sin_angle = 0.5*tailwidth/m_radius;
03981 if ( sin_angle > 1.0 ) sin_angle = 1.0; else if (sin_angle < -1.0) sin_angle = -1.0;
03982 const double tailangle = 2.0*asin(sin_angle);
03983
03984
03985 double arrow_angle = arrowangle + tailangle;
03986 if(arrow_angle > ON_PI * 0.5)
03987 arrow_angle = ON_PI * 0.5;
03988 if ( m_radius <= arrowwidth + tailwidth || m_radius*(a1-a0) < 2.0*(arrowwidth) + tailwidth )
03989 {
03990
03991
03992 a[0] = a0;
03993 a[1] = a0 - arrow_angle;
03994 a[2] = a1 + arrow_angle;
03995 a[3] = a1;
03996 a[4] = a0;
03997 a[5] = a1;
03998 if( dimextension_angle != 0.0)
03999 {
04000 a[0] += dimextension_angle;
04001 a[3] -= dimextension_angle;
04002 }
04003 bInside = false;
04004 return 2;
04005 }
04006
04007 if ( ON::dtInLine == textdisplay && m_radius <= 0.5*(textwidth+2.0*textgap) )
04008 {
04009
04010 a[0] = a0;
04011 a[1] = a0 - arrow_angle;
04012 a[2] = a1 + arrow_angle;
04013 a[3] = a1;
04014 a[4] = a0;
04015 a[5] = a1;
04016 if( dimextension_angle != 0.0)
04017 {
04018 a[0] += dimextension_angle;
04019 a[3] -= dimextension_angle;
04020 }
04021 bInside = false;
04022 return 2;
04023 }
04024
04025 sin_angle = 0.5*(textwidth+2.0*textgap)/m_radius;
04026 if ( sin_angle > 1.0 ) sin_angle = 1.0; else if (sin_angle < -1.0) sin_angle = -1.0;
04027 const double textangle = (ON::dtInLine == textdisplay && !m_userpositionedtext )
04028 ? 2.0*asin(sin_angle)
04029 : 0.0;
04030
04031 if ( (a1-a0) <= 2.0*(arrow_angle) + textangle )
04032 {
04033
04034 a[0] = a0;
04035 a[1] = a0 - arrow_angle;
04036 a[2] = a1 + arrow_angle;
04037 a[3] = a1;
04038 a[4] = a0;
04039 a[5] = a1;
04040 if( dimextension_angle != 0.0)
04041 {
04042 a[0] += dimextension_angle;
04043 a[3] -= dimextension_angle;
04044 }
04045 bInside = false;
04046 return 2;
04047 }
04048
04049 if ( (ON::dtHorizontal == textdisplay && vp) || m_userpositionedtext )
04050 {
04051
04052 double aa0, aa1, aa, r0, r1, t, tt[2];
04053 ON_3dPoint P, R, c[2];
04054 ON_2dVector corners[4], N;
04055 ON_Line ray;
04056 int i,xi, xrc;
04057 const ON_Circle circle(ON_xy_plane,1.0);
04058
04059 ON_3dVector vp_zaxis = (ON::dtHorizontal == textdisplay && vp)
04060 ? vp->CameraZ()
04061 : m_plane.zaxis;
04062
04063
04064
04065
04066 double gdi_gap = fabs(textgap/gdi_to_plane_scale)-12;
04067 if(gdi_gap < 0.0) gdi_gap = 0.0;
04068
04069 R.Set(gdi_text_rect.left-gdi_gap,gdi_text_rect.bottom+gdi_gap,0.0);
04070 ray.from = gdi_to_world*R; ray.to = ray.from + vp_zaxis;
04071 P = ( ON_Intersect(ray,m_plane,&t) ) ? ray.PointAt(t) : ray.from;
04072 m_plane.ClosestPointTo(P,&corners[0].x,&corners[0].y);
04073
04074 R.Set(gdi_text_rect.right+gdi_gap,gdi_text_rect.bottom+gdi_gap,0.0);
04075 ray.from = gdi_to_world*R; ray.to = ray.from + vp_zaxis;
04076 P = ( ON_Intersect(ray,m_plane,&t) ) ? ray.PointAt(t) : ray.from;
04077 m_plane.ClosestPointTo(P,&corners[1].x,&corners[1].y);
04078
04079 R.Set(gdi_text_rect.right+gdi_gap,gdi_text_rect.top-gdi_gap,0.0);
04080 ray.from = gdi_to_world*R; ray.to = ray.from + vp_zaxis;
04081 P = ( ON_Intersect(ray,m_plane,&t) ) ? ray.PointAt(t) : ray.from;
04082 m_plane.ClosestPointTo(P,&corners[2].x,&corners[2].y);
04083
04084 R.Set(gdi_text_rect.left-gdi_gap,gdi_text_rect.top-gdi_gap,0.0);
04085 ray.from = gdi_to_world*R; ray.to = ray.from + vp_zaxis;
04086 P = ( ON_Intersect(ray,m_plane,&t) ) ? ray.PointAt(t) : ray.from;
04087 m_plane.ClosestPointTo(P,&corners[3].x,&corners[3].y);
04088
04089
04090 OrientRectHelper(corners);
04091
04092 aa0 = a0;
04093 aa1 = a1;
04094 P.Set(cos(a0)*m_radius,sin(a0)*m_radius,0.0);
04095 R.Set(cos(a1)*m_radius,sin(a1)*m_radius,0.0);
04096 for ( i = 0; i < 4; i++ )
04097 {
04098 N.x = (corners[i].y-corners[(i+1)%4].y);
04099 N.y = (corners[(i+1)%4].x-corners[i].x);
04100 if ( !N.Unitize() )
04101 continue;
04102 if ( (P.x - corners[i].x)*N.x + (P.y - corners[i].y)*N.y < 0.0 )
04103 {
04104
04105 aa0 = ON_UNSET_VALUE;
04106 }
04107 if ( (R.x - corners[i].x)*N.x + (R.y - corners[i].y)*N.y < 0.0 )
04108 {
04109
04110 aa1 = ON_UNSET_VALUE;
04111 }
04112 }
04113
04114 if ( ON_UNSET_VALUE == aa0 )
04115 aa0 = aa1;
04116 else if ( ON_UNSET_VALUE == aa1 )
04117 aa1 = aa0;
04118
04119 r1 = corners[3].Length() - m_radius;
04120 ray.to.x = corners[3].x/m_radius; ray.to.y = corners[3].y/m_radius;
04121 ray.to.z = ray.from.z = 0.0;
04122 for ( i = 0; i < 4; i++ )
04123 {
04124 r0 = r1;
04125 r1 = corners[i].Length() - m_radius;
04126 ray.from = ray.to;
04127 ray.to.x = corners[i].x/m_radius; ray.to.y = corners[i].y/m_radius;
04128 if ( r0 < 0.0 && r1 < 0.0 )
04129 {
04130 continue;
04131 }
04132 if ( r0 > 0.0 && r1 > 0.0 )
04133 {
04134 if ( !ray.ClosestPointTo(ON_2dPoint(0.0,0.0),&t ) )
04135 continue;
04136 R = ray.PointAt(t);
04137 if ( R.x*R.x + R.y*R.y >= 1.0 )
04138 continue;
04139 }
04140
04141
04142 xrc = 0;
04143 if ( 0.0 == r0 )
04144 tt[xrc++] = 0.0;
04145
04146 if ( 0.0 == r1 )
04147 tt[xrc++] = 1.0;
04148
04149 if ( 0 == xrc )
04150 xrc = ON_Intersect(ray,circle,&tt[0],c[0],&tt[1],c[1]);
04151
04152 if ( xrc < 1 || xrc > 2 )
04153 continue;
04154
04155 for ( xi = 0; xi < xrc; xi++ )
04156 {
04157 if ( tt[xi] < 0.0 || tt[xi] > 1.0 )
04158 continue;
04159
04160 P = ray.PointAt(tt[xi]);
04161 if ( 0.0 == P.x && 0.0 == P.y )
04162 continue;
04163
04164 aa = atan2(P.y,P.x);
04165 if ( aa < a0 ) aa += 2.0*ON_PI; else if ( aa > a1 ) aa -= 2.0*ON_PI;
04166 if ( aa < a0 || aa > a1 )
04167 {
04168 continue;
04169 }
04170 if ( ON_UNSET_VALUE == aa0 )
04171 aa0 = aa1 = aa;
04172 else if ( aa < aa0 )
04173 aa0 = aa;
04174 else if ( aa > aa1 )
04175 aa1 = aa;
04176 }
04177 }
04178 if ( ON_UNSET_VALUE != aa0 && ON_UNSET_VALUE != aa1
04179 && a0 <= aa0 && aa0 < aa1 && aa1 <= a1 )
04180 {
04181 t = arrow_angle;
04182 if ( aa0 < a0+t && aa1 > a1-t )
04183 {
04184
04185
04186 a[0] = a0;
04187 a[1] = a0 - arrow_angle;
04188 a[2] = a1 + arrow_angle;
04189 a[3] = a1;
04190 a[4] = a0;
04191 a[5] = a1;
04192 if( dimextension_angle != 0.0)
04193 {
04194 a[0] += dimextension_angle;
04195 a[3] -= dimextension_angle;
04196 }
04197 bInside = false;
04198 rc = 2;
04199 }
04200 else
04201 {
04202 if ( aa0 < a0+t ) aa0 = a0+t;
04203 if ( aa1 > a1-t ) aa1 = a1-t;
04204 if ( a0 < aa0 && aa0 < aa1 && aa1 < a1 )
04205 {
04206
04207
04208 a[0] = a0;
04209 a[1] = aa0;
04210 a[2] = aa1;
04211 a[3] = a1;
04212 a[4] = a0;
04213 a[5] = a1;
04214 if( dimextension_angle != 0.0)
04215 {
04216 a[0] -= dimextension_angle;
04217 a[3] += dimextension_angle;
04218 }
04219 bInside = true;
04220 rc = 2;
04221 }
04222 else
04223 {
04224
04225
04226 a[0] = a0;
04227 a[1] = a1;
04228 a[2] = a0;
04229 a[3] = a1;
04230 a[4] = a0;
04231 a[5] = a1;
04232 if( dimextension_angle != 0.0)
04233 {
04234 a[0] -= dimextension_angle;
04235 a[1] += dimextension_angle;
04236 }
04237 bInside = true;
04238 rc = 1;
04239 }
04240 }
04241 }
04242 else
04243 {
04244
04245 a[0] = a0;
04246 a[1] = a1;
04247 a[2] = a0;
04248 a[3] = a1;
04249 a[4] = a0;
04250 a[5] = a1;
04251 if( dimextension_angle != 0.0)
04252 {
04253 a[0] -= dimextension_angle;
04254 a[1] += dimextension_angle;
04255 }
04256 bInside = true;
04257 rc = 1;
04258 }
04259 }
04260 else if ( ON::dtAboveLine == textdisplay || m_userpositionedtext )
04261 {
04262
04263 a[0] = a0;
04264 a[1] = a1;
04265 a[2] = a0;
04266 a[3] = a1;
04267 a[4] = a0;
04268 a[5] = a1;
04269 if( dimextension_angle != 0.0)
04270 {
04271 a[0] -= dimextension_angle;
04272 a[1] += dimextension_angle;
04273 }
04274 bInside = true;
04275 rc = 1;
04276 }
04277 else if ( ON::dtInLine == textdisplay )
04278 {
04279
04280 t = 0.5*((a1-a0) - textangle);
04281 a[0] = a0;
04282 a[1] = a0+t;
04283 a[2] = a1-t;
04284 a[3] = a1;
04285 a[4] = a0;
04286 a[5] = a1;
04287 if( dimextension_angle != 0.0)
04288 {
04289 a[0] -= dimextension_angle;
04290 a[3] += dimextension_angle;
04291 }
04292 bInside = true;
04293 rc = 2;
04294 }
04295
04296 return rc;
04297 }
04298
04299 double ON_AngularDimension2::DimpointOffset(int index) const
04300 {
04301 const ON_AngularDimension2Extra* pDE = ON_AngularDimension2Extra::AngularDimensionExtra(this);
04302 if(pDE != 0)
04303 return pDE->DimpointOffset(index);
04304 return -1.0;
04305 }
04306 void ON_AngularDimension2::SetDimpointOffset(int index, double offset)
04307 {
04308 ON_AngularDimension2Extra* pDE = ON_AngularDimension2Extra::AngularDimensionExtra(this);
04309 if(pDE != 0)
04310 pDE->SetDimpointOffset(index, offset);
04311 }
04312
04313
04314
04315 ON_OrdinateDimension2::ON_OrdinateDimension2()
04316 {
04317 m_type = ON::dtDimOrdinate;
04318 SetTextValue(DefaultText());
04319 SetTextFormula(0);
04320 m_direction = -1;
04321 m_points.Reserve(ON_OrdinateDimension2::dim_pt_count);
04322 m_points.SetCount(ON_OrdinateDimension2::dim_pt_count);
04323 m_points.Zero();
04324 m_kink_offset_0 = ON_UNSET_VALUE;
04325 m_kink_offset_1 = ON_UNSET_VALUE;
04326 }
04327
04328 ON_OrdinateDimension2::~ON_OrdinateDimension2()
04329 {
04330 }
04331
04332 ON_BOOL32 ON_OrdinateDimension2::Transform( const ON_Xform& xform )
04333 {
04334 bool rc = xform.IsIdentity();
04335 if ( !rc)
04336 {
04337 return ON_Annotation2::Transform(xform);
04338 }
04339 return rc;
04340 }
04341
04342 ON_2dPoint ON_OrdinateDimension2::Dim2dPoint( int point_index, double default_offset) const
04343 {
04344 ON_2dPoint p2( ON_UNSET_VALUE, ON_UNSET_VALUE);
04345 int dir = m_direction;
04346 if( dir == -1 && ( point_index == offset_pt_0 || point_index == offset_pt_1))
04347 {
04348 if( fabs( m_points[definition_pt_index].y - m_points[leader_end_pt_index].y) >
04349 fabs( m_points[definition_pt_index].x - m_points[leader_end_pt_index].x))
04350 dir = 0;
04351 else
04352 dir = 1;
04353 }
04354
04355 if( point_index >= 0 && point_index < dim_pt_count && m_points.Count() == dim_pt_count)
04356 {
04357 p2 = m_points[point_index];
04358 }
04359 else if( point_index == text_pivot_pt)
04360 {
04361
04362 }
04363 else if( point_index == offset_pt_0)
04364 {
04365 double offset;
04366 if( m_kink_offset_0 == ON_UNSET_VALUE)
04367 offset = default_offset;
04368 else
04369 offset = m_kink_offset_0;
04370
04371 if( dir == x)
04372 {
04373 p2 = m_points[leader_end_pt_index];
04374 if( p2.y > m_points[definition_pt_index].y)
04375 p2.y -= offset;
04376 else
04377 p2.y += offset;
04378 }
04379 else if( dir == y)
04380 {
04381 p2 = m_points[leader_end_pt_index];
04382 if( p2.x > m_points[definition_pt_index].x)
04383 p2.x -= offset;
04384 else
04385 p2.x += offset;
04386 }
04387 }
04388 else if( point_index == offset_pt_1)
04389 {
04390 double offset0;
04391 if( m_kink_offset_0 == ON_UNSET_VALUE)
04392 offset0 = default_offset;
04393 else
04394 offset0 = m_kink_offset_0;
04395
04396 double offset1;
04397 if( m_kink_offset_1 == ON_UNSET_VALUE)
04398 offset1 = default_offset;
04399 else
04400 offset1 = m_kink_offset_1;
04401
04402 if( dir == x)
04403 {
04404 p2.x = m_points[definition_pt_index].x;
04405 if( m_points[leader_end_pt_index].y > m_points[definition_pt_index].y)
04406 p2.y = m_points[leader_end_pt_index].y - offset0 - offset1;
04407 else
04408 p2.y = m_points[leader_end_pt_index].y + offset0 + offset1;
04409 }
04410 else if( dir == y)
04411 {
04412 p2.y = m_points[definition_pt_index].y;
04413 if( m_points[leader_end_pt_index].x > m_points[definition_pt_index].x)
04414 p2.x = m_points[leader_end_pt_index].x - offset0 - offset1;
04415 else
04416 p2.x = m_points[leader_end_pt_index].x + offset0 + offset1;
04417 }
04418 }
04419 return p2;
04420 }
04421
04422 ON_3dPoint ON_OrdinateDimension2::Dim3dPoint( int point_index, double default_offset) const
04423 {
04424 ON_2dPoint p2 = Dim2dPoint(point_index, default_offset);
04425 return (ON_UNSET_VALUE == p2.x) ? ON_UNSET_POINT : m_plane.PointAt(p2.x,p2.y);
04426 }
04427
04428 ON_BOOL32 ON_OrdinateDimension2::IsValid( ON_TextLog* text_log) const
04429 {
04430 if ( m_type != ON::dtDimOrdinate)
04431 {
04432 if ( text_log )
04433 {
04434 text_log->Print("ON_OrdinateDimension2 - m_type != ON::dtDimOrdinate.\n");
04435 }
04436 return false;
04437 }
04438
04439 if ( !ON_Annotation2::IsValid( text_log ))
04440 {
04441 if ( text_log )
04442 {
04443 text_log->Print("ON_OrdinateDimension2 - invalid ON_Annotation2 base class.\n");
04444 }
04445 return false;
04446 }
04447
04448 if ( m_points.Count() != 2 )
04449 {
04450 if ( text_log )
04451 {
04452 text_log->Print("ON_OrdinateDimension2 - m_points.Count() = %d (should be 2).\n",m_points.Count());
04453 }
04454 return false;
04455 }
04456
04457 return true;
04458
04459 }
04460
04461 ON_BOOL32 ON_OrdinateDimension2::Write( ON_BinaryArchive& file ) const
04462 {
04463
04464
04465 bool rc = file.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,1);
04466 if (rc)
04467 {
04468 rc = file.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
04469 if (rc)
04470 {
04471
04472
04473
04474
04475
04476
04477
04478
04479
04480 rc = ON_Annotation2::Write( file) ? true : false;
04481 if (!file.EndWrite3dmChunk() )
04482 rc = false;
04483 }
04484 if (rc)
04485 rc = file.WriteInt( m_direction);
04486
04487 if (rc)
04488 rc = file.WriteDouble( m_kink_offset_0);
04489 if (rc)
04490 rc = file.WriteDouble( m_kink_offset_1);
04491
04492
04493 if (!file.EndWrite3dmChunk() )
04494 rc = false;
04495 }
04496
04497 return rc;
04498 }
04499
04500 ON_BOOL32 ON_OrdinateDimension2::Read( ON_BinaryArchive& file )
04501 {
04502 int major_version=0, minor_version=0;
04503 bool rc = file.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
04504 if (rc)
04505 {
04506 if ( 1 != major_version )
04507 {
04508 rc = false;
04509 }
04510 else
04511 {
04512 int submajor_version=0, subminor_version=0;
04513
04514
04515
04516 rc = file.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&submajor_version,&subminor_version);
04517 if (rc)
04518 {
04519 if ( 1 != submajor_version )
04520 rc = false;
04521 else
04522 {
04523 rc = ON_Annotation2::Read( file) ? true : false;
04524 }
04525 if ( !file.EndRead3dmChunk() )
04526 rc = false;
04527 }
04528
04529 if( rc)
04530 rc = file.ReadInt( &m_direction);
04531
04532 if( minor_version > 0)
04533 {
04534 if( rc)
04535 rc = file.ReadDouble( &m_kink_offset_0);
04536 if( rc)
04537 rc = file.ReadDouble( &m_kink_offset_1);
04538 }
04539 }
04540
04541 if (!file.EndRead3dmChunk())
04542 rc = false;
04543 }
04544 return rc;
04545 }
04546
04547 double ON_OrdinateDimension2::NumericValue() const
04548 {
04549 if( m_direction == 0)
04550 return m_points[1].x - m_points[0].x;
04551 else
04552 return m_points[1].y - m_points[0].y;
04553 }
04554
04555 int ON_OrdinateDimension2::StyleIndex() const
04556 {
04557 return ON_Annotation2::Index();
04558 }
04559
04560 void ON_OrdinateDimension2::SetStyleIndex( int i)
04561 {
04562 ON_Annotation2::SetIndex( i);
04563 }
04564
04565 ON_BOOL32 ON_OrdinateDimension2::GetBBox( double* boxmin,
04566 double* boxmax,
04567 ON_BOOL32 bGrowBox) const
04568 {
04569 ON_BoundingBox bbox;
04570 if ( bGrowBox )
04571 {
04572 bbox.m_min.x = boxmin[0];
04573 bbox.m_min.y = boxmin[1];
04574 bbox.m_min.z = boxmin[2];
04575 bbox.m_max.x = boxmax[0];
04576 bbox.m_max.y = boxmax[1];
04577 bbox.m_max.z = boxmax[2];
04578 if ( !bbox.IsValid() )
04579 {
04580 bbox.Destroy();
04581 bGrowBox = false;
04582 }
04583 }
04584
04585 if( m_points.Count() == 2)
04586 {
04587 ON_3dPointArray P( 2);
04588
04589 P.Append( m_plane.PointAt( m_points[0].x, m_points[0].y));
04590 P.Append( m_plane.PointAt( m_points[1].x, m_points[1].y));
04591 bGrowBox = P.GetBBox(&bbox.m_min.x, &bbox.m_max.x, bGrowBox);
04592 }
04593
04594 if ( bGrowBox )
04595 {
04596 boxmin[0] = bbox.m_min.x;
04597 boxmin[1] = bbox.m_min.y;
04598 boxmin[2] = bbox.m_min.z;
04599 boxmax[0] = bbox.m_max.x;
04600 boxmax[1] = bbox.m_max.y;
04601 boxmax[2] = bbox.m_max.z;
04602 }
04603
04604 return bGrowBox;
04605 }
04606
04607 bool ON_OrdinateDimension2::GetTightBoundingBox( ON_BoundingBox& tight_bbox,
04608 int bGrowBox,
04609 const ON_Xform* xform) const
04610 {
04611 if( m_points.Count() == 2)
04612 {
04613 ON_3dPointArray P(2);
04614
04615 P.Append( m_plane.PointAt( m_points[0].x, m_points[0].y));
04616 P.Append( m_plane.PointAt( m_points[1].x, m_points[1].y));
04617
04618 if ( P.GetTightBoundingBox( tight_bbox, bGrowBox, xform))
04619 bGrowBox = true;
04620 }
04621 else if( bGrowBox && !tight_bbox.IsValid())
04622 {
04623 tight_bbox.Destroy();
04624 bGrowBox = false;
04625 }
04626
04627 return( 0 != bGrowBox);
04628 }
04629
04630 int ON_OrdinateDimension2::ImpliedDirection() const
04631 {
04632 int direction = -1;
04633 const ON_2dPoint& p0 = m_points[definition_pt_index];
04634 const ON_2dPoint& p1 = m_points[leader_end_pt_index];
04635 if( fabs( p1.x - p0.x) <= fabs( p1.y - p0.y))
04636 direction = 0;
04637 else
04638 direction = 1;
04639
04640 return direction;
04641 }
04642
04643 int ON_OrdinateDimension2::Direction() const
04644 {
04645 return m_direction;
04646 }
04647
04648 void ON_OrdinateDimension2::SetDirection( int direction)
04649 {
04650 m_direction = direction;
04651 }
04652
04653 const wchar_t* ON_OrdinateDimension2::DefaultText() { return L"<>"; }
04654
04655 double ON_OrdinateDimension2::KinkOffset( int index) const
04656 {
04657 if( index == 0)
04658 return m_kink_offset_0;
04659 else if( index == 1)
04660 return m_kink_offset_1;
04661 else
04662 return ON_UNSET_VALUE;
04663 }
04664
04665 void ON_OrdinateDimension2::SetKinkOffset( int index, double offset)
04666 {
04667 if( index == 0)
04668 m_kink_offset_0 = offset;
04669 else if( index == 1)
04670 m_kink_offset_1 = offset;
04671 }
04672
04673 void ON_OrdinateDimension2::CalcKinkPoints( ON_2dPoint p0, ON_2dPoint p1,
04674 int direction, double default_offset,
04675 ON_2dPoint& k0, ON_2dPoint& k1) const
04676 {
04677 double offset0 = KinkOffset( 0);
04678 double offset1 = KinkOffset( 1);
04679
04680
04681
04682 if( offset0 == ON_UNSET_VALUE)
04683 offset0 = default_offset;
04684 if( offset1 == ON_UNSET_VALUE)
04685 offset1 = default_offset;
04686
04687 if( p0[1-direction] > p1[1-direction])
04688 {
04689 offset0 = -offset0;
04690 offset1 = -offset1;
04691 }
04692
04693
04694
04695 if( direction == 0)
04696 {
04697
04698
04699 k1.x = p0.x;
04700 k1.y = p1.y - offset0 - offset1;
04701
04702
04703
04704
04705
04706
04707
04708 k0.x = p1.x;
04709 k0.y = p1.y - offset0;
04710 }
04711 else
04712 {
04713
04714
04715 k1.x = p1.x - offset0 - offset1;
04716 k1.y = p0.y;
04717
04718
04719
04720
04721
04722
04723
04724 k0.x = p1.x - offset0;
04725 k0.y = p1.y;
04726 }
04727 }
04728
04729
04730
04731
04732 ON_TextEntity2::ON_TextEntity2()
04733 {
04734 m_type = ON::dtTextBlock;
04735 m_textdisplaymode = ON::dtNormal;
04736 }
04737
04738 ON_TextEntity2::~ON_TextEntity2()
04739 {
04740 }
04741
04742 ON_BOOL32 ON_TextEntity2::IsValid( ON_TextLog* text_log ) const
04743 {
04744 if ( m_type != ON::dtTextBlock )
04745 {
04746 if ( text_log )
04747 {
04748 text_log->Print("ON_TextEntity2 - m_type != ON::dtTextBlock\n");
04749 }
04750 return false;
04751 }
04752
04753
04754
04755
04756 int count = m_usertext.Length();
04757 bool bValidText = false;
04758 for( int i=0; i<count; i++ )
04759 {
04760 wchar_t c = m_usertext[i];
04761
04762 if( c > L' ' )
04763 {
04764 bValidText = true;
04765 break;
04766 }
04767 }
04768
04769
04770 if( !bValidText && count<1 )
04771 {
04772 const wchar_t* formula = TextFormula();
04773 if( formula && formula[0] )
04774 bValidText = true;
04775 }
04776
04777 if( !bValidText )
04778 {
04779 if( text_log )
04780 {
04781 text_log->Print("ON_TextEntity2 - m_usertext does not contain printable characters.\n");
04782 }
04783 return false;
04784 }
04785
04786
04787 if ( !ON_Annotation2::IsValid( text_log ))
04788 {
04789 if ( text_log )
04790 {
04791 text_log->Print("ON_TextEntity2 - invalid ON_Annotation2 base class.\n");
04792 }
04793 return false;
04794 }
04795
04796 if ( 0 != m_points.Count() )
04797 {
04798 if ( text_log )
04799 {
04800 text_log->Print("ON_TextEntity2 - m_points.Count() = %d (should be 0)\n", m_points.Count() );
04801 }
04802 return false;
04803 }
04804
04805 return true;
04806 }
04807
04808
04809 ON_BOOL32 ON_TextEntity2::Write(ON_BinaryArchive& archive) const
04810 {
04811
04812
04813
04814
04815
04816 bool rc = false;
04817 bool bInChunk = (archive.Archive3dmVersion() >= 5);
04818 if ( bInChunk )
04819 {
04820 rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
04821 if ( !rc )
04822 return false;
04823 }
04824 else
04825 {
04826 rc = true;
04827 }
04828
04829 while(rc)
04830 {
04831 rc = ON_Annotation2::Write(archive)?true:false;
04832 if (!rc) break;
04833 if ( !bInChunk )
04834 break;
04835
04836
04837
04838
04839 break;
04840 }
04841
04842 if ( bInChunk )
04843 {
04844 if (!archive.EndWrite3dmChunk())
04845 rc = false;
04846 }
04847 return rc;
04848 }
04849
04850 ON_BOOL32 ON_TextEntity2::Read(ON_BinaryArchive& archive)
04851 {
04852
04853
04854
04855 int major_version = 0;
04856 int minor_version = 0;
04857 bool rc = false;
04858 bool bInChunk = (archive.Archive3dmVersion() >= 5 && archive.ArchiveOpenNURBSVersion() >= 200710180);
04859 if ( bInChunk )
04860 {
04861 rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
04862 if ( !rc )
04863 return false;
04864 }
04865 else
04866 {
04867 rc = true;
04868 }
04869
04870 while(rc)
04871 {
04872 rc = ON_Annotation2::Read(archive)?true:false;
04873 if (!rc) break;
04874 if ( !bInChunk || minor_version <= 0 )
04875 break;
04876
04877
04878
04879 break;
04880 }
04881
04882 if ( bInChunk )
04883 {
04884
04885
04886
04887
04888 if ( !archive.EndRead3dmChunk() )
04889 rc = false;
04890 }
04891 return rc;
04892 }
04893
04894
04895 ON_BOOL32 ON_TextEntity2::GetBBox(
04896 double* boxmax,
04897 double* boxmin,
04898 ON_BOOL32 bGrowBox
04899 ) const
04900 {
04901 ON_BoundingBox bbox;
04902 if ( bGrowBox )
04903 {
04904 bbox.m_min.x = boxmin[0];
04905 bbox.m_min.y = boxmin[1];
04906 bbox.m_min.z = boxmin[2];
04907 bbox.m_max.x = boxmax[0];
04908 bbox.m_max.y = boxmax[1];
04909 bbox.m_max.z = boxmax[2];
04910 if ( !bbox.IsValid() )
04911 {
04912 bbox.Destroy();
04913 bGrowBox = false;
04914 }
04915 }
04916
04917 if ( 1 == m_points.Count() )
04918 {
04919 ON_2dPoint uv = m_points[0];
04920 bbox.Set( m_plane.PointAt(uv.x,uv.y), bGrowBox );
04921 bGrowBox = true;
04922 }
04923 else if ( 0 == m_points.Count() )
04924 {
04925 bbox.Set( m_plane.origin, bGrowBox );
04926 bGrowBox = true;
04927 }
04928
04929 if ( bGrowBox )
04930 {
04931 boxmin[0] = bbox.m_min.x;
04932 boxmin[1] = bbox.m_min.y;
04933 boxmin[2] = bbox.m_min.z;
04934 boxmax[0] = bbox.m_max.x;
04935 boxmax[1] = bbox.m_max.y;
04936 boxmax[2] = bbox.m_max.z;
04937 }
04938
04939 return bGrowBox;
04940 }
04941
04942
04943
04944
04945
04946 bool ON_TextEntity2::GetTightBoundingBox(
04947 ON_BoundingBox& tight_bbox,
04948 int bGrowBox,
04949 const ON_Xform* xform
04950 ) const
04951 {
04952 if ( 1 == m_points.Count() )
04953 {
04954 ON_3dPointArray P(1);
04955 P.Append( m_plane.PointAt(m_points[0].x,m_points[0].y) );
04956 if ( P.GetTightBoundingBox( tight_bbox, bGrowBox, xform ) )
04957 bGrowBox = true;
04958 }
04959 else if ( bGrowBox && !tight_bbox.IsValid() )
04960 {
04961 tight_bbox.Destroy();
04962 bGrowBox = false;
04963 }
04964
04965 return (0!=bGrowBox);
04966 }
04967
04968 int ON_TextEntity2::FontIndex() const
04969 {
04970 return m_index;
04971 }
04972
04973 void ON_TextEntity2::SetFontIndex( int i)
04974 {
04975 m_index = i;
04976 }
04977
04978 ON_BOOL32 ON_TextEntity2::Transform( const ON_Xform& xform )
04979 {
04980
04981
04982 bool rc = xform.IsIdentity();
04983 if ( !rc)
04984 {
04985 ON_Plane xformed_plane = m_plane;
04986 rc = xformed_plane.Transform(xform);
04987 if (rc)
04988 rc = ON_Geometry::Transform(xform)?true:false;
04989 if (rc)
04990 {
04991 ON_3dPoint P0 = xform*m_plane.origin;
04992 ON_3dPoint P1 = xform*(m_plane.origin + m_plane.xaxis);
04993 double s = P0.DistanceTo(P1);
04994 if ( s <= ON_ZERO_TOLERANCE )
04995 {
04996 P1 = xform*(m_plane.origin + m_plane.yaxis);
04997 s = P0.DistanceTo(P1);
04998 }
04999 m_plane = xformed_plane;
05000 if ( s > ON_ZERO_TOLERANCE && fabs(s-1.0) > ON_SQRT_EPSILON )
05001 {
05002 s *= m_textheight;
05003 if ( s > ON_SQRT_EPSILON )
05004 m_textheight = s;
05005 }
05006 }
05007 }
05008
05009 return rc;
05010 }
05011
05012
05013
05014
05015 void ON_TextEntity2::GetV2Form( ON_TextEntity& text)
05016 {
05017 ON_Annotation2::ConvertBack( text);
05018 text.SetHeight( Height());
05019
05020 ON_Plane plane = Plane();
05021 plane.origin += plane.yaxis * 1.1 * m_textheight;
05022 plane.UpdateEquation();
05023 text.SetPlane( plane);
05024 }
05025
05026 void ON_TextEntity2::SetJustification( unsigned int justification)
05027 {
05028 m_justification = justification;
05029 }
05030
05031 unsigned int ON_TextEntity2::Justification()
05032 {
05033 return m_justification;
05034 }
05035
05036 bool ON_TextEntity2::DrawTextMask() const
05037 {
05038 const ON_TextExtra* pTE = ON_TextExtra::TextExtension(this, false);
05039 if(pTE)
05040 return pTE->DrawTextMask();
05041 else
05042 return false;
05043 }
05044
05045 void ON_TextEntity2::SetDrawTextMask(bool bDraw)
05046 {
05047 ON_TextExtra* pTE = ON_TextExtra::TextExtension(this, true);
05048 if(pTE)
05049 pTE->SetDrawTextMask(bDraw);
05050 }
05051
05052 int ON_TextEntity2::MaskColorSource() const
05053 {
05054 const ON_TextExtra* pTE = ON_TextExtra::TextExtension(this, false);
05055 if(pTE)
05056 return pTE->MaskColorSource();
05057 else
05058 return 0;
05059 }
05060
05061 void ON_TextEntity2::SetMaskColorSource(int source)
05062 {
05063 ON_TextExtra* pTE = ON_TextExtra::TextExtension(this, true);
05064 if(pTE)
05065 pTE->SetMaskColorSource(source);
05066 }
05067
05068 ON_Color ON_TextEntity2::MaskColor() const
05069 {
05070 const ON_TextExtra* pTE = ON_TextExtra::TextExtension(this, false);
05071 if(pTE)
05072 return pTE->MaskColor();
05073 else
05074 return 0;
05075 }
05076
05077 void ON_TextEntity2::SetMaskColor(ON_Color color)
05078 {
05079 ON_TextExtra* pTE = ON_TextExtra::TextExtension(this, true);
05080 if(pTE)
05081 pTE->SetMaskColor(color);
05082 }
05083
05084 double ON_TextEntity2::MaskOffsetFactor() const
05085 {
05086 const ON_TextExtra* pTE = ON_TextExtra::TextExtension(this, false);
05087 if(pTE)
05088 return pTE->MaskOffsetFactor();
05089 else
05090 return 0;
05091 }
05092
05093 void ON_TextEntity2::SetMaskOffsetFactor(double offset)
05094 {
05095 ON_TextExtra* pTE = ON_TextExtra::TextExtension(this, true);
05096 if(pTE)
05097 pTE->SetMaskOffsetFactor(offset);
05098 }
05099
05100 bool ON_TextEntity2::AnnotativeScaling() const
05101 {
05102 return m_annotative_scale;
05103 }
05104
05105 void ON_TextEntity2::SetAnnotativeScaling(bool b)
05106 {
05107 m_annotative_scale = b;
05108 }
05109
05110
05111
05112
05113 ON_Leader2::ON_Leader2()
05114 {
05115 m_type = ON::dtLeader;
05116 m_textdisplaymode = ON::dtInLine;
05117 }
05118
05119 ON_Leader2::~ON_Leader2()
05120 {
05121 }
05122
05123 ON_BOOL32 ON_Leader2::IsValid( ON_TextLog* text_log ) const
05124 {
05125 if ( m_type != ON::dtLeader )
05126 {
05127 if ( text_log )
05128 {
05129 text_log->Print("ON_Leader2 - m_type != ON::dtLeader\n");
05130 }
05131 return false;
05132 }
05133
05134 if ( !ON_Annotation2::IsValid( text_log ))
05135 {
05136 if ( text_log )
05137 {
05138 text_log->Print("ON_Leader2 - invalid ON_Annotation2 base class.\n");
05139 }
05140 return false;
05141 }
05142
05143 if ( m_points.Count() < 2 )
05144 {
05145 if ( text_log )
05146 {
05147 text_log->Print("ON_Leader2 - m_points.Count() = %d (should be >= 2)\n", m_points.Count() );
05148 }
05149 return false;
05150 }
05151
05152 return true;
05153 }
05154
05155 ON_BOOL32 ON_Leader2::Write(ON_BinaryArchive& archive) const
05156 {
05157
05158
05159
05160
05161
05162 bool rc = false;
05163 bool bInChunk = (archive.Archive3dmVersion() >= 5);
05164 if ( bInChunk )
05165 {
05166 rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
05167 if ( !rc )
05168 return false;
05169 }
05170 else
05171 {
05172 rc = true;
05173 }
05174
05175 while(rc)
05176 {
05177 rc = ON_Annotation2::Write(archive)?true:false;
05178 if (!rc) break;
05179 if ( !bInChunk )
05180 break;
05181
05182
05183
05184
05185 break;
05186 }
05187
05188 if ( bInChunk )
05189 {
05190 if (!archive.EndWrite3dmChunk())
05191 rc = false;
05192 }
05193 return rc;
05194 }
05195
05196 ON_BOOL32 ON_Leader2::Read(ON_BinaryArchive& archive)
05197 {
05198
05199
05200
05201 int major_version = 0;
05202 int minor_version = 0;
05203 bool rc = false;
05204 bool bInChunk = (archive.Archive3dmVersion() >= 5 && archive.ArchiveOpenNURBSVersion() >= 200710180);
05205 if ( bInChunk )
05206 {
05207 rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
05208 if ( !rc )
05209 return false;
05210 }
05211 else
05212 {
05213 rc = true;
05214 }
05215
05216 while(rc)
05217 {
05218 rc = ON_Annotation2::Read(archive)?true:false;
05219 if (!rc) break;
05220 if ( !bInChunk || minor_version <= 0 )
05221 break;
05222
05223
05224
05225 break;
05226 }
05227
05228 if ( bInChunk )
05229 {
05230 if ( !archive.EndRead3dmChunk() )
05231 rc = false;
05232 }
05233 return rc;
05234 }
05235
05236 ON_BOOL32 ON_Leader2::GetBBox(
05237 double* boxmax,
05238 double* boxmin,
05239 ON_BOOL32 bGrowBox
05240 ) const
05241 {
05242 ON_BoundingBox bbox;
05243 if ( bGrowBox )
05244 {
05245 bbox.m_min.x = boxmin[0];
05246 bbox.m_min.y = boxmin[1];
05247 bbox.m_min.z = boxmin[2];
05248 bbox.m_max.x = boxmax[0];
05249 bbox.m_max.y = boxmax[1];
05250 bbox.m_max.z = boxmax[2];
05251 if ( !bbox.IsValid() )
05252 {
05253 bbox.Destroy();
05254 bGrowBox = false;
05255 }
05256 }
05257
05258 const int point_count = m_points.Count();
05259 if ( point_count > 0 )
05260 {
05261 ON_3dPointArray P(point_count);
05262 int i;
05263 for ( i = 0; i < point_count; i++ )
05264 {
05265 ON_2dPoint uv = m_points[i];
05266 P.Append( m_plane.PointAt(uv.x,uv.y));
05267 }
05268 if ( P.GetBoundingBox(bbox,bGrowBox?true:false) )
05269 bGrowBox = true;
05270 }
05271
05272 if ( bGrowBox )
05273 {
05274 boxmin[0] = bbox.m_min.x;
05275 boxmin[1] = bbox.m_min.y;
05276 boxmin[2] = bbox.m_min.z;
05277 boxmax[0] = bbox.m_max.x;
05278 boxmax[1] = bbox.m_max.y;
05279 boxmax[2] = bbox.m_max.z;
05280 }
05281
05282 return bGrowBox;
05283 }
05284
05285
05286
05287 bool ON_Leader2::GetTightBoundingBox(
05288 ON_BoundingBox& tight_bbox,
05289 int bGrowBox,
05290 const ON_Xform* xform
05291 ) const
05292 {
05293 const int point_count = m_points.Count();
05294 if ( point_count >= 2 )
05295 {
05296 ON_3dPointArray P(point_count);
05297 int i;
05298 for ( i = 0; i < point_count; i++ )
05299 {
05300 ON_2dPoint uv = m_points[i];
05301 P.Append( m_plane.PointAt(uv.x,uv.y));
05302 }
05303 if ( P.GetTightBoundingBox( tight_bbox, bGrowBox, xform ) )
05304 bGrowBox = true;
05305 }
05306 else if ( bGrowBox && !tight_bbox.IsValid() )
05307 {
05308 tight_bbox.Destroy();
05309 bGrowBox = false;
05310 }
05311
05312 return (0!=bGrowBox);
05313 }
05314
05315 ON_2dPoint ON_Leader2::Dim2dPoint(
05316 int point_index
05317 ) const
05318 {
05319 ON_2dPoint p2;
05320 int point_count = m_points.Count();
05321 if ( point_index < 0 || point_count < 1 )
05322 {
05323 p2.x = p2.y = ON_UNSET_VALUE;
05324 }
05325 else
05326 {
05327 switch(point_index)
05328 {
05329 case arrow_pt_index:
05330 p2 = m_points[0];
05331 break;
05332
05333 case text_pivot_pt:
05334 case tail_pt:
05335 p2 = *m_points.Last();
05336 break;
05337
05338 default:
05339 if ( point_index < point_count )
05340 {
05341 p2 = m_points[point_index];
05342 }
05343 else
05344 {
05345 p2.x = p2.y = ON_UNSET_VALUE;
05346 }
05347 break;
05348 }
05349 }
05350 return p2;
05351 }
05352
05353 ON_3dPoint ON_Leader2::Dim3dPoint(
05354 int point_index
05355 ) const
05356 {
05357 ON_2dPoint p2 = Dim2dPoint(point_index);
05358 return (ON_UNSET_VALUE == p2.x) ? ON_UNSET_POINT : m_plane.PointAt(p2.x,p2.y);
05359 }
05360
05361
05362 void ON_Leader2::AddPoint( const ON_2dPoint& point )
05363 {
05364 m_points.Append( point);
05365
05366 }
05367
05368 bool ON_Leader2::RemovePoint( int idx )
05369 {
05370 bool rc = true;
05371 if( idx == -1)
05372 {
05373 m_points.Remove();
05374 }
05375 else if( idx >= 0 && idx < m_points.Count())
05376 {
05377 m_points.Remove( idx);
05378 }
05379 else
05380 {
05381 rc = false;
05382 }
05383
05384 return rc;
05385 }
05386
05387
05388 bool ON_Leader2::GetTextDirection( ON_2dVector& text_dir ) const
05389 {
05390 bool rc = false;
05391 const int point_count = m_points.Count();
05392 if ( point_count < 2 )
05393 {
05394 text_dir.Set(-1.0,0.0);
05395 }
05396 else
05397 {
05398 int i;
05399 for(i = point_count-1; i >= 1; i--)
05400 {
05401 text_dir = m_points[point_count-1] - m_points[i-1];
05402 if(text_dir.Unitize())
05403 {
05404 rc = true;
05405 break;
05406 }
05407 text_dir.Set(-1.0,0.0);
05408 }
05409 }
05410 return rc;
05411 }
05412
05413 bool ON_Leader2::GetArrowHeadDirection( ON_2dVector& arrowhead_dir ) const
05414 {
05415 bool rc = false;
05416 const int point_count = m_points.Count();
05417 if ( point_count < 2 )
05418 {
05419 arrowhead_dir.Set(-1.0,0.0);
05420 }
05421 else
05422 {
05423 int i;
05424 for ( i = 1; i < point_count; i++ )
05425 {
05426 arrowhead_dir = m_points[0] - m_points[i];
05427 if ( arrowhead_dir.Unitize() )
05428 {
05429 rc = true;
05430 break;
05431 }
05432 arrowhead_dir.Set(-1.0,0.0);
05433 }
05434 }
05435 return rc;
05436 }
05437
05438 bool ON_Leader2::GetArrowHeadTip( ON_2dPoint& arrowhead_tip ) const
05439 {
05440 bool rc = false;
05441 switch( m_points.Count())
05442 {
05443 case 0:
05444 arrowhead_tip.Set(0.0,0.0);
05445 break;
05446 case 1:
05447 arrowhead_tip = m_points[0];
05448 break;
05449 default:
05450 arrowhead_tip = m_points[0];
05451 rc = true;
05452 break;
05453 }
05454 return rc;
05455 }
05456
05457
05458
05459 bool ON_RadialDimension2::GetArrowHeadDirection( ON_2dVector& arrowhead_dir ) const
05460 {
05461 bool rc = false;
05462 if ( m_points.Count() < 4 )
05463 {
05464 arrowhead_dir.Set(-1.0,0.0);
05465 }
05466 else
05467 {
05468 arrowhead_dir = m_points[1] - m_points[3];
05469 if ( 0 == (rc=arrowhead_dir.Unitize()) )
05470 {
05471 arrowhead_dir = m_points[1] - m_points[2];
05472 if ( 0 == (rc=arrowhead_dir.Unitize()) )
05473 {
05474 arrowhead_dir = m_points[0] - m_points[1];
05475 rc = arrowhead_dir.Unitize();
05476 }
05477 }
05478 }
05479 return rc;
05480 }
05481
05482 bool ON_RadialDimension2::GetArrowHeadTip( ON_2dPoint& arrowhead_tip ) const
05483 {
05484 bool rc = false;
05485 if ( m_points.Count() >= 2 )
05486 {
05487 arrowhead_tip = m_points[1];
05488 rc = true;
05489 }
05490 else
05491 {
05492 arrowhead_tip.Set(0.0,0.0);
05493 rc = false;
05494 }
05495 return rc;
05496 }
05497
05498
05499 void ON_Leader2::GetV2Form( ON_Leader& leader)
05500 {
05501 ON_Annotation2::ConvertBack( leader);
05502 }
05503
05504
05505 bool ON_Leader2::CreateFromV2(
05506 const ON_Annotation& v2_ann,
05507 const ON_3dmAnnotationSettings& settings,
05508 int dimstyle_index
05509 )
05510 {
05511 bool rc = false;
05512 if( ON::dtLeader == v2_ann.m_type && v2_ann.m_points.Count() >= 2 )
05513 {
05514 m_plane = v2_ann.m_plane;
05515 m_plane.UpdateEquation();
05516 m_points.Reserve(v2_ann.m_points.Count());
05517 m_points.SetCount(0);
05518 m_points.Append(v2_ann.m_points.Count(),v2_ann.m_points.Array());
05519 ON_2dVector v = m_points[0];
05520 SetTextValue(v2_ann.UserText());
05521 SetTextFormula(0);
05522 m_userpositionedtext = false;
05523 m_textdisplaymode = ( 2 == settings.m_textalign )
05524 ? ON::dtHorizontal
05525 : ON::dtInLine;
05526 m_type = ON::dtLeader;
05527 m_index = dimstyle_index;
05528
05529 if ( !v.IsZero() )
05530 {
05531 m_plane.origin = m_plane.PointAt(v.x,v.y);
05532 m_plane.UpdateEquation();
05533 v.Reverse();
05534 int i;
05535 for ( i = 1; i < m_points.Count(); i++ )
05536 {
05537 m_points[i] += v;
05538 }
05539 m_points[0].Set(0.0,0.0);
05540 }
05541 rc = true;
05542 }
05543 return rc;
05544 }
05545
05546
05547
05548
05549 ON_TextDot::ON_TextDot() :
05550 m_point( ON_origin), m_height( 14), m_text( L'1'),
05551 m_fontface( L"Arial bold"), m_display( 0)
05552 {
05553 }
05554
05555 ON_TextDot::~ON_TextDot()
05556 {
05557 }
05558
05559 void ON_TextDot::EmergencyDestroy()
05560 {
05561 m_text.EmergencyDestroy();
05562 m_fontface.EmergencyDestroy();
05563 m_point = ON_origin;
05564 m_height = 0;
05565 m_display = 0;
05566 }
05567
05568 ON_BOOL32 ON_TextDot::IsValid(
05569 ON_TextLog* text_log
05570 ) const
05571 {
05572
05573 if ( !m_point.IsValid() )
05574 {
05575 if ( 0 != text_log )
05576 {
05577 text_log->Print("ON_TextDot m_point is not valid\n");
05578 }
05579 return false;
05580 }
05581 return true;
05582 }
05583
05584 void ON_TextDot::Dump( ON_TextLog& log) const
05585 {
05586 log.Print("ON_TextDot \"%ls\" at ",m_text.Array());
05587 log.Print( m_point);
05588 log.Print("\n");
05589 }
05590
05591 ON_BOOL32 ON_TextDot::Write( ON_BinaryArchive& file) const
05592 {
05593 ON_BOOL32 rc = file.Write3dmChunkVersion(1,0);
05594 if (rc) rc = file.WritePoint( m_point );
05595 if (rc) rc = file.WriteInt( m_height);
05596 if (rc) rc = file.WriteString( m_text);
05597 if (rc) rc = file.WriteString( m_fontface);
05598 if (rc) rc = file.WriteInt( m_display);
05599
05600 return rc;
05601 }
05602
05603 ON_BOOL32 ON_TextDot::Read( ON_BinaryArchive& file)
05604 {
05605 m_text.Empty();
05606 int major_version = 0;
05607 int minor_version = 0;
05608 ON_BOOL32 rc = file.Read3dmChunkVersion(&major_version,&minor_version);
05609 if ( major_version == 1 ) {
05610 if (rc) rc = file.ReadPoint( m_point);
05611 if (rc) rc = file.ReadInt( &m_height);
05612 if (rc) rc = file.ReadString( m_text);
05613 if (rc) rc = file.ReadString( m_fontface);
05614 if (rc) rc = file.ReadInt( &m_display);
05615 }
05616 else {
05617 rc = false;
05618 }
05619 return rc;
05620 }
05621
05622 ON::object_type ON_TextDot::ObjectType() const
05623 {
05624 return ON::text_dot;
05625 }
05626
05627 int ON_TextDot::Dimension() const
05628 {
05629 return 3;
05630 }
05631
05632 ON_BOOL32 ON_TextDot::GetBBox( double* box_min, double* box_max, ON_BOOL32 grow_box ) const
05633 {
05634 return ON_GetPointListBoundingBox( 3, 0, 1, 3, &m_point.x, box_min, box_max, grow_box?true:false );
05635 }
05636
05637 ON_BOOL32 ON_TextDot::Transform( const ON_Xform& xform)
05638 {
05639 TransformUserData( xform);
05640 return ON_TransformPointList( 3, 0, 1, 3, &m_point.x, xform);
05641 }
05642
05643 bool ON_TextDot::IsDeformable() const
05644 {
05645 return true;
05646 }
05647
05648 bool ON_TextDot::MakeDeformable()
05649 {
05650 return true;
05651 }
05652
05653 const ON_3dPoint& ON_TextDot::Point() const
05654 {
05655 return m_point;
05656 }
05657
05658 void ON_TextDot::SetPoint( const ON_3dPoint& point)
05659 {
05660 m_point = point;
05661 }
05662
05663 int ON_TextDot::Height() const
05664 {
05665 return m_height;
05666 }
05667
05668 void ON_TextDot::SetHeight( int height)
05669 {
05670 if( height > 2)
05671 m_height = height;
05672 }
05673
05674 const wchar_t* ON_TextDot::TextString() const
05675 {
05676 if( m_text.IsEmpty())
05677 return L"";
05678 else
05679 return m_text;
05680 }
05681
05682 void ON_TextDot::SetTextString( const wchar_t* string)
05683 {
05684 m_text.Empty();
05685 if( string)
05686 {
05687 int len = (int)wcslen(string);
05688 wchar_t* str = 0;
05689 if(len > 0 && string[len-1] <= L' ')
05690 {
05691
05692 str = (wchar_t*)onmalloc((len+1)*sizeof(wchar_t));
05693 int j = 0;
05694 for(int i = 0; i < len; i++)
05695 {
05696 if(string[i] == L'\r' || string[i] == L'\n')
05697 continue;
05698 str[j++] = string[i];
05699 }
05700 str[j] = 0;
05701
05702
05703 for(int i = len-1; i >= 0 && str[i] <= L' '; i--)
05704 str[i] = 0;
05705 }
05706 if(str)
05707 {
05708 if(wcslen(str) > 0)
05709 m_text = str;
05710 onfree(str);
05711 }
05712 else
05713 m_text = string;
05714 }
05715 }
05716
05717 const wchar_t* ON_TextDot::FontFace() const
05718 {
05719 if( m_fontface.IsEmpty())
05720 return L"";
05721 else
05722 return m_fontface;
05723 }
05724
05725 void ON_TextDot::SetFontFace( const wchar_t* face)
05726 {
05727 if( face)
05728 m_fontface = face;
05729 else
05730 m_fontface.Empty();
05731 }
05732
05733 void ON_TextDot::SetAlwaysOnTop(bool bTop)
05734 {
05735 if(bTop)
05736 m_display |= 1;
05737 else
05738 m_display &= (~1);
05739 }
05740
05741 bool ON_TextDot::AlwaysOnTop() const
05742 {
05743 return (m_display & 1) == 1;
05744 }
05745
05746 void ON_TextDot::SetTransparent(bool bTransparent)
05747 {
05748 if(bTransparent)
05749 m_display |= 2;
05750 else
05751 m_display &= (~2);
05752 }
05753
05754 bool ON_TextDot::Transparent() const
05755 {
05756 return (m_display & 2) == 2;
05757 }
05758
05759 void ON_TextDot::SetBold(bool bBold)
05760 {
05761 if(bBold)
05762 m_display |= 4;
05763 else
05764 m_display &= (~4);
05765 }
05766
05767 bool ON_TextDot::Bold() const
05768 {
05769 return (m_display & 4) == 4;
05770 }
05771
05772 void ON_TextDot::SetItalic(bool bItalic)
05773 {
05774 if(bItalic)
05775 m_display |= 8;
05776 else
05777 m_display &= (~8);
05778 }
05779
05780 bool ON_TextDot::Italic() const
05781 {
05782 return (m_display & 8) == 8;
05783 }
05784
05785
05786
05787
05788 ON_Annotation2Text::ON_Annotation2Text()
05789 {
05790 memset(&m_rect,0,sizeof(m_rect));
05791 }
05792
05793 ON_Annotation2Text::~ON_Annotation2Text()
05794 {
05795 }
05796
05797 ON_Annotation2Text& ON_Annotation2Text::operator=(const char* s)
05798 {
05799 SetText(s);
05800 return *this;
05801 }
05802
05803 ON_Annotation2Text& ON_Annotation2Text::operator=(const wchar_t* s)
05804 {
05805 SetText(s);
05806 return *this;
05807 }
05808
05809 void ON_Annotation2Text::SetText(const char* s)
05810 {
05811 ON_wString::operator=(s);
05812 memset(&m_rect,0,sizeof(m_rect));
05813 }
05814
05815 void ON_Annotation2Text::SetText(const wchar_t* s)
05816 {
05817 ON_wString::operator=(s);
05818 memset(&m_rect,0,sizeof(m_rect));
05819 }
05820
05821
05822
05823 bool ON_Annotation2::GetTextXform(
05824 ON_RECT gdi_text_rect,
05825 const ON_Font& font,
05826 const ON_DimStyle& dimstyle,
05827 double dimscale,
05828 const ON_Viewport* vp,
05829 ON_Xform& xform
05830 ) const
05831 {
05832 ON_ERROR("This function should not be used. Use the version that takes a model transform argument.");
05833 return false;
05834
05835
05836
05837
05838
05839
05840
05841
05842
05845
05846
05847
05848
05849
05850
05851
05852
05853
05854
05855
05856
05857 }
05858
05859
05860
05861 #if 0
05862 bool ON_Annotation2::GetTextXform(
05863 ON_RECT gdi_text_rect,
05864 const ON_Font& font,
05865 const ON_DimStyle& dimstyle,
05866 double dimscale,
05867 const ON_Viewport* vp,
05868 const ON_Xform* model_xform,
05869 ON_Xform& xform
05870 ) const
05871 {
05872 ON_ERROR("This function should not be used. Use the one below that takes a dimstyle pointer.");
05873 return false;
05874 }
05875 #endif
05876
05877 bool ON_Annotation2::GetTextXform(
05878 ON_RECT gdi_text_rect,
05879 const ON_Font& font,
05880 const ON_DimStyle* dimstyle,
05881 double dimscale,
05882 const ON_Viewport* vp,
05883 const ON_Xform* model_xform,
05884 ON_Xform& xform
05885 ) const
05886 {
05887 int gdi_height_of_I = font.HeightOfI();
05888 const double textheight = dimstyle ? dimstyle->TextHeight() : m_textheight;
05889 double textgap = dimstyle ? dimstyle->TextGap() : 0.0;
05890 const ON::eTextDisplayMode textalignment = dimstyle ? ON::TextDisplayMode(dimstyle->TextAlignment()) : ON::dtNormal;
05891 const ON_3dVector cameraX = (vp) ? vp->CameraX() : m_plane.xaxis;
05892 const ON_3dVector cameraY = (vp) ? vp->CameraY() : m_plane.yaxis;
05893 if(dimstyle)
05894 {
05895
05896
05897 if(( dimstyle->ToleranceStyle() == 2 || dimstyle->ToleranceStyle() == 3) &&
05898 ( Type() == ON::dtDimLinear || Type() == ON::dtDimAligned))
05899 textgap += textheight * 0.5;
05900 }
05901 return GetTextXform(
05902 gdi_text_rect,
05903 gdi_height_of_I,
05904 textheight, textgap, textalignment,
05905 dimscale,
05906 cameraX, cameraY,
05907 model_xform,
05908 xform
05909 );
05910 }
05911
05912
05913
05914 static bool GetLeaderEndAndDirection( const ON_Annotation2* pAnn,
05915 ON_2dPoint& E,
05916 ON_2dVector& R )
05917 {
05918 bool rc = false;
05919
05920 ON::eAnnotationType ann_type = pAnn->m_type;
05921 const ON_2dPointArray& ann_m_points = pAnn->m_points;
05922
05923
05924 R.Set(1.0,0.0);
05925 E.Set(0.0,0.0);
05926
05927 if ( ann_m_points.Count() >= 4 && (ON::dtDimDiameter == ann_type || ON::dtDimRadius == ann_type) )
05928 {
05929 E = ann_m_points[2];
05930 R = E - ann_m_points[3];
05931 if ( !R.Unitize() )
05932 {
05933 R = E - ann_m_points[1];
05934 if ( !R.Unitize() )
05935 {
05936 R = E - ann_m_points[0];
05937 if ( !R.Unitize() )
05938 {
05939 R.Set(1.0,0.0);
05940 }
05941 }
05942 }
05943 rc = true;
05944 }
05945 else if ( ann_m_points.Count() >= 2 && ON::dtLeader == ann_type )
05946 {
05947 int i;
05948 E = *ann_m_points.Last();
05949 for (i = ann_m_points.Count()-2; i >= 0; i-- )
05950 {
05951 R = E - ann_m_points[i];
05952 if ( R.Unitize() )
05953 {
05954 break;
05955 }
05956 R.Set(1.0,0.0);
05957 }
05958 rc = true;
05959 }
05960 else if ( ann_m_points.Count() >= 2 && ON::dtDimOrdinate == ann_type )
05961 {
05962 E = ann_m_points[1];
05963
05964 int direction = (( ON_OrdinateDimension2*)pAnn)->Direction();
05965 if( direction == -1)
05966 {
05967 if( fabs( ann_m_points[1].x - ann_m_points[0].x)
05968 <= fabs( ann_m_points[1].y - ann_m_points[0].y))
05969 direction = 0;
05970 else
05971 direction = 1;
05972 }
05973
05974 if( direction == 0)
05975 R.Set( 0.0, ann_m_points[1].y - ann_m_points[0].y);
05976 else
05977 R.Set( ann_m_points[1].x - ann_m_points[0].x, 0.0);
05978
05979 if( !R.Unitize())
05980 R.Set(1.0,0.0);
05981
05982 rc = true;
05983 }
05984
05985 return rc;
05986 }
05987
05988
05989
05990 bool ON_Annotation2::GetTextXform(
05991 ON_RECT gdi_text_rect,
05992 int gdi_height_of_I,
05993 double dimstyle_textheight,
05994 double dimstyle_textgap,
05995 ON::eTextDisplayMode dimstyle_textalignment,
05996 double dimscale,
05997 ON_3dVector cameraX,
05998 ON_3dVector cameraY,
05999 ON_Xform& xform
06000 ) const
06001 {
06002 ON_ERROR("This function should not be used. Use the version that takes a model transform argument.");
06003 return false;
06004
06005
06006
06007
06008
06009
06010
06011
06012
06013
06014
06015
06016
06017
06018
06019
06020
06021
06022
06023
06024
06025
06026
06027
06028
06029
06030
06031
06032
06033
06034
06037
06038
06039
06040
06041
06043
06045
06046
06047
06048
06049
06050
06051
06052
06053
06054
06055
06056
06057
06058
06059
06060
06061
06062
06063
06069
06070
06071
06072
06073
06074
06075
06076
06077
06078
06079
06080
06081
06082
06083
06084
06085
06086
06087
06088
06089
06090
06091
06092
06095
06096
06097
06098
06099
06100
06101
06102
06103
06104
06105
06106
06107
06108
06109
06110
06111
06112
06113
06114
06115
06116
06117
06118
06119
06120
06121
06122
06123
06124
06127
06128
06133
06134
06135
06136
06137
06138
06139
06140
06141
06142
06143
06144
06145
06146
06147
06148
06149
06150
06151
06152
06153
06154
06155
06156
06157
06158
06159
06160
06161
06162
06163
06164
06165
06166
06167
06168
06169
06170
06171
06172
06173
06174
06175
06176
06177
06178
06179
06180
06181
06182
06183
06184
06185
06186
06187
06188
06189
06190
06191
06192
06193
06194
06195
06196
06197
06198
06199
06200
06201
06202
06203
06204
06205
06206
06207
06208
06209
06210
06211
06212
06213
06214
06215
06216
06217
06218
06219
06222
06223
06224
06227
06228
06229
06230
06231
06232
06233
06234
06235
06236
06237
06238
06239
06240
06241
06242
06243
06244
06245
06246
06247
06248
06249
06250
06251
06252
06253
06254
06255
06256
06257
06258
06259
06260
06261
06262
06263
06264
06265
06266
06267
06268
06269
06270
06271
06272
06273
06274
06275
06276
06277
06278
06279
06280
06281
06282
06283
06284
06285
06286
06288
06289
06290
06291
06292
06293
06294
06295
06296
06297
06298
06299
06300
06301
06302
06303
06304
06305
06306
06307
06308
06309
06310
06311
06312
06313
06314
06315
06316
06317
06318
06319
06320
06321
06322
06323
06324
06325
06326
06327
06328
06329
06330
06331
06332
06333
06334 }
06335
06336
06337
06338
06339
06340
06341
06342
06343
06344
06345
06346 bool ON_Annotation2::GetTextXform(
06347 ON_RECT gdi_text_rect,
06348 int gdi_height_of_I,
06349 double dimstyle_textheight,
06350 double dimstyle_textgap,
06351 ON::eTextDisplayMode dimstyle_textalignment,
06352 double dimscale,
06353 ON_3dVector cameraX,
06354 ON_3dVector cameraY,
06355 const ON_Xform* model_xform,
06356 ON_Xform& xform
06357 ) const
06358 {
06359 ON_Xform mxi;
06360 if( model_xform)
06361 {
06362 mxi = model_xform->Inverse();
06363 cameraX.Transform( mxi);
06364 cameraY.Transform( mxi);
06365 }
06366 const ON_Annotation2* ann = this;
06367
06368 const ON::eAnnotationType ann_type = ann->m_type;
06369
06370 if ( 0 == gdi_height_of_I )
06371 {
06372
06373 gdi_height_of_I = (165*ON_Font::normal_font_height)/256;
06374 }
06375
06376 if ( 0.0 == dimscale )
06377 {
06378 dimscale = 1.0;
06379 }
06380
06381 dimstyle_textheight *= dimscale;
06382 dimstyle_textgap *= dimscale;
06383
06384 double textheight = ( ON::dtTextBlock == ann_type )
06385 ? m_textheight*dimscale
06386 : dimstyle_textheight;
06387 if ( 0.0 == textheight )
06388 textheight = 1.0;
06389
06390 ON_3dVector cameraZ = ON_CrossProduct( cameraX, cameraY );
06391 if ( fabs( 1.0 - cameraZ.Length() ) > ON_SQRT_EPSILON )
06392 {
06393 cameraZ.Unitize();
06394 }
06395
06396
06397
06398 const double gdi_to_plane_scale = textheight/gdi_height_of_I;
06399 ON_Xform gdi_to_plane(1.0);
06400 gdi_to_plane.m_xform[0][0] = gdi_to_plane_scale;
06401 gdi_to_plane.m_xform[1][1] = -gdi_to_plane_scale;
06402
06403
06404 const double text_line_width = gdi_to_plane_scale*(gdi_text_rect.right - gdi_text_rect.left);
06405
06406
06407 if ( ON::dtTextBlock == ann_type )
06408 {
06409
06410
06411
06412
06413
06414
06415
06416
06417
06418 ON_Xform plane_to_world(1.0);
06419 plane_to_world.Rotation(ON_xy_plane,ann->m_plane);
06420 xform = plane_to_world*gdi_to_plane;
06421 return true;
06422 }
06423
06424
06425
06426
06427
06428
06429 int position_style = 0;
06430 switch( ann_type )
06431 {
06432 case ON::dtDimAligned:
06433 case ON::dtDimLinear:
06434 case ON::dtDimAngular:
06435
06436 position_style = 1;
06437 break;
06438
06439 case ON::dtLeader:
06440 if(ON::dtHorizontal == dimstyle_textalignment)
06441 position_style = 1;
06442 else
06443 position_style = 2;
06444 break;
06445
06446 case ON::dtDimRadius:
06447 case ON::dtDimDiameter:
06448 case ON::dtDimOrdinate:
06449
06450 position_style = 2;
06451 break;
06452
06453 case ON::dtTextBlock:
06454 case ON::dtNothing:
06455 break;
06456 }
06457
06458
06459
06460 if ( ON::dtHorizontal != dimstyle_textalignment || 1 == position_style )
06461 {
06462 if((m_justification & tjRight) == tjRight)
06463 gdi_to_plane.m_xform[0][3] = 0.5*text_line_width;
06464 else
06465 gdi_to_plane.m_xform[0][3] = -0.5*text_line_width;
06466 }
06467 gdi_to_plane.m_xform[1][3] = -0.5*textheight;
06468
06469 if ( ON::dtHorizontal != dimstyle_textalignment )
06470 {
06471 if ( ((cameraZ*m_plane.zaxis) < -ON_SQRT_EPSILON) )
06472 {
06473
06474 ON_Xform flip(1.0);
06475 switch ( position_style )
06476 {
06477 case 1:
06478 flip.m_xform[0][0] = -1.0;
06479 flip.m_xform[0][3] = gdi_text_rect.left + gdi_text_rect.right;
06480 break;
06481
06482 case 2:
06483
06484
06485 break;
06486 }
06487 gdi_to_plane = gdi_to_plane*flip;
06488 }
06489 }
06490
06491
06492
06493 ON_2dVector text_centering_rotation(1.0,0.0);
06494
06495
06496
06497
06498
06499 ON_2dVector text_centering_translation(0.0,0.0);
06500 bool text_y_flip = false;
06501 double x, y;
06502
06503 if ( ON::dtHorizontal != dimstyle_textalignment )
06504 {
06505 if ( ON::dtDimLinear == ann_type || ON::dtDimAligned == ann_type )
06506 {
06507 if ( ON::dtAboveLine == dimstyle_textalignment )
06508 {
06509 text_centering_translation.y = 0.5*textheight+dimstyle_textgap;
06510 }
06511 y = ann->m_plane.yaxis*cameraY;
06512 x = -ann->m_plane.yaxis*cameraX;
06513 if ( fabs(y) <= ON_SQRT_EPSILON && fabs(x) > ON_SQRT_EPSILON )
06514 {
06515 y = x;
06516 }
06517 if ( y < 0.0 )
06518 {
06519 text_centering_translation.Reverse();
06520 text_centering_rotation.Reverse();
06521 }
06522 }
06523 else if ( ON::dtDimAngular == ann_type )
06524 {
06525
06526 const ON_AngularDimension2* angular_dim = ON_AngularDimension2::Cast(ann);
06527 if ( 0 != angular_dim )
06528 {
06529 double a = 0.5*angular_dim->m_angle;
06530 ON_2dVector R(cos(a),sin(a));
06531 a -= 0.5*ON_PI;
06532 text_centering_rotation.x = cos(a);
06533 text_centering_rotation.y = sin(a);
06534 ON_3dVector V = R.x*m_plane.xaxis + R.y*m_plane.yaxis;
06535 x = V*cameraX;
06536 y = V*cameraY;
06537 if ( fabs(y) <= ON_SQRT_EPSILON && fabs(x) > ON_SQRT_EPSILON )
06538 {
06539 y = -x;
06540 }
06541 if ( y < 0.0 )
06542 {
06543 text_centering_rotation.Reverse();
06544 }
06545
06546 if ( ON::dtAboveLine == dimstyle_textalignment )
06547 {
06548 y = 0.5*textheight + dimstyle_textgap;
06549 text_centering_translation.x = -y*text_centering_rotation.y;
06550 text_centering_translation.y = y*text_centering_rotation.x;
06551 }
06552 }
06553 }
06554 else if ( ON::dtDimDiameter == ann_type
06555 || ON::dtDimRadius == ann_type
06556 || ON::dtLeader == ann_type
06557 || ON::dtDimOrdinate == ann_type)
06558 {
06559 ON_2dPoint E(0.0,0.0);
06560 ON_2dVector R(1.0,0.0);
06561 GetLeaderEndAndDirection( this, E, R );
06562
06563 text_centering_rotation = R;
06564
06565 text_centering_translation = (dimstyle_textgap + 0.5*text_line_width)*text_centering_rotation;
06566
06567 ON_3dVector V = text_centering_rotation.x*m_plane.xaxis + text_centering_rotation.y*m_plane.yaxis;
06568 x = V*cameraX;
06569 y = V*cameraY;
06570 if ( fabs(x) <= ON_SQRT_EPSILON && fabs(y) > ON_SQRT_EPSILON )
06571 {
06572 x = y;
06573 }
06574 if ( x < 0.0 )
06575 text_centering_rotation.Reverse();
06576
06577 if(cameraZ * m_plane.zaxis < 0.0)
06578 text_y_flip = true;
06579 }
06580 }
06581 else if(ann_type == ON::dtLeader)
06582 {
06583 if((m_justification & tjRight) == tjRight)
06584 text_centering_translation.Set(-(dimstyle_textgap + 0.5*text_line_width), 0.0);
06585 else if((m_justification & tjLeft) == tjLeft)
06586 text_centering_translation.Set(dimstyle_textgap + 0.5*text_line_width, 0.0);
06587
06588 }
06589
06590 ON_Xform text_centering_xform(1.0);
06591 text_centering_xform.m_xform[0][0] = text_centering_rotation.x;
06592 text_centering_xform.m_xform[0][1] = -text_centering_rotation.y;
06593 text_centering_xform.m_xform[1][0] = text_centering_rotation.y;
06594 if(text_y_flip)
06595 text_centering_xform.m_xform[1][1] = -text_centering_rotation.x;
06596 else
06597 text_centering_xform.m_xform[1][1] = text_centering_rotation.x;
06598
06599
06600
06601
06602 text_centering_xform.m_xform[0][3] = text_centering_translation.x;
06603 text_centering_xform.m_xform[1][3] = text_centering_translation.y;
06604
06605
06606
06607
06608 ON_2dVector text_offset_translation(0.0,0.0);
06609 switch( ann_type )
06610 {
06611 case ON::dtDimLinear:
06612 case ON::dtDimAligned:
06613 if ( m_points.Count() >= ON_LinearDimension2::dim_pt_count )
06614 {
06615 const ON_LinearDimension2* linear_dim = ON_LinearDimension2::Cast(ann);
06616 if ( linear_dim )
06617 {
06618 text_offset_translation = linear_dim->Dim2dPoint(ON_LinearDimension2::text_pivot_pt);
06619 }
06620 }
06621 break;
06622
06623 case ON::dtDimAngular:
06624 if ( m_points.Count() >= ON_AngularDimension2::dim_pt_count )
06625 {
06626 const ON_AngularDimension2* angular_dim = ON_AngularDimension2::Cast(ann);
06627 if ( angular_dim )
06628 {
06629 text_offset_translation = angular_dim->Dim2dPoint(ON_AngularDimension2::text_pivot_pt);
06630 }
06631 }
06632 break;
06633
06634 case ON::dtDimDiameter:
06635 case ON::dtDimRadius:
06636 if ( m_points.Count() >= ON_RadialDimension2::dim_pt_count )
06637 {
06638
06639 text_offset_translation = m_points[ON_RadialDimension2::tail_pt_index];
06640 }
06641 break;
06642
06643 case ON::dtLeader:
06644 if ( m_points.Count() > 0 )
06645 {
06646
06647 text_offset_translation = *m_points.Last();
06648 }
06649 break;
06650
06651 case ON::dtDimOrdinate:
06652 if ( m_points.Count() == 2 )
06653 {
06654
06655 text_offset_translation = m_points[1];
06656 }
06657 break;
06658
06659 case ON::dtTextBlock:
06660 case ON::dtNothing:
06661 break;
06662 }
06663
06664 ON_Xform plane_translation(1.0);
06665 plane_translation.m_xform[0][3] = text_offset_translation.x;
06666 plane_translation.m_xform[1][3] = text_offset_translation.y;
06667
06668
06669 ON_Xform plane_to_world(1.0);
06670 plane_to_world.Rotation(ON_xy_plane,ann->m_plane);
06671
06672 ON_Xform horizonal_xform(1.0);
06673 if ( ON::dtHorizontal == dimstyle_textalignment )
06674 {
06675 ON_3dPoint fixed_point = ann->m_plane.PointAt(text_offset_translation.x,text_offset_translation.y);
06676 horizonal_xform.Rotation(
06677 fixed_point,
06678 ann->m_plane.xaxis,
06679 ann->m_plane.yaxis,
06680 ann->m_plane.zaxis,
06681 fixed_point,
06682 cameraX,
06683 cameraY,
06684 cameraZ
06685 );
06686
06687 if ( 2 == position_style )
06688 {
06689
06690 ON_2dPoint E(0.0,0.0);
06691 ON_2dVector R(1.0,0.0);
06692 GetLeaderEndAndDirection( this, E, R );
06693 ON_3dVector V = R.x*m_plane.xaxis + R.y*m_plane.yaxis;
06694 x = V*cameraX;
06695 y = ( x > -ON_SQRT_EPSILON )
06696 ? dimstyle_textgap
06697 : -(dimstyle_textgap + text_line_width);
06698 V = y*cameraX;
06699 horizonal_xform.m_xform[0][3] += V.x;
06700 horizonal_xform.m_xform[1][3] += V.y;
06701 horizonal_xform.m_xform[2][3] += V.z;
06702 }
06703 }
06704
06705 ON_Xform gdi_to_world;
06706
06707 gdi_to_world = horizonal_xform
06708 * plane_to_world
06709 * plane_translation
06710 * text_centering_xform
06711 * gdi_to_plane;
06712
06713 xform = gdi_to_world;
06714
06715 return true;
06716 }
06717
06718 bool ON_Annotation2::GetTextPoint( ON_2dPoint& text_2d_point ) const
06719 {
06720 bool rc = false;
06721 switch ( m_type )
06722 {
06723 case ON::dtTextBlock:
06724 text_2d_point.Set(0.0,0.0);
06725 rc = true;
06726 break;
06727
06728 case ON::dtDimLinear:
06729 case ON::dtDimAligned:
06730 if ( m_userpositionedtext )
06731 {
06732 if ( m_points.Count() >= 5 )
06733 {
06734 text_2d_point = m_points[4];
06735 rc = true;
06736 }
06737 }
06738 else if ( m_points.Count() >= 3 )
06739 {
06740 text_2d_point.x = 0.5*(m_points[0].x + m_points[2].x);
06741 text_2d_point.y = m_points[2].y;
06742 rc = true;
06743 }
06744 break;
06745
06746 case ON::dtLeader:
06747 if ( m_points.Count() > 0 )
06748 {
06749 text_2d_point = *m_points.Last();
06750 rc = true;
06751 }
06752 break;
06753
06754 case ON::dtDimAngular:
06755 {
06756 const ON_AngularDimension2* angular_dim = ON_AngularDimension2::Cast(this);
06757 if ( angular_dim )
06758 {
06759 if ( m_userpositionedtext )
06760 {
06761 if ( m_points.Count() >= 0 )
06762 {
06763 text_2d_point = m_points[0];
06764 }
06765 }
06766 else
06767 {
06768 text_2d_point.x = angular_dim->m_radius*cos(angular_dim->m_angle);
06769 text_2d_point.y = angular_dim->m_radius*sin(angular_dim->m_angle);
06770 rc = true;
06771 }
06772 }
06773 }
06774 break;
06775
06776 case ON::dtDimRadius:
06777 case ON::dtDimDiameter:
06778
06779 if ( m_points.Count() >= 3 )
06780 {
06781 text_2d_point = m_points[2];
06782 rc = true;
06783 }
06784
06785 break;
06786
06787 case ON::dtDimOrdinate:
06788 case ON::dtNothing:
06789 break;
06790 }
06791 return rc;
06792 }
06793
06794
06796
06797
06798
06799 class ON_AnnotationTextFormula : public ON_UserData
06800 {
06801 #if !defined(BOZO_VACCINE_699FCC4262D4488c9109F1B7A37CE926)
06802 #error Never copy this class definition or put this definition in a header file!
06803 #endif
06804 ON_OBJECT_DECLARE(ON_AnnotationTextFormula);
06805 public:
06806 ON_AnnotationTextFormula();
06807 ~ON_AnnotationTextFormula();
06808
06809
06810 ON_BOOL32 GetDescription(ON_wString&);
06811
06812 static ON_AnnotationTextFormula* Get(const ON_Annotation2*);
06813 static void Set(ON_Annotation2*,const wchar_t* text_formula);
06814
06815 ON_wString m_text_formula;
06816 };
06817
06818 #undef BOZO_VACCINE_699FCC4262D4488c9109F1B7A37CE926
06819
06820 ON_OBJECT_IMPLEMENT(ON_AnnotationTextFormula,ON_UserData,"699FCC42-62D4-488c-9109-F1B7A37CE926");
06821
06822 ON_AnnotationTextFormula::~ON_AnnotationTextFormula()
06823 {}
06824
06825 ON_AnnotationTextFormula::ON_AnnotationTextFormula()
06826 {
06827 m_userdata_uuid = ON_AnnotationTextFormula::m_ON_AnnotationTextFormula_class_id.Uuid();
06828 m_application_uuid = ON_opennurbs5_id;
06829 m_userdata_copycount = 1;
06830 }
06831
06832 ON_BOOL32 ON_AnnotationTextFormula::GetDescription( ON_wString& description )
06833 {
06834 description = "Annotation Text Formula";
06835 return true;
06836 }
06837
06838 ON_AnnotationTextFormula* ON_AnnotationTextFormula::Get(const ON_Annotation2* p)
06839 {
06840 return (0 != p)
06841 ? ON_AnnotationTextFormula::Cast(p->GetUserData(ON_AnnotationTextFormula::m_ON_AnnotationTextFormula_class_id.Uuid()))
06842 : 0;
06843 }
06844
06845 void ON_AnnotationTextFormula::Set(ON_Annotation2* p,const wchar_t* text_formula)
06846 {
06847 if ( 0 != p )
06848 {
06849 ON_AnnotationTextFormula* tf = Get(p);
06850 if ( 0 == text_formula || 0 == text_formula[0] )
06851 {
06852 if (0 != tf )
06853 delete tf;
06854 }
06855 else
06856 {
06857 if ( 0 == tf )
06858 {
06859 tf = new ON_AnnotationTextFormula();
06860 p->AttachUserData(tf);
06861 }
06862 tf->m_text_formula = text_formula;
06863 }
06864 }
06865 }
06866
06867
06868
06870
06871 void ON_Annotation2::SetTextValue( const wchar_t* text_value )
06872 {
06873 m_usertext = text_value;
06874 }
06875
06876 const wchar_t* ON_Annotation2::TextValue() const
06877 {
06878 return ((const wchar_t*)m_usertext);
06879 }
06880
06881 void ON_Annotation2::SetTextFormula( const wchar_t* text_formula )
06882 {
06883 ON_AnnotationTextFormula::Set(this,text_formula);
06884 }
06885
06886 const wchar_t* ON_Annotation2::TextFormula() const
06887 {
06888 const ON_AnnotationTextFormula* tf = ON_AnnotationTextFormula::Get(this);
06889 return (0 != tf) ? ((const wchar_t*)tf->m_text_formula) : 0;
06890 }
06891