00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015
00016 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00017
00018
00019
00020
00021
00022
00023 class ON_HatchExtra : public ON_UserData
00024 {
00025 ON_OBJECT_DECLARE(ON_HatchExtra);
00026 public:
00027 static ON_HatchExtra* HatchExtension(ON_Hatch* pHatch, bool bCreate);
00028 static const ON_HatchExtra* HatchExtension(const ON_Hatch* pHatch, bool bCreate);
00029
00030 ON_HatchExtra();
00031 ~ON_HatchExtra();
00032
00033 void SetDefaults();
00034
00035
00036 void Dump( ON_TextLog& text_log ) const;
00037
00038
00039 unsigned int SizeOf() const;
00040
00041
00042 ON_BOOL32 Write(ON_BinaryArchive& binary_archive) const;
00043
00044
00045 ON_BOOL32 Read(ON_BinaryArchive& binary_archive);
00046
00047
00048 ON_BOOL32 GetDescription( ON_wString& description );
00049
00050
00051 ON_BOOL32 Archive() const;
00052
00053
00054 void SetBasePoint(ON_2dPoint& basepoint);
00055 ON_2dPoint BasePoint() const;
00056
00057 ON_UUID m_parent_hatch;
00058 ON_2dPoint m_basepoint;
00059
00060 };
00061
00062 ON_OBJECT_IMPLEMENT(ON_HatchExtra,ON_UserData,"3FF7007C-3D04-463f-84E3-132ACEB91062");
00063
00064 ON_HatchExtra* ON_HatchExtra::HatchExtension(ON_Hatch* pHatch, bool bCreate)
00065 {
00066 ON_HatchExtra* pExtra = 0;
00067 if(pHatch)
00068 {
00069 pExtra = ON_HatchExtra::Cast(pHatch->GetUserData(ON_HatchExtra::m_ON_HatchExtra_class_id.Uuid()));
00070 if(pExtra == 0 && bCreate)
00071 {
00072 pExtra = new ON_HatchExtra;
00073 if(pExtra)
00074 {
00075 if(!pHatch->AttachUserData(pExtra))
00076 {
00077 delete pExtra;
00078 pExtra = 0;
00079 }
00080 }
00081 }
00082 }
00083 return pExtra;
00084 }
00085
00086 const ON_HatchExtra* ON_HatchExtra::HatchExtension(const ON_Hatch* pHatch, bool bCreate)
00087 {
00088 return HatchExtension((ON_Hatch*)pHatch, bCreate);
00089 }
00090
00091 ON_HatchExtra::ON_HatchExtra()
00092 {
00093 m_userdata_uuid = ON_HatchExtra::m_ON_HatchExtra_class_id.Uuid();
00094 m_application_uuid = ON_opennurbs5_id;
00095
00096
00097
00098 m_userdata_copycount = 1;
00099 SetDefaults();
00100 }
00101
00102 ON_HatchExtra::~ON_HatchExtra()
00103 {
00104 }
00105
00106 void ON_HatchExtra::SetDefaults()
00107 {
00108 m_parent_hatch = ON_nil_uuid;
00109 m_basepoint.Set(0.0,0.0);
00110 }
00111
00112 void ON_HatchExtra::Dump(ON_TextLog& text_log) const
00113 {
00114 }
00115
00116 unsigned int ON_HatchExtra::SizeOf() const
00117 {
00118 unsigned int sz = ON_UserData::SizeOf();
00119 sz += sizeof(*this)-sizeof(ON_UserData);
00120 return sz;
00121 }
00122
00123 ON_BOOL32 ON_HatchExtra::Write(ON_BinaryArchive& archive) const
00124 {
00125 bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
00126
00127 if(rc) rc = archive.WriteUuid( m_parent_hatch);
00128 if(rc) rc = archive.WritePoint(m_basepoint);
00129
00130 if(!archive.EndWrite3dmChunk())
00131 rc = false;
00132
00133 return rc;
00134 }
00135
00136 ON_BOOL32 ON_HatchExtra::Read(ON_BinaryArchive& archive)
00137 {
00138 int major_version = 0;
00139 int minor_version = 0;
00140 bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
00141
00142 if(major_version != 1)
00143 rc = false;
00144
00145 m_basepoint.Set(0.0,0.0);
00146 if(rc) rc = archive.ReadUuid(m_parent_hatch);
00147 if(rc) rc = archive.ReadPoint(m_basepoint);
00148
00149 if(!archive.EndRead3dmChunk())
00150 rc = false;
00151
00152 return rc;
00153 }
00154
00155 ON_BOOL32 ON_HatchExtra::GetDescription( ON_wString& description)
00156 {
00157 description.Format( "Userdata extension of ON_Hatch (contains basepoint)");
00158 return true;
00159 }
00160
00161 ON_BOOL32 ON_HatchExtra::Archive() const
00162 {
00163 return true;
00164 }
00165
00166 void ON_HatchExtra::SetBasePoint(ON_2dPoint& point)
00167 {
00168 if(point.IsValid())
00169 m_basepoint = point;
00170 }
00171
00172 ON_2dPoint ON_HatchExtra::BasePoint() const
00173 {
00174 return m_basepoint;
00175 }
00176
00178
00180
00181 ON_HatchLine::ON_HatchLine()
00182 : m_angle( 0.0), m_base( 0.0,0.0), m_offset( 0.0, 1.0)
00183 {
00184 }
00185
00186 ON_HatchLine::ON_HatchLine(double angle,
00187 const ON_2dPoint& base,
00188 const ON_2dVector& offset,
00189 const ON_SimpleArray<double> dashes)
00190 : m_angle( angle), m_base( base), m_offset( offset), m_dashes( dashes)
00191 {
00192 }
00193
00194 bool ON_HatchLine::operator==(const ON_HatchLine& src) const
00195 {
00196 return( m_angle == src.m_angle &&
00197 m_base == src.m_base &&
00198 m_offset == src.m_offset &&
00199 m_dashes == src.m_dashes);
00200 }
00201
00202 bool ON_HatchLine::operator!=(const ON_HatchLine& src) const
00203 {
00204 return !operator==( src);
00205 }
00206
00207 ON_BOOL32 ON_HatchLine::IsValid( ON_TextLog* text_log) const
00208 {
00209 bool rc = m_angle >= 0.0;
00210 if( !rc)
00211 {
00212 if( text_log)
00213 text_log->Print( "Angle ( %lf) must be >= 0.0\n", m_angle);
00214 return false;
00215 }
00216 rc = m_angle < ON_PI * 2.0;
00217 if( !rc)
00218 {
00219 if( text_log)
00220 text_log->Print( "Angle ( %lf) must be < 2*Pi.\n", m_angle);
00221 return false;
00222 }
00223 rc = m_base != ON_2dPoint( ON_UNSET_VALUE, ON_UNSET_VALUE);
00224 if( !rc)
00225 {
00226 if( text_log)
00227 text_log->Print( "Base is not a valid point.\n");
00228 return false;
00229 }
00230 rc = m_offset.x != ON_UNSET_VALUE;
00231 if( !rc)
00232 {
00233 if( text_log)
00234 text_log->Print( "Offset is not a valid vector.\n");
00235 return false;
00236 }
00237 rc = m_offset.y > ON_SQRT_EPSILON;
00238 if( !rc)
00239 {
00240 if( text_log)
00241 text_log->Print( "Offset.y ( %lf) must be > 0.0", m_offset.y);
00242 return false;
00243 }
00244 return true;
00245 }
00246
00247 void ON_HatchLine::Dump( ON_TextLog& dump) const
00248 {
00249 dump.Print( "ON_HatchLine: angle = %lf radians ( %lf degrees) ",
00250 Angle(), ON_RADIANS_TO_DEGREES * Angle());
00251 dump.Print( " base = ");
00252 dump.Print( m_base);
00253 dump.Print( " offset = ");
00254 dump.Print( m_offset);
00255 int count = m_dashes.Count();
00256 dump.Print( "\nDash count = %d: ", count);
00257 for( int i = 0; i < count; i++)
00258 {
00259 dump.Print( "%lf", Dash( i));
00260 if( i < count-1)
00261 dump.Print( ", ");
00262 }
00263 dump.Print( "\n");
00264 }
00265
00266 ON_BOOL32 ON_HatchLine::Write( ON_BinaryArchive& ar) const
00267 {
00268 ON_BOOL32 rc = ar.Write3dmChunkVersion(1,1);
00269
00270 if (rc) rc = ar.WriteDouble( m_angle);
00271 if (rc) rc = ar.WritePoint( m_base);
00272 if (rc) rc = ar.WriteVector( m_offset);
00273 if (rc) rc = ar.WriteArray( m_dashes);
00274
00275 return rc;
00276 }
00277
00278 ON_BOOL32 ON_HatchLine::Read( ON_BinaryArchive& ar)
00279 {
00280 m_angle = 0.0;
00281 m_base.Set( 0.0, 0.0);
00282 m_offset.Set( 0.0, 1.0);
00283 m_dashes.Empty();
00284 int major_version = 0;
00285 int minor_version = 0;
00286 ON_BOOL32 rc = ar.Read3dmChunkVersion( &major_version, &minor_version);
00287 if ( major_version == 1 )
00288 {
00289 if ( rc) rc = ar.ReadDouble( &m_angle);
00290 if ( rc) rc = ar.ReadPoint( m_base);
00291 if ( rc) rc = ar.ReadVector( m_offset);
00292 if ( rc) rc = ar.ReadArray( m_dashes);
00293 }
00294 return rc;
00295 }
00296
00297
00298 double ON_HatchLine::Angle() const
00299 {
00300 return m_angle;
00301 }
00302
00303 void ON_HatchLine::SetAngle( double angle)
00304 {
00305 m_angle = angle;
00306 double twopi = ON_PI * 2.0;
00307
00308
00309 while( m_angle < 0.0)
00310 m_angle += twopi;
00311 while( m_angle > twopi)
00312 m_angle -= twopi;
00313 }
00314
00315 ON_2dPoint ON_HatchLine::Base() const
00316 {
00317 return m_base;
00318 }
00319
00320 void ON_HatchLine::SetBase( const ON_2dPoint& base)
00321 {
00322 m_base = base;
00323 }
00324
00325 ON_2dVector ON_HatchLine::Offset() const
00326 {
00327 return m_offset;
00328 }
00329
00330 void ON_HatchLine::SetOffset( const ON_2dVector& offset)
00331 {
00332 m_offset = offset;
00333 }
00334
00335 int ON_HatchLine::DashCount() const
00336 {
00337 return m_dashes.Count();
00338 }
00339
00340 double ON_HatchLine::Dash( int index) const
00341 {
00342 if( index >= 0 && index < m_dashes.Count())
00343 return m_dashes[index];
00344 return 0.0;
00345 }
00346
00347 void ON_HatchLine::AppendDash( double dash)
00348 {
00349
00350 m_dashes.Append( dash);
00351 }
00352
00353 void ON_HatchLine::SetPattern( const ON_SimpleArray<double>& dashes)
00354 {
00355 m_dashes = dashes;
00356 }
00357
00358 void ON_HatchLine::GetLineData( double& angle,
00359 ON_2dPoint& base,
00360 ON_2dVector& offset,
00361 ON_SimpleArray<double>& dashes) const
00362 {
00363 angle = m_angle;
00364 base = m_base;
00365 offset = m_offset; dashes = m_dashes;
00366 }
00367
00368 double ON_HatchLine::GetPatternLength() const
00369 {
00370 int i;
00371 double length = 0.0;
00372 for( i = 0; i < m_dashes.Count(); i++)
00373 length += fabs( m_dashes[i]);
00374
00375 return length;
00376 }
00377
00378
00379
00381 ON_OBJECT_IMPLEMENT( ON_HatchPattern, ON_Object, "064E7C91-35F6-4734-A446-79FF7CD659E1" );
00382
00383 ON_HatchPattern::ON_HatchPattern()
00384 : m_hatchpattern_index(-1)
00385 , m_hatchpattern_id(ON_nil_uuid)
00386 , m_type(ON_HatchPattern::ftSolid)
00387 {
00388 }
00389
00390 ON_HatchPattern::~ON_HatchPattern()
00391 {
00392 }
00393
00394 ON_BOOL32 ON_HatchPattern::IsValid( ON_TextLog* text_log) const
00395 {
00396 eFillType type = FillType();
00397 ON_BOOL32 rc = true;
00398 if( type != ftSolid && type != ftLines && type != ftGradient)
00399 {
00400 if( text_log)
00401 text_log->Print( "Type field not set correctly.\n");
00402 rc = false;
00403 }
00404 if( type == ftLines)
00405 {
00406 int count = m_lines.Count();
00407 if( count < 1)
00408 {
00409 if( text_log)
00410 text_log->Print( "Line type patetern with no lines.\n");
00411 return false;
00412 }
00413 for( int i = 0; i < count; i++)
00414 {
00415 if( !m_lines[i].IsValid())
00416 {
00417 if( text_log)
00418 text_log->Print( "Line[%d] is not valid.\n", i);
00419 return false;
00420 }
00421 }
00422 return true;
00423 }
00424 return rc;
00425 }
00426
00427 void ON_HatchPattern::Dump( ON_TextLog& dump) const
00428 {
00429 dump.Print( "Hatch pattern - ");
00430 switch( m_type)
00431 {
00432 case ftSolid:
00433 dump.Print( "fill type: Solid");
00434 break;
00435 case ftLines:
00436 dump.Print( "fill type: Lines");
00437 break;
00438 case ftGradient:
00439 dump.Print( "fill type: Gradient");
00440 break;
00441 case ftLast:
00442
00443 break;
00444 }
00445 dump.Print( "\n");
00446
00447 const wchar_t* wsHatchPatternName = m_hatchpattern_name;
00448 if ( 0 == wsHatchPatternName )
00449 wsHatchPatternName = L"";
00450 dump.Print( "Name: %ls\n", wsHatchPatternName);
00451
00452 const wchar_t* wsDescription = m_description;
00453 if ( 0 == wsDescription )
00454 wsDescription = L"";
00455 dump.Print( "Description: %ls\n", wsDescription);
00456
00457 if( m_type == ftLines)
00458 {
00459 int count = m_lines.Count();
00460 dump.Print( "Line count = %d\n", count);
00461 for( int i = 0; i < count; i++)
00462 {
00463 m_lines[i].Dump( dump);
00464 }
00465 dump.Print( "\n");
00466 }
00467 }
00468
00469 ON_BOOL32 ON_HatchPattern::Write( ON_BinaryArchive& ar) const
00470 {
00471 ON_BOOL32 rc = ar.Write3dmChunkVersion(1,2);
00472
00473 if (rc) rc = ar.WriteInt( m_hatchpattern_index);
00474 if (rc) rc = ar.WriteInt( m_type);
00475 if (rc) rc = ar.WriteString( m_hatchpattern_name);
00476 if (rc) rc = ar.WriteString( m_description);
00477 if( rc)
00478 {
00479 if( m_type == ftLines)
00480 {
00481 int i, count = m_lines.Count();
00482 if ( count < 0 )
00483 count = 0;
00484 rc = ar.WriteInt( count );
00485 for( i = 0; i < count && rc; i++)
00486 rc = m_lines[i].Write( ar);
00487 }
00488 }
00489
00490 if (rc) rc = ar.WriteUuid(m_hatchpattern_id);
00491
00492 return rc;
00493 }
00494
00495 ON_BOOL32 ON_HatchPattern::Read( ON_BinaryArchive& ar)
00496 {
00497 m_hatchpattern_index = -1;
00498 memset(&m_hatchpattern_id,0,sizeof(m_hatchpattern_id));
00499 m_type = ftSolid;
00500 m_hatchpattern_name.Empty();
00501 m_description.Empty();
00502 m_lines.Empty();
00503 int i;
00504
00505 int major_version = 0;
00506 int minor_version = 0;
00507 ON_BOOL32 rc = ar.Read3dmChunkVersion( &major_version, &minor_version);
00508 if ( major_version == 1 )
00509 {
00510 if( rc) rc = ar.ReadInt( &m_hatchpattern_index);
00511 i = 0;
00512 if( rc) rc = ar.ReadInt( &i);
00513 if( rc)
00514 {
00515 switch( i)
00516 {
00517 case 0: m_type = ftSolid; break;
00518 case 1: m_type = ftLines; break;
00519 case 2: m_type = ftGradient; break;
00520 default: rc = false; break;
00521 }
00522 }
00523 if( rc) rc = ar.ReadString( m_hatchpattern_name);
00524 if( rc) rc = ar.ReadString( m_description);
00525 if( rc)
00526 {
00527 if( m_type == ftLines)
00528 {
00529 m_lines.Empty();
00530 int count = 0;
00531 rc = ar.ReadInt( &count);
00532 if( rc && count > 0 )
00533 {
00534 m_lines.SetCapacity( count);
00535 int i;
00536 for( i = 0; rc && i < count; i++)
00537 {
00538 ON_HatchLine& line = m_lines.AppendNew();
00539 rc = line.Read( ar);
00540 }
00541 }
00542 }
00543 }
00544 if ( minor_version >= 2 )
00545 {
00546 rc = ar.ReadUuid(m_hatchpattern_id);
00547 }
00548 }
00549 return rc;
00550 }
00551
00552 ON_HatchPattern::eFillType ON_HatchPattern::FillType() const
00553 {
00554 if( m_type >= ftSolid && m_type < ftLast)
00555 return m_type;
00556
00557 return ftLast;
00558 }
00559
00560 void ON_HatchPattern::SetFillType( eFillType type)
00561 {
00562 m_type = type;
00563 }
00564
00565 void ON_HatchPattern::SetName( const wchar_t* pName)
00566 {
00567 m_hatchpattern_name = pName;
00568 m_hatchpattern_name.TrimLeftAndRight();
00569 }
00570
00571 void ON_HatchPattern::SetName( const char* pName)
00572 {
00573 m_hatchpattern_name = pName;
00574 m_hatchpattern_name.TrimLeftAndRight();
00575 }
00576
00577 void ON_HatchPattern::GetName( ON_wString& string) const
00578 {
00579 string = m_hatchpattern_name;
00580 }
00581
00582 const wchar_t* ON_HatchPattern::Name() const
00583 {
00584 return m_hatchpattern_name;
00585 }
00586
00587
00588 void ON_HatchPattern::SetDescription( const wchar_t* pDescription)
00589 {
00590 m_description = pDescription;
00591 }
00592
00593 void ON_HatchPattern::SetDescription( const char* pDescription)
00594 {
00595 m_description = pDescription;
00596 }
00597
00598 void ON_HatchPattern::GetDescription( ON_wString& string) const
00599 {
00600 string = m_description;
00601 }
00602
00603 const wchar_t* ON_HatchPattern::Description() const
00604 {
00605 return m_description;
00606 }
00607
00608
00609 void ON_HatchPattern::SetIndex( int i)
00610 {
00611 m_hatchpattern_index = i;
00612 }
00613
00614 int ON_HatchPattern::Index() const
00615 {
00616 return m_hatchpattern_index;
00617 }
00618
00619
00620
00621
00622 int ON_HatchPattern::HatchLineCount() const
00623 {
00624 return m_lines.Count();
00625 }
00626
00627 int ON_HatchPattern::AddHatchLine( const ON_HatchLine& line)
00628 {
00629 m_lines.Append( line);
00630 return m_lines.Count()-1;
00631 }
00632
00633 const ON_HatchLine* ON_HatchPattern::HatchLine( int index) const
00634 {
00635 if( index >= 0 && index < m_lines.Count())
00636 return &m_lines[index];
00637 else
00638 return NULL;
00639 }
00640
00641 bool ON_HatchPattern::RemoveHatchLine( int index)
00642 {
00643 if( index >= 0 && index < m_lines.Count())
00644 {
00645 m_lines.Remove( index);
00646 return true;
00647 }
00648 return false;
00649 }
00650
00651 void ON_HatchPattern::RemoveAllHatchLines()
00652 {
00653 m_lines.Empty();
00654 }
00655
00656 int ON_HatchPattern::SetHatchLines( const ON_ClassArray<ON_HatchLine> lines)
00657 {
00658 m_lines = lines;
00659 return m_lines.Count();
00660 }
00661
00662
00663
00664
00665
00667
00668 #if defined(ON_DLL_EXPORTS)
00669
00670
00671
00672
00673
00674
00675 void* ON_HatchLoop::operator new(size_t sz)
00676 {
00677
00678 return onmalloc(sz);
00679 }
00680
00681 void ON_HatchLoop::operator delete(void* p)
00682 {
00683
00684 onfree(p);
00685 }
00686
00687 void* ON_HatchLoop::operator new[] (size_t sz)
00688 {
00689
00690 return onmalloc(sz);
00691 }
00692
00693 void ON_HatchLoop::operator delete[] (void* p)
00694 {
00695
00696 onfree(p);
00697 }
00698
00699 void* ON_HatchLoop::operator new(size_t, void* p)
00700 {
00701
00702 return p;
00703 }
00704
00705 void ON_HatchLoop::operator delete(void*, void*)
00706 {
00707
00708 return;
00709 }
00710
00711 #endif
00712
00713
00714 ON_HatchLoop::ON_HatchLoop()
00715 : m_type( ON_HatchLoop::ltOuter), m_p2dCurve( NULL)
00716 {
00717 }
00718
00719 ON_HatchLoop::ON_HatchLoop( ON_Curve* pCurve2d, eLoopType type)
00720 : m_type( type), m_p2dCurve( pCurve2d)
00721 {
00722 }
00723
00724 ON_HatchLoop::ON_HatchLoop( const ON_HatchLoop& src)
00725 : m_type( src.m_type), m_p2dCurve( NULL)
00726 {
00727 if( src.m_p2dCurve)
00728 m_p2dCurve = src.m_p2dCurve->DuplicateCurve();
00729 }
00730
00731 ON_HatchLoop::~ON_HatchLoop()
00732 {
00733 delete m_p2dCurve;
00734 }
00735
00736 ON_HatchLoop& ON_HatchLoop::operator=( const ON_HatchLoop& src)
00737 {
00738 if( this != &src)
00739 {
00740 if( m_p2dCurve)
00741 delete m_p2dCurve;
00742 m_p2dCurve = src.m_p2dCurve->DuplicateCurve();
00743
00744 m_type = src.m_type;
00745 }
00746 return *this;
00747 }
00748
00749 ON_BOOL32 ON_HatchLoop::IsValid( ON_TextLog* text_log) const
00750 {
00751 ON_BOOL32 rc = m_p2dCurve != NULL;
00752 if( !rc)
00753 {
00754 if( text_log)
00755 text_log->Print( "2d loop curve is NULL\n");
00756 }
00757 if( rc)
00758 {
00759 rc = m_p2dCurve->IsValid( text_log);
00760 if( !rc)
00761 {
00762 if( text_log)
00763 text_log->Print( "Loop curve is not valid\n");
00764 }
00765 }
00766
00767 if( rc)
00768 {
00769 ON_BoundingBox box;
00770 m_p2dCurve->GetBoundingBox( box);
00771 rc = ( box.Max().z == box.Min().z && box.Max().z == 0.0);
00772 if( !rc)
00773 {
00774 if( text_log)
00775 text_log->Print( "2d loop curve has non-zero z coordinates\n");
00776 }
00777 }
00778
00779 if( rc && m_type != ltOuter && m_type != ltInner)
00780 {
00781 if( text_log)
00782 text_log->Print( "Loop type is invalid.\n");
00783 rc = false;
00784 }
00785
00786 return rc;
00787 }
00788
00789 void ON_HatchLoop::Dump( ON_TextLog& dump) const
00790 {
00791 if( m_type == ltOuter)
00792 dump.Print( "Outer hatch loop\n");
00793 if( m_type == ltInner)
00794 dump.Print( "Inner hatch loop\n");
00795
00796 if ( 0 == m_p2dCurve )
00797 {
00798 dump.Print( "2d curve: null pointer\n");
00799 }
00800 else
00801 {
00802 dump.Print( "2d curve:\n");
00803 m_p2dCurve->Dump(dump);
00804 }
00805
00806 }
00807
00808 ON_BOOL32 ON_HatchLoop::Write( ON_BinaryArchive& ar) const
00809 {
00810 ON_BOOL32 rc = ar.Write3dmChunkVersion(1,1);
00811 if( rc) rc = ar.WriteInt( m_type);
00812 if( rc) rc = ar.WriteObject( m_p2dCurve);
00813 return rc;
00814 }
00815
00816 ON_BOOL32 ON_HatchLoop::Read( ON_BinaryArchive& ar)
00817 {
00818 m_type = ltOuter;
00819 delete m_p2dCurve;
00820 m_p2dCurve = NULL;
00821 int major_version = 0;
00822 int minor_version = 0;
00823 ON_BOOL32 rc = ar.Read3dmChunkVersion( &major_version, &minor_version);
00824 if ( major_version == 1 )
00825 {
00826 int type = 0;
00827 if( rc) rc = ar.ReadInt( &type);
00828 if( rc)
00829 {
00830 switch( type)
00831 {
00832 case ltOuter: m_type = ltOuter; break;
00833 case ltInner: m_type = ltInner; break;
00834 default: rc = false; break;
00835 }
00836 }
00837 if( rc)
00838 {
00839 ON_Object* pObj = NULL;
00840 rc = ar.ReadObject( &pObj);
00841 if( pObj)
00842 {
00843 m_p2dCurve = ON_Curve::Cast( pObj);
00844 if( !m_p2dCurve)
00845 {
00846 rc = false;
00847 delete pObj;
00848 }
00849 }
00850 }
00851 }
00852 return rc;
00853 }
00854
00855 const ON_Curve* ON_HatchLoop::Curve() const
00856 {
00857 return m_p2dCurve;
00858 }
00859
00860 bool ON_HatchLoop::SetCurve( const ON_Curve& curve)
00861 {
00862 ON_Curve* pC = curve.DuplicateCurve();
00863 if( pC)
00864 {
00865 if(pC->Dimension() == 3 && !pC->ChangeDimension(2))
00866 return false;
00867
00868 if( m_p2dCurve)
00869 delete m_p2dCurve;
00870 m_p2dCurve = pC;
00871 }
00872 return true;
00873 }
00874 ON_HatchLoop::eLoopType ON_HatchLoop::Type() const
00875 {
00876 return m_type;
00877 }
00878
00879 void ON_HatchLoop::SetType( eLoopType type)
00880 {
00881 m_type = type;
00882 }
00883
00884
00886 ON_OBJECT_IMPLEMENT( ON_Hatch, ON_Geometry, "0559733B-5332-49d1-A936-0532AC76ADE5");
00887
00888
00889 ON_Hatch::ON_Hatch()
00890 : m_pattern_scale( 1.0),
00891 m_pattern_rotation( 0.0),
00892 m_pattern_index( -1)
00893 {
00894 }
00895
00896 ON_Hatch::ON_Hatch( const ON_Hatch& src)
00897 : ON_Geometry(src),
00898 m_plane( src.m_plane),
00899 m_pattern_scale( src.m_pattern_scale),
00900 m_pattern_rotation( src.m_pattern_rotation),
00901 m_pattern_index( src.m_pattern_index)
00902 {
00903 m_loops.Reserve( src.m_loops.Count());
00904 for( int i = 0; i < src.m_loops.Count(); i++)
00905 {
00906 ON_HatchLoop* pL = new ON_HatchLoop( *src.m_loops[i]);
00907 m_loops.Append( pL);
00908 }
00909 }
00910
00911 ON_Hatch& ON_Hatch::operator=( const ON_Hatch& src)
00912 {
00913 if( this != &src)
00914 {
00915
00916
00917 int i;
00918 for ( i = 0; i < m_loops.Count(); i++ )
00919 {
00920 ON_HatchLoop* pL = m_loops[i];
00921 if ( pL )
00922 {
00923 m_loops[i] = 0;
00924 delete pL;
00925 }
00926 }
00927 m_loops.SetCount(0);
00928
00929 ON_Geometry::operator =(src);
00930
00931 m_plane = src.m_plane;
00932 m_pattern_index = src.m_pattern_index;
00933 m_pattern_scale = src.m_pattern_scale;
00934 m_pattern_rotation = src.m_pattern_rotation;
00935 m_loops.Reserve( src.m_loops.Count());
00936 for( i = 0; i < src.m_loops.Count(); i++)
00937 {
00938 ON_HatchLoop* pL = new ON_HatchLoop( *src.m_loops[i]);
00939 m_loops.Append( pL);
00940 }
00941 }
00942 return *this;
00943 }
00944
00945 ON_Hatch::~ON_Hatch()
00946 {
00947 int i;
00948 for ( i = 0; i < m_loops.Count(); i++ )
00949 {
00950 ON_HatchLoop* pL = m_loops[i];
00951 if ( pL )
00952 {
00953 m_loops[i] = 0;
00954 delete pL;
00955 }
00956 }
00957 }
00958
00959
00960 ON_Hatch* ON_Hatch::DuplicateHatch() const
00961 {
00962 return Duplicate();
00963 }
00964
00965 ON_BOOL32 ON_Hatch::IsValid( ON_TextLog* text_log) const
00966 {
00967 ON_BOOL32 rc = m_plane.IsValid();
00968 if( !rc)
00969 {
00970 if( text_log)
00971 text_log->Print( "Plane is not valid\n");
00972 return false;
00973 }
00974
00975
00976 int count = m_loops.Count();
00977 for(int i = 0; i < count; i++)
00978 {
00979 if(m_loops[i] == 0)
00980 {
00981 if( text_log)
00982 text_log->Print( "Loop[%d] is NULL\n", i);
00983 return false;
00984 }
00985 if(rc)
00986 rc = m_loops[i]->IsValid( text_log);
00987 if( !rc)
00988 {
00989 if( text_log)
00990 text_log->Print( "Loop[%d] is not valid\n", i);
00991 return false;
00992 }
00993 }
00994
00995 return true;
00996 }
00997
00998 void ON_Hatch::Dump( ON_TextLog& dump) const
00999 {
01000 dump.Print("Hatch: Pattern index: %d\n", PatternIndex());
01001 dump.Print("Pattern rotation: %g\n", PatternRotation());
01002 dump.Print("Pattern scale: %g\n", PatternScale());
01003 ON_3dPoint p = this->BasePoint();
01004 dump.Print("Base point: %g, %g, %g\n", p.x, p.y, p.z);
01005 dump.Print("Plane origin: %g, %g, %g\n", m_plane.origin.x, m_plane.origin.y, m_plane.origin.z);
01006 dump.Print("Plane x axis: %g, %g, %g\n", m_plane.xaxis.x, m_plane.xaxis.y, m_plane.xaxis.z);
01007 dump.Print("Plane y axis: %g, %g, %g\n", m_plane.yaxis.x, m_plane.yaxis.y, m_plane.yaxis.z);
01008 dump.Print("Plane z axis: %g, %g, %g\n", m_plane.zaxis.x, m_plane.zaxis.y, m_plane.zaxis.z);
01009 int count = m_loops.Count();
01010 dump.Print("Loop count = %d\n", count);
01011 for( int i = 0; i < count; i++)
01012 m_loops[i]->Dump( dump);
01013 }
01014
01015 ON_BOOL32 ON_Hatch::Write( ON_BinaryArchive& ar) const
01016 {
01017 ON_BOOL32 rc = ar.Write3dmChunkVersion(1,1);
01018 if (rc) rc = ar.WritePlane( m_plane);
01019 if (rc) rc = ar.WriteDouble( m_pattern_scale);
01020 if (rc) rc = ar.WriteDouble( m_pattern_rotation);
01021 if (rc) rc = ar.WriteInt( m_pattern_index);
01022 if (rc)
01023 {
01024 int i, count = m_loops.Count();
01025 if( count < 0 )
01026 count = 0;
01027 ON_BOOL32 rc = ar.WriteInt( count);
01028 for( i = 0; i < count && rc; i++)
01029 rc = m_loops[i]->Write( ar);
01030 }
01031 return rc;
01032 }
01033
01034 ON_BOOL32 ON_Hatch::Read( ON_BinaryArchive& ar)
01035 {
01036 m_plane.CreateFromNormal( ON_origin, ON_zaxis);
01037 m_pattern_scale = 1.0;
01038 m_pattern_rotation = 0.0;
01039 m_pattern_index = -1;
01040 m_loops.Empty();
01041 int major_version = 0;
01042 int minor_version = 0;
01043 ON_BOOL32 rc = ar.Read3dmChunkVersion( &major_version, &minor_version);
01044 if ( major_version == 1 )
01045 {
01046 if( rc) rc = ar.ReadPlane( m_plane);
01047 if( rc) rc = ar.ReadDouble( &m_pattern_scale);
01048 if( rc) rc = ar.ReadDouble( &m_pattern_rotation);
01049 if( rc) rc = ar.ReadInt( &m_pattern_index);
01050 if( rc)
01051 {
01052 m_loops.Empty();
01053 int i, count = 0;
01054 rc = ar.ReadInt( &count);
01055 if( rc && count > 0)
01056 {
01057 m_loops.SetCapacity( count );
01058 for( i = 0; rc && i < count; i++)
01059 {
01060 ON_HatchLoop*& pLoop = m_loops.AppendNew();
01061 pLoop = new ON_HatchLoop;
01062 if( pLoop)
01063 rc = pLoop->Read( ar);
01064 else
01065 rc = false;
01066 }
01067 }
01068 }
01069 }
01070 return rc;
01071 }
01072
01073 ON::object_type ON_Hatch::ObjectType() const
01074 {
01075 return ON::hatch_object;
01076 }
01077
01078 int ON_Hatch::Dimension() const
01079 {
01080 return 3;
01081 }
01082
01083
01084
01085 ON_Curve* ON_Hatch::LoopCurve3d( int index) const
01086 {
01087 int count = m_loops.Count();
01088 ON_Curve* pC = NULL;
01089
01090 if( index >= 0 && index < count)
01091 {
01092 if( m_loops[index]->Curve())
01093 {
01094 pC = m_loops[index]->Curve()->DuplicateCurve();
01095 if( pC)
01096 {
01097 pC->ChangeDimension( 3);
01098
01099 ON_Xform xf;
01100 xf.Rotation( ON_xy_plane, m_plane);
01101
01102 pC->Transform( xf);
01103 }
01104 }
01105 }
01106 return pC;
01107 }
01108
01109
01110 int ON_Hatch::PatternIndex() const
01111 {
01112 return m_pattern_index;
01113 }
01114
01115 void ON_Hatch::SetPatternIndex( int index)
01116 {
01117 m_pattern_index = index;
01118 }
01119
01120
01121 ON_BOOL32 ON_Hatch::GetBBox( double* bmin, double* bmax, ON_BOOL32 bGrowBox) const
01122 {
01123 int i;
01124 int count = m_loops.Count();
01125 ON_BOOL32 rc = true;
01126 ON_Curve* pC;
01127 for( i = 0; rc && i < count; i++)
01128 {
01129 pC = LoopCurve3d( i);
01130 if( pC)
01131 {
01132 rc = pC->GetBBox( bmin, bmax, i?true:bGrowBox);
01133 delete pC;
01134 }
01135 }
01136 return rc;
01137 }
01138
01139 bool ON_Hatch::GetTightBoundingBox( ON_BoundingBox& tight_bbox, int bGrowBox, const ON_Xform* xform) const
01140 {
01141 int i;
01142 int count = m_loops.Count();
01143 ON_CurveArray curves(count);
01144 for( i = 0; i < count; i++)
01145 {
01146 curves.Append( LoopCurve3d(i) );
01147 }
01148 return curves.GetTightBoundingBox(tight_bbox,bGrowBox,xform);
01149 }
01150
01151 static double Angle3d(const ON_3dVector& axis, ON_3dVector& from, const ON_3dVector& to)
01152 {
01153 ON_3dVector x = from, a = to;
01154 x.Unitize();
01155 a.Unitize();
01156
01157 ON_3dVector y = ON_CrossProduct(axis, from);
01158 y.Unitize();
01159
01160 double cosa = x * a;
01161
01162 if(cosa > 1.0 - ON_SQRT_EPSILON)
01163 return 0.0;
01164 if(cosa < ON_SQRT_EPSILON - 1.0)
01165 return ON_PI;
01166
01167 double sina = a * y;
01168
01169 return atan2(sina, cosa);
01170 }
01171
01172
01173 #define ARBBOUND 0.015625
01174 void arbaxis(const ON_3dVector& givenaxis, ON_3dVector& newaxis)
01175 {
01176 if(fabs(givenaxis[0]) < ARBBOUND && fabs(givenaxis[1]) < ARBBOUND)
01177 newaxis = ON_CrossProduct(ON_yaxis, givenaxis);
01178 else
01179 newaxis = ON_CrossProduct(ON_zaxis, givenaxis);
01180
01181 newaxis.Unitize();
01182 }
01183
01184 double arbaxisRotation(const ON_Plane& plane)
01185 {
01186
01187 ON_3dVector arbXaxis;
01188 arbaxis(plane.zaxis, arbXaxis);
01189 return Angle3d(plane.zaxis, arbXaxis, plane.xaxis);
01190 }
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203 static void UnrotateHatch(ON_Hatch* hatch)
01204 {
01205 double a = arbaxisRotation(hatch->Plane());
01206 ON_Plane& plane = *(ON_Plane*)(&hatch->Plane());
01207 if(fabs(a) > ON_ZERO_TOLERANCE)
01208 {
01209 plane.Rotate(-a, plane.zaxis);
01210 for(int i = 0; i < hatch->LoopCount(); i++)
01211 {
01212 ON_Curve* pC = (ON_Curve*)hatch->Loop(i)->Curve();
01213 pC->Rotate(a, ON_zaxis, ON_origin);
01214 }
01215 hatch->SetPatternRotation(hatch->PatternRotation()+a);
01216 }
01217 ON_3dPoint P;
01218 plane.ClosestPointTo(ON_origin, &P.x, &P.y);
01219
01220 if(fabs(P.x) > ON_ZERO_TOLERANCE ||fabs(P.y) > ON_ZERO_TOLERANCE ||fabs(P.z) > ON_ZERO_TOLERANCE)
01221 {
01222 ON_2dVector V(-P.x, -P.y);
01223 for(int i = 0; i < hatch->LoopCount(); i++)
01224 {
01225 ON_Curve* pC = (ON_Curve*)hatch->Loop(i)->Curve();
01226 pC->Translate(V);
01227 }
01228 P = plane.PointAt(P.x, P.y);
01229 plane.origin = P;
01230 }
01231 }
01232
01233 ON_BOOL32 ON_Hatch::Transform( const ON_Xform& xform)
01234 {
01235 if( fabs( fabs( xform.Determinant()) - 1.0) > 1.0e-4)
01236 {
01237
01238 ON_Plane tmp( m_plane);
01239 tmp.Transform( xform);
01240 ON_Xform A, B, T;
01241 A.Rotation( ON_xy_plane, m_plane);
01242 B.Rotation( tmp, ON_xy_plane);
01243 T = B * xform * A;
01244
01245
01246 T[0][2] = T[0][3] = 0.0;
01247 T[1][2] = T[1][3] = 0.0;
01248 T[2][0] = T[2][1] = 0.0; T[2][2] = 1.0; T[2][3] = 0.0;
01249 T[3][0] = T[3][1] = T[3][2] = 0.0; T[3][3] = 1.0;
01250
01251 for( int i = 0; i < LoopCount(); i++)
01252 m_loops[i]->m_p2dCurve->Transform( T);
01253 }
01254 int rc = m_plane.Transform( xform);
01255
01256 UnrotateHatch(this);
01257
01258 TransformUserData(xform);
01259
01260
01261
01262
01263 return rc;
01264 }
01265
01266 bool ON_Hatch::Create( const ON_Plane& plane,
01267 const ON_SimpleArray<const ON_Curve*> loops,
01268 int pattern_index,
01269 double pattern_rotation,
01270 double pattern_scale)
01271 {
01272 if( loops.Count() < 1)
01273 return false;
01274 if( pattern_index < 0)
01275 return false;
01276 SetPlane( plane);
01277 for( int i = 0; i < loops.Count(); i++)
01278 {
01279 ON_HatchLoop* pLoop = new ON_HatchLoop;
01280 pLoop->SetCurve( *loops[i]);
01281 pLoop->SetType( i?ON_HatchLoop::ltInner:ON_HatchLoop::ltOuter);
01282 AddLoop( pLoop);
01283 }
01284 SetPatternIndex( pattern_index);
01285 SetPatternRotation( pattern_rotation);
01286 SetPatternScale( pattern_scale);
01287 return true;
01288 }
01289
01290 const ON_Plane& ON_Hatch::Plane() const
01291 {
01292 return m_plane;
01293 }
01294
01295 void ON_Hatch::SetPlane( const ON_Plane& plane)
01296 {
01297 m_plane = plane;
01298 }
01299
01300 double ON_Hatch::PatternRotation() const
01301 {
01302 return m_pattern_rotation;
01303 }
01304
01305 void ON_Hatch::SetPatternRotation( double rotation)
01306 {
01307 m_pattern_rotation = rotation;
01308 }
01309
01310 double ON_Hatch::PatternScale() const
01311 {
01312 return m_pattern_scale;
01313 }
01314
01315 void ON_Hatch::SetPatternScale( double scale)
01316 {
01317 if( scale > 0.001)
01318 m_pattern_scale = scale;
01319 }
01320
01321 int ON_Hatch::LoopCount() const
01322 {
01323 return m_loops.Count();
01324 }
01325
01326 void ON_Hatch::AddLoop( ON_HatchLoop* pLoop)
01327 {
01328 m_loops.Append( pLoop);
01329 }
01330
01331 bool ON_Hatch::InsertLoop( int index, ON_HatchLoop* loop)
01332 {
01333 if( index >= 0 && index <= m_loops.Count())
01334 {
01335 m_loops.Insert(index, loop);
01336 return true;
01337 }
01338
01339 return false;
01340 }
01341
01342 bool ON_Hatch::RemoveLoop( int index)
01343 {
01344 if( index >= 0 && index < m_loops.Count())
01345 {
01346 delete m_loops[index];
01347 m_loops.Remove(index);
01348 return true;
01349 }
01350
01351 return false;
01352 }
01353
01354
01355 bool ON_Hatch::ReplaceLoops(ON_SimpleArray<const ON_Curve*> loop_curves)
01356 {
01357 if(loop_curves.Count() < 1)
01358 return false;
01359
01360 bool rc = true;
01361 ON_Xform xf;
01362 bool flat = false;
01363 ON_SimpleArray<ON_HatchLoop*> loops;
01364
01365 for(int i = 0; i < loop_curves.Count(); i++)
01366 {
01367 if(loop_curves[i] == 0)
01368 {
01369 rc = false;
01370 break;
01371 }
01372 ON_Curve* p2d = loop_curves[i]->Duplicate();
01373 if(p2d == 0)
01374 {
01375 rc = false;
01376 break;
01377 }
01378 if(p2d->Dimension() == 3)
01379 {
01380 if(!flat)
01381 {
01382 xf.PlanarProjection(m_plane);
01383 flat = true;
01384 }
01385 if(!p2d->Transform(xf) ||
01386 !p2d->ChangeDimension(2))
01387 {
01388 delete p2d;
01389 rc = false;
01390 break;
01391 }
01392 }
01393 ON_HatchLoop* loop = new ON_HatchLoop(p2d,loops.Count()?ON_HatchLoop::ltInner:ON_HatchLoop::ltOuter);
01394 if(loop)
01395 loops.Append(loop);
01396 else
01397 delete p2d;
01398 }
01399 if(!rc)
01400 {
01401 for(int i = 0; i < loops.Count(); i++)
01402 delete loops[i];
01403
01404 loops.Empty();
01405 }
01406
01407 if(loops.Count() < 1)
01408 return false;
01409
01410 for(int i = 0; i < m_loops.Count(); i++)
01411 delete m_loops[i];
01412 m_loops.Empty();
01413 for(int i = 0; i < loops.Count(); i++)
01414 m_loops.Append(loops[i]);
01415 return true;
01416 }
01417
01418 const ON_HatchLoop* ON_Hatch::Loop( int index) const
01419 {
01420 if( index >= 0 && index < m_loops.Count())
01421 return m_loops[index];
01422
01423 return NULL;
01424 }
01425
01426
01427 void ON_Hatch::SetBasePoint(ON_2dPoint basepoint)
01428 {
01429 ON_HatchExtra* pE = ON_HatchExtra::HatchExtension(this,true);
01430 if(pE)
01431 {
01432 pE->SetBasePoint(basepoint);
01433 }
01434 }
01435
01436 void ON_Hatch::SetBasePoint(ON_3dPoint point)
01437 {
01438 ON_HatchExtra* pE = ON_HatchExtra::HatchExtension(this,true);
01439 if(pE)
01440 {
01441 ON_2dPoint base;
01442 if(m_plane.ClosestPointTo(point, &base.x, &base.y))
01443 pE->SetBasePoint(base);
01444 }
01445 }
01446
01447 ON_3dPoint ON_Hatch::BasePoint() const
01448 {
01449 ON_3dPoint point(ON_origin);
01450 const ON_HatchExtra* pE = ON_HatchExtra::HatchExtension(this,false);
01451 if(pE)
01452 {
01453 ON_2dPoint base = pE->BasePoint();
01454 point = m_plane.PointAt(base.x, base.y);
01455 }
01456 return point;
01457 }
01458
01459 ON_2dPoint ON_Hatch::BasePoint2d() const
01460 {
01461 ON_2dPoint basepoint(0.0,0.0);
01462 const ON_HatchExtra* pE = ON_HatchExtra::HatchExtension(this,false);
01463 if(pE)
01464 basepoint = pE->BasePoint();
01465
01466 return basepoint;
01467 }
01468
01469
01470
01471 class ON_HatchExtra* ON_Hatch::HatchExtension()
01472 {
01473 ON_HatchExtra* pExtra = ON_HatchExtra::Cast( GetUserData( ON_HatchExtra::m_ON_HatchExtra_class_id.Uuid()));
01474 return pExtra;
01475 }