mirror of
https://github.com/mcneel/opennurbs.git
synced 2026-03-01 03:26:09 +08:00
1702 lines
41 KiB
C++
1702 lines
41 KiB
C++
//
|
|
// Copyright (c) 1993-2022 Robert McNeel & Associates. All rights reserved.
|
|
// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
|
|
// McNeel & Associates.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
|
|
// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
|
|
// MERCHANTABILITY ARE HEREBY DISCLAIMED.
|
|
//
|
|
// For complete openNURBS copyright information see <http://www.opennurbs.org>.
|
|
//
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
#include "opennurbs.h"
|
|
|
|
#if !defined(ON_COMPILING_OPENNURBS)
|
|
// This check is included in all opennurbs source .c and .cpp files to insure
|
|
// ON_COMPILING_OPENNURBS is defined when opennurbs source is compiled.
|
|
// When opennurbs source is being compiled, ON_COMPILING_OPENNURBS is defined
|
|
// and the opennurbs .h files alter what is declared and how it is declared.
|
|
#error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs
|
|
#endif
|
|
|
|
bool
|
|
ON_BrepVertex::Write( ON_BinaryArchive& file ) const
|
|
{
|
|
bool rc = file.WriteInt( m_vertex_index );
|
|
if ( rc )
|
|
rc = file.WritePoint( point );
|
|
if ( rc )
|
|
rc = file.WriteArray( m_ei );
|
|
if ( rc )
|
|
rc = file.WriteDouble( m_tolerance );
|
|
return rc;
|
|
}
|
|
|
|
bool
|
|
ON_BrepVertex::Read( ON_BinaryArchive& file )
|
|
{
|
|
bool rc = file.ReadInt( &m_vertex_index );
|
|
if ( rc )
|
|
rc = file.ReadPoint( point );
|
|
if ( rc )
|
|
rc = file.ReadArray( m_ei );
|
|
if ( rc )
|
|
rc = file.ReadDouble( &m_tolerance );
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepEdge::Write( ON_BinaryArchive& file ) const
|
|
{
|
|
bool rc = file.WriteInt( m_edge_index );
|
|
if (rc) rc = file.WriteInt( m_c3i );
|
|
int i = ProxyCurveIsReversed() ? 1 : 0;
|
|
if (rc) rc = file.WriteInt( i );
|
|
if (rc) rc = file.WriteInterval( ProxyCurveDomain() );
|
|
if (rc) rc = file.WriteInt( 2, m_vi );
|
|
if (rc) rc = file.WriteArray( m_ti );
|
|
if (rc) rc = file.WriteDouble( m_tolerance );
|
|
if ( file.Archive3dmVersion() >= 3 )
|
|
{
|
|
// added in opennurbs version 200206180
|
|
if (rc)
|
|
rc = file.WriteInterval( Domain() );
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepEdge::Read( ON_BinaryArchive& file )
|
|
{
|
|
int bReversed = false;
|
|
ON_Interval proxy_domain;
|
|
bool rc = file.ReadInt( &m_edge_index );
|
|
if (rc) rc = file.ReadInt( &m_c3i );
|
|
if (rc) rc = file.ReadInt( &bReversed );
|
|
if (rc) rc = file.ReadInterval( proxy_domain );
|
|
if (rc) rc = file.ReadInt( 2, m_vi );
|
|
if (rc) rc = file.ReadArray( m_ti );
|
|
if (rc) rc = file.ReadDouble( &m_tolerance );
|
|
ON_Interval domain = proxy_domain;
|
|
if ( file.Archive3dmVersion() >= 3
|
|
&& file.ArchiveOpenNURBSVersion() >= 200206180 )
|
|
{
|
|
if (rc)
|
|
{
|
|
rc = file.ReadInterval(domain);
|
|
if ( !rc)
|
|
domain = proxy_domain;
|
|
}
|
|
}
|
|
SetProxyCurve( nullptr, proxy_domain );
|
|
if ( bReversed )
|
|
ON_CurveProxy::Reverse();
|
|
SetDomain(domain);
|
|
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepTrim::Write( ON_BinaryArchive& file ) const
|
|
{
|
|
ON_3dPoint P(0.0,0.0,0.0);
|
|
bool rc = file.WriteInt( m_trim_index );
|
|
int i;
|
|
if ( rc )
|
|
rc = file.WriteInt( m_c2i );
|
|
if ( rc )
|
|
rc = file.WriteInterval( ProxyCurveDomain() );
|
|
if ( rc )
|
|
rc = file.WriteInt( m_ei );
|
|
if ( rc )
|
|
rc = file.WriteInt( 2, m_vi );
|
|
if ( rc )
|
|
rc = file.WriteInt( m_bRev3d );
|
|
i = m_type;
|
|
if ( rc )
|
|
rc = file.WriteInt( i );
|
|
i = m_iso;
|
|
if ( rc )
|
|
rc = file.WriteInt( i );
|
|
if ( rc )
|
|
rc = file.WriteInt( m_li );
|
|
if ( rc )
|
|
rc = file.WriteDouble( 2, m_tolerance );
|
|
if ( file.Archive3dmVersion() < 3 )
|
|
{
|
|
if ( rc )
|
|
rc = file.WritePoint( P ); // m_P[0] );
|
|
if ( rc )
|
|
rc = file.WritePoint( P ); // m_P[1] );
|
|
}
|
|
else
|
|
{
|
|
// trim proxy curve information added in version 200206180
|
|
if (rc )
|
|
rc = file.WriteInterval( Domain() );
|
|
unsigned char b[24];
|
|
memset(b,0,sizeof(b));
|
|
b[0] = ProxyCurveIsReversed() ? 1 : 0;
|
|
if (rc)
|
|
rc = file.WriteChar(8,b);
|
|
b[0] = 0;
|
|
if (rc)
|
|
rc = file.WriteChar(24,b);
|
|
}
|
|
if ( rc )
|
|
rc = file.WriteDouble( m__legacy_2d_tol );
|
|
if ( rc )
|
|
rc = file.WriteDouble( m__legacy_3d_tol );
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepTrim::Read( ON_BinaryArchive& file )
|
|
{
|
|
ON_3dPoint P[2];
|
|
int i;
|
|
bool rc = file.ReadInt( &m_trim_index );
|
|
if ( rc )
|
|
rc = file.ReadInt( &m_c2i );
|
|
if ( rc )
|
|
{
|
|
ON_Interval d;
|
|
rc = file.ReadInterval( d );
|
|
if (rc)
|
|
{
|
|
SetProxyCurveDomain(d);
|
|
SetDomain(d);
|
|
}
|
|
}
|
|
if ( rc )
|
|
rc = file.ReadInt( &m_ei );
|
|
if ( rc )
|
|
rc = file.ReadInt( 2, m_vi );
|
|
if ( rc )
|
|
{
|
|
i = m_bRev3d;
|
|
rc = file.ReadInt( &i );
|
|
if (rc)
|
|
m_bRev3d = (i!=0);
|
|
}
|
|
|
|
i = unknown;
|
|
if ( rc )
|
|
rc = file.ReadInt( &i );
|
|
switch (i) {
|
|
case unknown:
|
|
m_type = unknown;
|
|
break;
|
|
case boundary:
|
|
m_type = boundary;
|
|
break;
|
|
case mated:
|
|
m_type = mated;
|
|
break;
|
|
case seam:
|
|
m_type = seam;
|
|
break;
|
|
case singular:
|
|
m_type = singular;
|
|
break;
|
|
}
|
|
|
|
i = ON_Surface::not_iso;
|
|
if ( rc )
|
|
rc = file.ReadInt( &i );
|
|
switch(i) {
|
|
case ON_Surface::not_iso:
|
|
m_iso = ON_Surface::not_iso;
|
|
break;
|
|
case ON_Surface::x_iso:
|
|
m_iso = ON_Surface::x_iso;
|
|
break;
|
|
case ON_Surface::y_iso:
|
|
m_iso = ON_Surface::y_iso;
|
|
break;
|
|
case ON_Surface::W_iso:
|
|
m_iso = ON_Surface::W_iso;
|
|
break;
|
|
case ON_Surface::S_iso:
|
|
m_iso = ON_Surface::S_iso;
|
|
break;
|
|
case ON_Surface::E_iso:
|
|
m_iso = ON_Surface::E_iso;
|
|
break;
|
|
case ON_Surface::N_iso:
|
|
m_iso = ON_Surface::N_iso;
|
|
break;
|
|
}
|
|
|
|
if ( rc )
|
|
rc = file.ReadInt( &m_li );
|
|
if ( rc )
|
|
rc = file.ReadDouble( 2, m_tolerance );
|
|
if ( file.Archive3dmVersion() >= 3 && file.ArchiveOpenNURBSVersion() >= 200206180 )
|
|
{
|
|
// read trim proxy curve information added in version 200206180
|
|
ON_Interval d = ProxyCurveDomain();
|
|
if (rc )
|
|
{
|
|
rc = file.ReadInterval( d );
|
|
if ( !rc )
|
|
d = ProxyCurveDomain();
|
|
}
|
|
unsigned char b[24];
|
|
memset(b,0,sizeof(b));
|
|
bool bProxyCurveIsReversed = false;
|
|
if (rc)
|
|
{
|
|
rc = file.ReadChar(8,b);
|
|
if (rc && b[0] == 1 )
|
|
bProxyCurveIsReversed = true;
|
|
}
|
|
if (rc)
|
|
rc = file.ReadChar(24,b);
|
|
|
|
if ( bProxyCurveIsReversed )
|
|
ON_CurveProxy::Reverse();
|
|
SetDomain(d);
|
|
}
|
|
else
|
|
{
|
|
if ( rc )
|
|
rc = file.ReadPoint( P[0] ); //m_P[0] );
|
|
if ( rc )
|
|
rc = file.ReadPoint( P[1] ); //m_P[1] );
|
|
}
|
|
if ( rc )
|
|
rc = file.ReadDouble( &m__legacy_2d_tol );
|
|
if ( rc )
|
|
rc = file.ReadDouble( &m__legacy_3d_tol );
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepLoop::Write( ON_BinaryArchive& file ) const
|
|
{
|
|
int i;
|
|
bool rc = file.WriteInt( m_loop_index );
|
|
if (rc)
|
|
rc = file.WriteArray( m_ti );
|
|
i = m_type;
|
|
if (rc)
|
|
rc = file.WriteInt( i );
|
|
if (rc)
|
|
rc = file.WriteInt( m_fi );
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepLoop::Read( ON_BinaryArchive& file )
|
|
{
|
|
int i;
|
|
bool rc = file.ReadInt( & m_loop_index );
|
|
if (rc)
|
|
rc = file.ReadArray( m_ti );
|
|
|
|
i = unknown;
|
|
if (rc)
|
|
rc = file.ReadInt( &i );
|
|
switch(i) {
|
|
case unknown:
|
|
m_type = unknown;
|
|
break;
|
|
case outer:
|
|
m_type = outer;
|
|
break;
|
|
case inner:
|
|
m_type = inner;
|
|
break;
|
|
case slit:
|
|
m_type = slit;
|
|
break;
|
|
}
|
|
|
|
if (rc)
|
|
rc = file.ReadInt( &m_fi );
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepFace::Write( ON_BinaryArchive& file ) const
|
|
{
|
|
bool rc = file.WriteInt( m_face_index );
|
|
if ( rc )
|
|
rc = file.WriteArray( m_li );
|
|
if ( rc )
|
|
rc = file.WriteInt( m_si );
|
|
if ( rc )
|
|
rc = file.WriteInt( m_bRev );
|
|
if ( rc )
|
|
rc = file.WriteInt( m_face_material_channel );
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepFace::Read( ON_BinaryArchive& file )
|
|
{
|
|
int i;
|
|
bool rc = file.ReadInt( &m_face_index );
|
|
if ( rc )
|
|
rc = file.ReadArray( m_li );
|
|
if ( rc )
|
|
rc = file.ReadInt( &m_si );
|
|
if ( rc )
|
|
{
|
|
i = m_bRev;
|
|
rc = file.ReadInt( &i );
|
|
if ( rc )
|
|
m_bRev = (i!=0);
|
|
}
|
|
if ( rc )
|
|
{
|
|
rc = file.ReadInt( &m_face_material_channel );
|
|
if ( m_face_material_channel < 0 )
|
|
m_face_material_channel = 0;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepVertexArray::Read( ON_BinaryArchive& file )
|
|
{
|
|
Empty();
|
|
ON__UINT32 tcode = 0;
|
|
ON__INT64 length_TCODE_ANONYMOUS_CHUNK = 0;
|
|
int count = 0;
|
|
int i;
|
|
int major_version = 0;
|
|
int minor_version = 0;
|
|
bool rc = file.BeginRead3dmBigChunk( &tcode, &length_TCODE_ANONYMOUS_CHUNK );
|
|
if (rc) {
|
|
if (tcode != TCODE_ANONYMOUS_CHUNK)
|
|
rc = false;
|
|
if (rc) rc = file.Read3dmChunkVersion(&major_version,&minor_version);
|
|
if (rc) {
|
|
if ( major_version==1 ) {
|
|
if (rc) rc = file.ReadInt(&count);
|
|
SetCapacity(count);
|
|
for ( i = 0; i < count && rc ; i++ ) {
|
|
ON_BrepVertex& vertex = AppendNew();
|
|
rc = vertex.Read(file)?true:false;
|
|
}
|
|
}
|
|
else {
|
|
rc = 0;
|
|
}
|
|
}
|
|
if ( !file.EndRead3dmChunk() )
|
|
rc = false;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepVertexArray::Write( ON_BinaryArchive& file ) const
|
|
{
|
|
int i;
|
|
bool rc = file.BeginWrite3dmChunk( TCODE_ANONYMOUS_CHUNK, 0 );
|
|
if (rc) {
|
|
rc = file.Write3dmChunkVersion(1,0);
|
|
const int count = Count();
|
|
if (rc) rc = file.WriteInt( count );
|
|
for ( i = 0; rc && i < count; i++ ) {
|
|
if (rc) rc = m_a[i].Write(file);
|
|
}
|
|
if ( !file.EndWrite3dmChunk() )
|
|
rc = false;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepEdgeArray::Read( ON_BinaryArchive& file )
|
|
{
|
|
Empty();
|
|
ON__UINT32 tcode = 0;
|
|
ON__INT64 length_TCODE_ANONYMOUS_CHUNK = 0;
|
|
int count = 0;
|
|
int i;
|
|
int major_version = 0;
|
|
int minor_version = 0;
|
|
bool rc = file.BeginRead3dmBigChunk( &tcode, &length_TCODE_ANONYMOUS_CHUNK );
|
|
if (rc) {
|
|
if (tcode != TCODE_ANONYMOUS_CHUNK)
|
|
rc = false;
|
|
if (rc) rc = file.Read3dmChunkVersion(&major_version,&minor_version);
|
|
if (rc) {
|
|
if ( major_version==1 ) {
|
|
if (rc) rc = file.ReadInt(&count);
|
|
SetCapacity(count);
|
|
for ( i = 0; i < count && rc ; i++ ) {
|
|
ON_BrepEdge& edge = AppendNew();
|
|
rc = edge.Read(file) ? true : false;
|
|
}
|
|
}
|
|
else {
|
|
rc = 0;
|
|
}
|
|
}
|
|
if ( !file.EndRead3dmChunk() )
|
|
rc = false;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepEdgeArray::Write( ON_BinaryArchive& file ) const
|
|
{
|
|
int i;
|
|
bool rc = file.BeginWrite3dmChunk( TCODE_ANONYMOUS_CHUNK, 0 );
|
|
if (rc) {
|
|
rc = file.Write3dmChunkVersion(1,0);
|
|
const int count = Count();
|
|
if (rc) rc = file.WriteInt( count );
|
|
for ( i = 0; rc && i < count; i++ ) {
|
|
if (rc) rc = m_a[i].Write(file);
|
|
}
|
|
if ( !file.EndWrite3dmChunk() )
|
|
rc = false;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepTrimArray::Read( ON_BinaryArchive& file )
|
|
{
|
|
Empty();
|
|
ON__UINT32 tcode = 0;
|
|
ON__INT64 length_TCODE_ANONYMOUS_CHUNK = 0;
|
|
int count = 0;
|
|
int i;
|
|
int major_version = 0;
|
|
int minor_version = 0;
|
|
bool rc = file.BeginRead3dmBigChunk( &tcode, &length_TCODE_ANONYMOUS_CHUNK );
|
|
if (rc) {
|
|
if (tcode != TCODE_ANONYMOUS_CHUNK)
|
|
rc = false;
|
|
if (rc) rc = file.Read3dmChunkVersion(&major_version,&minor_version);
|
|
if (rc) {
|
|
if ( major_version==1 ) {
|
|
if (rc) rc = file.ReadInt(&count);
|
|
SetCapacity(count);
|
|
for ( i = 0; i < count && rc ; i++ ) {
|
|
ON_BrepTrim& trim = AppendNew();
|
|
rc = trim.Read(file)?true:false;
|
|
if ( rc )
|
|
{
|
|
if ( trim.m_trim_index != m_count-1 )
|
|
{
|
|
// 28 May 2013 Dale Lear
|
|
// Fix http://mcneel.myjetbrains.com/youtrack/issue/RH-18299
|
|
// Fix bogus index values to prevent crashes.
|
|
ON_ERROR("Invalid value of m_trim_index");
|
|
trim.m_trim_index = m_count-1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
rc = 0;
|
|
}
|
|
}
|
|
if ( !file.EndRead3dmChunk() )
|
|
rc = false;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepTrimArray::Write( ON_BinaryArchive& file ) const
|
|
{
|
|
int i;
|
|
bool rc = file.BeginWrite3dmChunk( TCODE_ANONYMOUS_CHUNK, 0 );
|
|
if (rc) {
|
|
rc = file.Write3dmChunkVersion(1,0);
|
|
const int count = Count();
|
|
if (rc) rc = file.WriteInt( count );
|
|
for ( i = 0; rc && i < count; i++ ) {
|
|
if (rc) rc = m_a[i].Write(file);
|
|
}
|
|
if ( !file.EndWrite3dmChunk() )
|
|
rc = false;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepLoopArray::Read( ON_BinaryArchive& file )
|
|
{
|
|
Empty();
|
|
ON__UINT32 tcode = 0;
|
|
ON__INT64 length_TCODE_ANONYMOUS_CHUNK = 0;
|
|
int count = 0;
|
|
int i;
|
|
int major_version = 0;
|
|
int minor_version = 0;
|
|
bool rc = file.BeginRead3dmBigChunk( &tcode, &length_TCODE_ANONYMOUS_CHUNK );
|
|
if (rc) {
|
|
if (tcode != TCODE_ANONYMOUS_CHUNK)
|
|
rc = false;
|
|
if (rc) rc = file.Read3dmChunkVersion(&major_version,&minor_version);
|
|
if (rc) {
|
|
if ( major_version==1 ) {
|
|
if (rc) rc = file.ReadInt(&count);
|
|
SetCapacity(count);
|
|
for ( i = 0; i < count && rc ; i++ ) {
|
|
ON_BrepLoop& loop = AppendNew();
|
|
rc = loop.Read(file) ? true : false;
|
|
}
|
|
}
|
|
else {
|
|
rc = 0;
|
|
}
|
|
}
|
|
if ( !file.EndRead3dmChunk() )
|
|
rc = false;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepLoopArray::Write( ON_BinaryArchive& file ) const
|
|
{
|
|
int i;
|
|
bool rc = file.BeginWrite3dmChunk( TCODE_ANONYMOUS_CHUNK, 0 );
|
|
if (rc) {
|
|
rc = file.Write3dmChunkVersion(1,0);
|
|
const int count = Count();
|
|
if (rc) rc = file.WriteInt( count );
|
|
for ( i = 0; rc && i < count; i++ ) {
|
|
if (rc) rc = m_a[i].Write(file);
|
|
}
|
|
if ( !file.EndWrite3dmChunk() )
|
|
rc = false;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepFaceArray::Read( ON_BinaryArchive& file )
|
|
{
|
|
Empty();
|
|
ON__UINT32 tcode = 0;
|
|
ON__INT64 length_TCODE_ANONYMOUS_CHUNK = 0;
|
|
int count = 0;
|
|
int i;
|
|
int major_version = 0;
|
|
int minor_version = 0;
|
|
bool rc = file.BeginRead3dmBigChunk( &tcode, &length_TCODE_ANONYMOUS_CHUNK );
|
|
if (rc) {
|
|
if (tcode != TCODE_ANONYMOUS_CHUNK)
|
|
rc = false;
|
|
if (rc) rc = file.Read3dmChunkVersion(&major_version,&minor_version);
|
|
if (rc) {
|
|
if ( major_version==1 )
|
|
{
|
|
if (rc) rc = file.ReadInt(&count);
|
|
SetCapacity(count);
|
|
for ( i = 0; i < count && rc ; i++ )
|
|
{
|
|
ON_BrepFace& face = AppendNew();
|
|
rc = face.Read(file)?true:false;
|
|
}
|
|
|
|
if ( minor_version >= 1 )
|
|
{
|
|
// chunk version 1.1 and later has face uuids
|
|
for ( i = 0; i < count && rc; i++ )
|
|
{
|
|
rc = file.ReadUuid( m_a[i].m_face_uuid );
|
|
}
|
|
|
|
if (rc && minor_version >= 2)
|
|
{
|
|
// chunk version 1.2 and later has per face colors
|
|
bool bHavePerFaceColors = false;
|
|
rc = file.ReadBool(&bHavePerFaceColors);
|
|
if (rc && bHavePerFaceColors)
|
|
{
|
|
for (i = 0; rc && i < count; i++)
|
|
{
|
|
ON_Color per_face_color = ON_Color::UnsetColor;
|
|
rc = file.ReadColor(per_face_color);
|
|
if (rc && ON_Color::UnsetColor != per_face_color)
|
|
m_a[i].SetPerFaceColor(per_face_color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rc = 0;
|
|
}
|
|
}
|
|
if ( !file.EndRead3dmChunk() )
|
|
rc = false;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool ON_BrepFaceArray::Write( ON_BinaryArchive& file ) const
|
|
{
|
|
int i;
|
|
bool rc = file.BeginWrite3dmChunk( TCODE_ANONYMOUS_CHUNK, 0 );
|
|
if (rc)
|
|
{
|
|
// 1.1 added m_face_uuid
|
|
// 1.2 added m_per_face_color
|
|
const int minor_version = file.Archive3dmVersion() >= 70 ? 2 : 1;
|
|
rc = file.Write3dmChunkVersion(1, minor_version);
|
|
|
|
// chunk version 1.0 and later
|
|
const int count = Count();
|
|
if (rc) rc = file.WriteInt( count );
|
|
for ( i = 0; rc && i < count; i++ )
|
|
{
|
|
if (rc) rc = m_a[i].Write(file);
|
|
}
|
|
|
|
// chunk version 1.1 and later
|
|
for ( i = 0; rc && i < count; i++ )
|
|
{
|
|
rc = file.WriteUuid( m_a[i].m_face_uuid );
|
|
}
|
|
|
|
if (rc && minor_version >= 2)
|
|
{
|
|
// 1.2 added optional per face colors
|
|
bool bHavePerFaceColors = false;
|
|
for (i = 0; rc && i < count; i++)
|
|
{
|
|
if (ON_Color::UnsetColor != m_a[i].PerFaceColor())
|
|
{
|
|
bHavePerFaceColors = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
rc = file.WriteBool(bHavePerFaceColors);
|
|
if (rc && bHavePerFaceColors)
|
|
{
|
|
for (i = 0; rc && i < count; i++)
|
|
rc = file.WriteColor(m_a[i].PerFaceColor());
|
|
}
|
|
}
|
|
|
|
if ( !file.EndWrite3dmChunk() )
|
|
rc = false;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
bool ON_Brep::Write( ON_BinaryArchive& file ) const
|
|
{
|
|
const ON_Brep* brep = this;
|
|
ON_Brep* v2brep = 0;
|
|
|
|
|
|
//bool rc = file.Write3dmChunkVersion(3,0); // serialization version
|
|
//bool rc = file.Write3dmChunkVersion(3,1); // added meshes
|
|
|
|
int minor_version
|
|
= (file.Archive3dmVersion() <= 50)
|
|
? 2
|
|
: 3 // August 9, 2016 m_region_topology added to V6 files.
|
|
;
|
|
|
|
bool rc = file.Write3dmChunkVersion(3,minor_version); // added m_is_solid
|
|
|
|
// 2d curves
|
|
if (rc) rc = brep->m_C2.Write(file);
|
|
|
|
// 3d curves
|
|
if (rc) rc = brep->m_C3.Write(file);
|
|
|
|
// untrimmed surfaces
|
|
if (rc) rc = brep->m_S.Write(file);
|
|
|
|
// vertices
|
|
if (rc) rc = brep->m_V.Write(file);
|
|
|
|
// edges
|
|
if (rc) rc = brep->m_E.Write(file);
|
|
|
|
// trims
|
|
if (rc) rc = brep->m_T.Write(file);
|
|
|
|
// loops
|
|
if (rc) rc = brep->m_L.Write(file);
|
|
|
|
// faces
|
|
if (rc) rc = brep->m_F.Write(file);
|
|
|
|
// bounding box
|
|
if (rc) rc = file.WritePoint( brep->m_bbox.m_min );
|
|
if (rc) rc = file.WritePoint( brep->m_bbox.m_max );
|
|
|
|
// end of chunk version 3.0
|
|
|
|
if (rc)
|
|
{
|
|
// added for chunk version 3.1
|
|
const int face_count = brep->m_F.Count();
|
|
int fi;
|
|
unsigned char b;
|
|
|
|
// write render meshes
|
|
rc = file.BeginWrite3dmChunk( TCODE_ANONYMOUS_CHUNK, 0 );
|
|
if ( rc )
|
|
{
|
|
for ( fi = 0; rc && fi < face_count; fi++ ) {
|
|
const auto mesh = file.Save3dmRenderMesh(ON::object_type::brep_object) ? brep->m_F[fi].SharedMesh(ON::render_mesh) : nullptr;
|
|
b = mesh ? 1 : 0;
|
|
rc = file.WriteChar(b);
|
|
if (rc && mesh) {
|
|
rc = file.WriteObject(*mesh);
|
|
}
|
|
}
|
|
if ( !file.EndWrite3dmChunk() )
|
|
{
|
|
rc = false;
|
|
}
|
|
}
|
|
|
|
// write analysis meshes
|
|
if (rc) rc = file.BeginWrite3dmChunk( TCODE_ANONYMOUS_CHUNK, 0 );
|
|
if ( rc )
|
|
{
|
|
for ( fi = 0; rc && fi < face_count; fi++ ) {
|
|
const auto mesh = file.Save3dmAnalysisMesh(ON::object_type::brep_object) ? brep->m_F[fi].SharedMesh(ON::analysis_mesh) : nullptr;
|
|
b = mesh ? 1 : 0;
|
|
rc = file.WriteChar(b);
|
|
if (rc && mesh) {
|
|
rc = file.WriteObject(*mesh);
|
|
}
|
|
}
|
|
if ( !file.EndWrite3dmChunk() )
|
|
rc = false;
|
|
}
|
|
|
|
}
|
|
// end of chunk version 3.1
|
|
|
|
if (rc)
|
|
{
|
|
// use value of "this" m_is_solid to avoid expensive
|
|
// calculation on the v2brep
|
|
if ( !file.WriteInt( m_is_solid ) )
|
|
rc = false;
|
|
}
|
|
|
|
// end of chunk version 3.2
|
|
|
|
if (rc)
|
|
{
|
|
const bool bWriteRegionTopology
|
|
= (nullptr != m_region_topology)
|
|
&& (m_F.UnsignedCount() > 0)
|
|
&& (m_region_topology->m_FS.UnsignedCount() == 2 * m_F.UnsignedCount());
|
|
|
|
if (minor_version <= 2)
|
|
{
|
|
if (bWriteRegionTopology && minor_version == 2 && 50 == file.Archive3dmVersion())
|
|
Internal_AttachV5RegionTopologyAsUserData(file);
|
|
}
|
|
else if (minor_version >= 3)
|
|
{
|
|
// begin chunk verson 3.3
|
|
|
|
// region topology chunk added
|
|
if (!file.BeginWrite3dmAnonymousChunk(1))
|
|
return false;
|
|
|
|
rc = false;
|
|
for (;;)
|
|
{
|
|
if (!file.WriteBool(bWriteRegionTopology))
|
|
break;
|
|
if (bWriteRegionTopology)
|
|
{
|
|
if (!m_region_topology->Write(file))
|
|
break;
|
|
}
|
|
rc = true;
|
|
break;
|
|
}
|
|
if (!file.EndWrite3dmChunk())
|
|
rc = false;
|
|
// end chunk version 3.3
|
|
}
|
|
}
|
|
|
|
if ( 0 != v2brep )
|
|
delete v2brep;
|
|
|
|
return rc;
|
|
}
|
|
|
|
static
|
|
void ReadFillInMissingBoxes( ON_Brep& brep )
|
|
{
|
|
// older files did not save bounding box information
|
|
int ti, li, lti, trim_count, loop_count;
|
|
const ON_Curve* c2;
|
|
trim_count = brep.m_T.Count();
|
|
loop_count = brep.m_L.Count();
|
|
for ( ti = 0; ti < trim_count; ti++ )
|
|
{
|
|
ON_BrepTrim& trim = brep.m_T[ti];
|
|
if ( !trim.m_pbox.IsValid() )
|
|
{
|
|
c2 = trim.TrimCurveOf();
|
|
if ( c2 )
|
|
trim.m_pbox = c2->BoundingBox();
|
|
}
|
|
}
|
|
|
|
for ( li = 0; li < loop_count; li++ )
|
|
{
|
|
ON_BrepLoop& loop = brep.m_L[li];
|
|
if ( !loop.m_pbox.IsValid() )
|
|
{
|
|
for ( lti = 0; lti < loop.m_ti.Count(); lti++ )
|
|
{
|
|
ti = loop.m_ti[lti];
|
|
if ( ti >= 0 && ti < trim_count )
|
|
loop.m_pbox.Union( brep.m_T[ti].m_pbox );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static const ON_BoundingBox Internal_BestBoundingBox(
|
|
const ON_BoundingBox archive_bbox,
|
|
const ON_BoundingBox new_bbox
|
|
)
|
|
{
|
|
if (false == new_bbox.IsNotEmpty())
|
|
return archive_bbox; // don't have a new bbox
|
|
|
|
if (false == archive_bbox.IsValid())
|
|
return new_bbox;
|
|
|
|
if (archive_bbox.Includes(new_bbox, false))
|
|
return new_bbox;
|
|
|
|
// The best code currently available calculated new_box.
|
|
// I should be good enough. If it is different
|
|
// from archive then you need to understand WHY it is different
|
|
// and fix the problem at the source - not mask it at read time.
|
|
return new_bbox; // <- Good place to debug bbox reading bugs
|
|
|
|
}
|
|
|
|
bool ON_Brep::Read( ON_BinaryArchive& file )
|
|
{
|
|
int i;
|
|
int C2_count = 0;
|
|
int C3_count = 0;
|
|
int S_count = 0;
|
|
int major_version = 0;
|
|
int minor_version = 0;
|
|
bool rc = file.Read3dmChunkVersion( &major_version, &minor_version );
|
|
if ( rc && major_version == 2 )
|
|
{
|
|
rc = ReadOld200(file,minor_version); // legacy trimmed face
|
|
}
|
|
else if ( rc && major_version == 3 )
|
|
{
|
|
// 2d curves
|
|
if (rc)
|
|
rc = m_C2.Read(file);
|
|
C2_count = m_C2.Count();
|
|
|
|
// 3d curves
|
|
if (rc)
|
|
rc = m_C3.Read(file);
|
|
C3_count = m_C3.Count();
|
|
|
|
// untrimmed surfaces
|
|
if (rc)
|
|
rc = m_S.Read(file);
|
|
S_count = m_S.Count();
|
|
|
|
// vertices
|
|
if (rc)
|
|
rc = m_V.Read(file);
|
|
|
|
// edges
|
|
if (rc)
|
|
{
|
|
rc = m_E.Read(file);
|
|
if (rc) {
|
|
for ( i = 0; i < m_E.Count(); i++ ) {
|
|
ON_BrepEdge& e = m_E[i];
|
|
e.m_brep = this;
|
|
if ( e.m_c3i >= 0 && e.m_c3i < C3_count )
|
|
{
|
|
bool bProxyCurveIsReversed = e.ProxyCurveIsReversed();
|
|
ON_Interval pdom = e.ProxyCurveDomain();
|
|
ON_Interval edom = e.Domain();
|
|
e.SetProxyCurve( m_C3[e.m_c3i], pdom );
|
|
if ( bProxyCurveIsReversed )
|
|
e.ON_CurveProxy::Reverse();
|
|
e.SetDomain(edom);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// trims
|
|
if (rc)
|
|
{
|
|
rc = m_T.Read(file);
|
|
if (rc) {
|
|
for ( i = 0; i < m_T.Count(); i++ ) {
|
|
ON_BrepTrim& trim = m_T[i];
|
|
trim.m_brep = this;
|
|
if ( trim.m_c2i >= 0 && trim.m_c2i < C2_count )
|
|
{
|
|
bool bProxyCurveIsReversed = trim.ProxyCurveIsReversed();
|
|
ON_Interval pdom = trim.ProxyCurveDomain();
|
|
ON_Interval tdom = trim.Domain();
|
|
trim.SetProxyCurve( m_C2[trim.m_c2i], pdom );
|
|
if ( bProxyCurveIsReversed )
|
|
trim.ON_CurveProxy::Reverse();
|
|
trim.SetDomain(tdom);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// loops
|
|
if (rc)
|
|
{
|
|
rc = m_L.Read(file);
|
|
if ( rc )
|
|
{
|
|
for ( i = 0; i < m_L.Count(); i++ )
|
|
{
|
|
m_L[i].m_brep = this;
|
|
}
|
|
}
|
|
}
|
|
|
|
// faces
|
|
if (rc)
|
|
{
|
|
rc = m_F.Read(file);
|
|
if (rc) {
|
|
for ( i = 0; i < m_F.Count(); i++ ) {
|
|
ON_BrepFace& f = m_F[i];
|
|
f.m_brep = this;
|
|
if ( f.m_si >= 0 && f.m_si < S_count )
|
|
f.SetProxySurface(m_S[f.m_si]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// bounding box
|
|
if (rc)
|
|
rc = file.ReadPoint( m_bbox.m_min );
|
|
if (rc)
|
|
rc = file.ReadPoint( m_bbox.m_max );
|
|
|
|
// fill in missing information
|
|
ReadFillInMissingBoxes(*this);
|
|
|
|
// end of chunk version 3.0
|
|
|
|
if (rc && minor_version >= 1 )
|
|
{
|
|
// added for chunk version 3.1
|
|
|
|
ON_Object* obj;
|
|
ON__UINT32 tcode = 0;
|
|
ON__INT64 length_TCODE_ANONYMOUS_CHUNK = 0;
|
|
int fi;
|
|
unsigned char b;
|
|
|
|
const int face_count = m_F.Count();
|
|
|
|
// read render meshes
|
|
tcode = 0;
|
|
length_TCODE_ANONYMOUS_CHUNK = 0;
|
|
rc = file.BeginRead3dmBigChunk( &tcode, &length_TCODE_ANONYMOUS_CHUNK );
|
|
if ( rc )
|
|
{
|
|
if ( tcode != TCODE_ANONYMOUS_CHUNK )
|
|
rc = false;
|
|
else
|
|
{
|
|
for ( fi = 0; rc && fi < face_count; fi++ )
|
|
{
|
|
rc = file.ReadChar(&b);
|
|
if (rc && b)
|
|
{
|
|
obj = 0;
|
|
rc = file.ReadObject(&obj);
|
|
if ( 0 != obj )
|
|
{
|
|
auto pMesh = ON_Mesh::Cast(obj);
|
|
if (nullptr == pMesh)
|
|
{
|
|
delete obj;
|
|
}
|
|
else
|
|
{
|
|
m_F[fi].SetMesh(ON::render_mesh, pMesh);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( !file.EndRead3dmChunk() )
|
|
rc = false;
|
|
}
|
|
|
|
if (rc)
|
|
{
|
|
// read analysis meshes
|
|
tcode = 0;
|
|
length_TCODE_ANONYMOUS_CHUNK = 0;
|
|
rc = file.BeginRead3dmBigChunk( &tcode, &length_TCODE_ANONYMOUS_CHUNK );
|
|
if ( rc )
|
|
{
|
|
if ( tcode != TCODE_ANONYMOUS_CHUNK )
|
|
rc = false;
|
|
else
|
|
{
|
|
for ( fi = 0; rc && fi < face_count; fi++ )
|
|
{
|
|
rc = file.ReadChar(&b);
|
|
if (rc && b)
|
|
{
|
|
rc = file.ReadObject(&obj);
|
|
|
|
if (nullptr != obj)
|
|
{
|
|
auto pMesh = ON_Mesh::Cast(obj);
|
|
if (nullptr == pMesh)
|
|
{
|
|
delete obj;
|
|
}
|
|
else
|
|
{
|
|
m_F[fi].SetMesh(ON::analysis_mesh, pMesh);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( !file.EndRead3dmChunk() )
|
|
rc = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( rc && minor_version >= 2 )
|
|
{
|
|
rc = file.ReadInt( &m_is_solid );
|
|
if ( m_is_solid < 0 || m_is_solid >= 3 )
|
|
m_is_solid = 0;
|
|
if (rc && minor_version >= 3)
|
|
{
|
|
// begin chunk verson 3.3
|
|
|
|
// region topology chunk added
|
|
int region_topology_chunk_version = 0;
|
|
if (!file.BeginRead3dmAnonymousChunk(®ion_topology_chunk_version))
|
|
rc = false;
|
|
else
|
|
{
|
|
bool rc1 = false;
|
|
for (;;)
|
|
{
|
|
if (region_topology_chunk_version < 1)
|
|
break;
|
|
|
|
bool bReadRegionTopology = false;
|
|
if (!file.ReadBool(&bReadRegionTopology))
|
|
break;
|
|
|
|
if (bReadRegionTopology)
|
|
{
|
|
m_region_topology = new ON_BrepRegionTopology();
|
|
if (!m_region_topology->Read(file))
|
|
{
|
|
delete m_region_topology;
|
|
m_region_topology = nullptr;
|
|
break;
|
|
}
|
|
}
|
|
rc1 = true;
|
|
break;
|
|
}
|
|
if (!file.EndRead3dmChunk())
|
|
rc1 = false;
|
|
if (false == rc1)
|
|
rc = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( file.ArchiveOpenNURBSVersion() < 20021002 )
|
|
{
|
|
m_is_solid = 0;
|
|
}
|
|
|
|
// GBA 3-Sept-20 RH-60112
|
|
// In V6 and earlier bounding boxes of faces were bounding box of underlying surface.
|
|
// This can result in enourmous boxes which mess up make2d
|
|
// In V7 bounding boxes use the trim pbox resulting in resonable boxes.
|
|
////if (file.Archive3dmVersion() < 70 || file.ArchiveOpenNURBSVersion() < 2382395020)
|
|
////{
|
|
//// if (!m_bbox.IsEmpty())
|
|
//// {
|
|
//// ON_BoundingBox orig_box = m_bbox;
|
|
//// ClearBoundingBox();
|
|
//// BoundingBox(); // compute bounding box
|
|
//// m_bbox.Intersection(orig_box);
|
|
//// }
|
|
////}
|
|
|
|
// Dale Lear https://mcneel.myjetbrains.com/youtrack/issue/RH-64277
|
|
// The test used to fix RH-60112 was not adequate and now the set of
|
|
// active v7 3dm files has lots of cases with breps that have
|
|
// oversized bounding boxes by the new standard avter Greg's RH-60112 changes.
|
|
// We have already started writing V8 files and those versions of V8
|
|
// have been used by some of our Discourse early adopters.
|
|
// At this point, I'm going to assume a bounding box read from a V7 or V8 file
|
|
// can be too big. By the time V9 rolls around, the boxes should be cleaned up.
|
|
if (file.Archive3dmVersion() < 90 && m_bbox.IsNotEmpty() )
|
|
{
|
|
const ON_BoundingBox archive_brep_bbox = m_bbox;
|
|
ON_BoundingBox new_brep_bbox = ON_BoundingBox::EmptyBoundingBox;
|
|
const unsigned int face_count = m_F.UnsignedCount();
|
|
for (unsigned fi = 0; fi < face_count; ++fi)
|
|
{
|
|
ON_BrepFace& f = this->m_F[fi];
|
|
const ON_BoundingBox archive_face_bbox = f.m_bbox;
|
|
ON_BoundingBox new_face_bbox = f.InternalFaceBoundingBox(false, false);
|
|
f.m_bbox = Internal_BestBoundingBox(archive_face_bbox, new_face_bbox);
|
|
new_brep_bbox.Union(f.m_bbox);
|
|
}
|
|
m_bbox = Internal_BestBoundingBox(archive_brep_bbox, new_brep_bbox);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
bool ON_Brep::ReadOld200( ON_BinaryArchive& file, int minor_version )
|
|
{
|
|
bool rc = true;
|
|
|
|
// read legacy trimmed surface collection from Rhino 2.0
|
|
|
|
int face_count = 0;
|
|
int edge_count = 0;
|
|
int loop_count = 0;
|
|
int trim_count = 0;
|
|
int outer_flag = 0;
|
|
|
|
ON_BoundingBox bnd_2d_bbox;
|
|
int i, fi, fbi, fbcnt, bti, btcnt, twin_index;
|
|
int ftype_flag, btype_flag, gcon_flag, mono_flag;
|
|
char b;
|
|
|
|
if (rc) rc = file.ReadInt( &face_count );
|
|
if (rc) rc = file.ReadInt( &edge_count );
|
|
if (rc) rc = file.ReadInt( &loop_count );
|
|
if (rc) rc = file.ReadInt( &trim_count );
|
|
|
|
if ( face_count < 1 || edge_count < 1 || loop_count < 1 || trim_count < 1 )
|
|
rc = false;
|
|
|
|
if (rc) rc = file.ReadInt( &outer_flag );
|
|
if (rc) rc = file.ReadPoint( m_bbox.m_min );
|
|
if (rc) rc = file.ReadPoint( m_bbox.m_max );
|
|
|
|
// 2d curves
|
|
m_C2.Reserve(trim_count);
|
|
for ( i = 0; rc && i < trim_count; i++ ) {
|
|
ON_PolyCurve* curve = new ON_PolyCurve();
|
|
rc = curve->Read( file )?true:false;
|
|
if ( curve->Count() == 1 ) {
|
|
m_C2.Append( curve->HarvestSegment(0) );
|
|
delete curve;
|
|
}
|
|
else
|
|
m_C2.Append( curve );
|
|
}
|
|
const int c2_count = m_C2.Count();
|
|
|
|
// 3d curves
|
|
m_C3.Reserve(edge_count);
|
|
for ( i = 0; rc && i < edge_count; i++ ) {
|
|
ON_PolyCurve* curve = new ON_PolyCurve();
|
|
rc = curve->Read( file )?true:false;
|
|
if ( curve->Count() == 1 ) {
|
|
m_C3.Append( curve->HarvestSegment(0) );
|
|
delete curve;
|
|
}
|
|
else
|
|
m_C3.Append( curve );
|
|
}
|
|
const int c3_count = m_C3.Count();
|
|
|
|
// make a new edge for each 3d curve
|
|
m_E.Reserve(c3_count);
|
|
for ( i = 0; i < c3_count && rc; i++ )
|
|
{
|
|
NewEdge(i);
|
|
}
|
|
|
|
// 3d surfaces
|
|
m_S.Reserve(face_count);
|
|
for ( i = 0; rc && i < face_count; i++ ) {
|
|
ON_NurbsSurface* surface = new ON_NurbsSurface();
|
|
rc = surface->Read( file )?true:false;
|
|
m_S.Append( surface );
|
|
}
|
|
|
|
ON_SimpleArray<int> te_index(trim_count);
|
|
ON_SimpleArray<int> te_twin_index(trim_count);
|
|
|
|
m_F.Reserve(face_count);
|
|
m_L.Reserve(loop_count);
|
|
m_T.Reserve(trim_count);
|
|
|
|
for ( fi = 0; rc && fi < face_count; fi++ )
|
|
{
|
|
ftype_flag = 0;
|
|
fbcnt = 0;
|
|
ON_BrepFace& f = NewFace(fi);
|
|
if (rc) rc = file.ReadInt( &i ); // legacy face index
|
|
if (rc) rc = file.ReadInt( &i ); // OBSOLETE f.m_material_index
|
|
int k = f.m_bRev;
|
|
if (rc) rc = file.ReadInt( &k );
|
|
if (rc) f.m_bRev = (k!=0);
|
|
if (rc) rc = file.ReadInt( &ftype_flag );
|
|
if (rc) rc = file.ReadPoint( f.m_bbox.m_min );
|
|
if (rc) rc = file.ReadPoint( f.m_bbox.m_max );
|
|
if (rc) rc = file.ReadInt( &fbcnt);
|
|
if (fbcnt < 1 )
|
|
rc = false;
|
|
for ( fbi = 0; rc && fbi < fbcnt; fbi++ ) {
|
|
btype_flag = 0;
|
|
ON_BrepLoop::TYPE looptype = ON_BrepLoop::unknown;
|
|
if (rc) rc = file.ReadInt( &i ); // legacy loop index
|
|
if (rc) rc = file.ReadInt( &btype_flag );
|
|
switch (btype_flag)
|
|
{
|
|
case 0:
|
|
looptype = ON_BrepLoop::outer;
|
|
break;
|
|
case 1:
|
|
looptype = ON_BrepLoop::inner;
|
|
break;
|
|
case -1:
|
|
looptype = ON_BrepLoop::slit;
|
|
break;
|
|
default:
|
|
looptype = ON_BrepLoop::unknown;
|
|
break;
|
|
}
|
|
if (rc) rc = file.ReadDouble( 2, &bnd_2d_bbox.m_min.x );
|
|
if (rc) rc = file.ReadDouble( 2, &bnd_2d_bbox.m_max.x );
|
|
btcnt = 0;
|
|
if (rc) rc = file.ReadInt( &btcnt );
|
|
if (btcnt < 1 )
|
|
rc = false;
|
|
ON_BrepLoop& bnd = NewLoop(looptype,f);
|
|
for ( bti = 0; rc && bti < btcnt; bti++ ) {
|
|
ON_BrepTrim& trim = NewTrim(false,bnd,m_T.Count());
|
|
te_index.Append(trim.m_trim_index);
|
|
if (rc) rc = file.ReadInt( &i ); // legacy trim index
|
|
if ( trim.m_trim_index != i )
|
|
{
|
|
ON_ERROR("ON_Brep::ReadOld200 - trim.m_trim_index out of synch.");
|
|
//rc = false;
|
|
//break;
|
|
}
|
|
if (rc) rc = file.ReadInt( &twin_index );
|
|
te_twin_index.Append(twin_index);
|
|
b = 0;
|
|
if (rc) rc = file.ReadChar( &b ); // true if legacy trim managed 3d edge
|
|
if (rc) rc = file.ReadInt( &trim.m_ei );
|
|
if ( trim.m_ei < 0 || trim.m_ei >= c3_count )
|
|
{
|
|
trim.m_ei = -1;
|
|
if (b)
|
|
{
|
|
ON_ERROR("ON_Brep::ReadOld201 - trim.m_ei out of range.");
|
|
rc = false;
|
|
break;
|
|
}
|
|
}
|
|
if ( trim.m_trim_index >= 0 && trim.m_trim_index < c2_count )
|
|
trim.m_c2i = trim.m_trim_index;
|
|
else {
|
|
ON_ERROR("ON_Brep::ReadOld200 - trim.m_trim_index out of range.");
|
|
rc = false;
|
|
trim.m_c2i = -1;
|
|
break;
|
|
}
|
|
int bRev3d_as_int = trim.m_bRev3d;
|
|
if (rc) rc = file.ReadInt(&bRev3d_as_int);
|
|
if (rc) trim.m_bRev3d = (bRev3d_as_int!=0);
|
|
if (rc) rc = file.ReadInt(&gcon_flag);
|
|
if (rc) rc = file.ReadInt(&mono_flag);
|
|
if (rc) rc = file.ReadDouble(&trim.m__legacy_3d_tol);
|
|
if (rc) rc = file.ReadDouble(&trim.m__legacy_2d_tol);
|
|
}
|
|
}
|
|
}
|
|
|
|
// finish hooking trims to edges
|
|
if (rc) {
|
|
int trim_index;
|
|
for ( i = 0; i < trim_count; i++ ) {
|
|
trim_index = te_index[i];
|
|
if ( trim_index >= 0 && trim_index < m_T.Count() )
|
|
continue;
|
|
twin_index = te_twin_index[i];
|
|
if ( twin_index >= 0 && twin_index < m_T.Count() )
|
|
continue;
|
|
ON_BrepTrim& trim1 = m_T[trim_index];
|
|
ON_BrepTrim& trim2 = m_T[twin_index];
|
|
if ( trim1.m_ei >= 0 && trim1.m_ei < c2_count && trim2.m_ei < 0 )
|
|
trim2.m_ei = trim1.m_ei;
|
|
else if ( trim2.m_ei >= 0 && trim2.m_ei < c2_count && trim1.m_ei < 0 )
|
|
trim1.m_ei = trim2.m_ei;
|
|
}
|
|
for ( i = 0; i < m_T.Count(); i++ ) {
|
|
ON_BrepTrim& trim = m_T[i];
|
|
ON_Curve* tcurve = m_C2[trim.m_c2i];
|
|
trim.SetProxyCurve( tcurve );
|
|
if ( trim.m_ei >= 0 && trim.m_ei < c3_count )
|
|
m_E[trim.m_ei].m_ti.Append(trim.m_trim_index);
|
|
}
|
|
|
|
|
|
// finish setting flags
|
|
SetTrimIsoFlags();
|
|
SetTrimTypeFlags();
|
|
|
|
// create 3d vertex information
|
|
SetVertices();
|
|
|
|
// set tols from values in file
|
|
SetTolsFromLegacyValues();
|
|
|
|
}
|
|
else {
|
|
Destroy();
|
|
}
|
|
|
|
if (rc) {
|
|
// 3d render mesh geometry
|
|
ON_Object* obj;
|
|
for ( i = 0; rc && i < face_count; i++ ) {
|
|
ON_BrepFace& f = m_F[i];
|
|
file.ReadChar(&b);
|
|
if (b) {
|
|
obj = 0;
|
|
rc = (file.ReadObject(&obj)==1)?true:false;
|
|
|
|
if (nullptr != obj)
|
|
{
|
|
auto pMesh = ON_Mesh::Cast(obj);
|
|
if (pMesh)
|
|
{
|
|
f.SetMesh(ON::render_mesh, pMesh);
|
|
}
|
|
else
|
|
{
|
|
delete pMesh;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !rc ) {
|
|
// delete render mesh geometry
|
|
for ( i = 0; i < face_count; i++ )
|
|
{
|
|
ON_BrepFace& f = m_F[i];
|
|
f.DestroyMesh(ON::render_mesh);
|
|
}
|
|
}
|
|
|
|
if (rc && minor_version >= 1) {
|
|
// 3d analysis mesh geometry
|
|
for ( i = 0; rc && i < face_count; i++ ) {
|
|
ON_BrepFace& f = m_F[i];
|
|
file.ReadChar(&b);
|
|
if (b)
|
|
{
|
|
obj = 0;
|
|
rc = file.ReadObject(&obj)?true:false;
|
|
|
|
if (nullptr != obj)
|
|
{
|
|
auto pMesh = ON_Mesh::Cast(obj);
|
|
if (pMesh)
|
|
{
|
|
f.SetMesh(ON::analysis_mesh, pMesh);
|
|
}
|
|
else
|
|
{
|
|
delete pMesh;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( !rc ) {
|
|
// delete analysis mesh geometry
|
|
for ( i = 0; i < face_count; i++ ) {
|
|
ON_BrepFace& f = m_F[i];
|
|
f.DestroyMesh(ON::analysis_mesh);
|
|
}
|
|
}
|
|
}
|
|
|
|
// fill in missing information
|
|
ReadFillInMissingBoxes(*this);
|
|
|
|
if (!rc ) {
|
|
ON_ERROR("ON_Brep::ReadOld201() - trouble reading render/analysis meshes");
|
|
rc = true;
|
|
}
|
|
}
|
|
|
|
// 22 April 2003:
|
|
// Use outer_flag to set m_is_solid for closed solids
|
|
// with outward pointing normals.
|
|
if ( 1 == outer_flag && IsSolid() )
|
|
m_is_solid = 1;
|
|
|
|
return rc;
|
|
}
|
|
|
|
bool ON_Brep::ReadOld100( ON_BinaryArchive& file )
|
|
{
|
|
// b-rep was written by old Rhino I/O tookit
|
|
int sz, i;
|
|
|
|
// 2d curve geometry
|
|
file.ReadInt( &sz );
|
|
if ( sz < 1 ) {
|
|
return false;
|
|
}
|
|
m_C2.Reserve(sz);
|
|
for ( i = 0; i < sz; i++ ) {
|
|
m_C2.Append( Read100_BrepCurve( file ) );
|
|
}
|
|
|
|
// 3d curve geomery
|
|
file.ReadInt( &sz );
|
|
if ( sz < 1 ) {
|
|
return false;
|
|
}
|
|
m_C3.Reserve(sz);
|
|
for ( i = 0; i < sz; i++ ) {
|
|
m_C3.Append( Read100_BrepCurve( file ) );
|
|
}
|
|
|
|
// surface geometry
|
|
file.ReadInt( &sz );
|
|
if ( sz < 1 ) {
|
|
return false;
|
|
}
|
|
m_S.Reserve(sz);
|
|
for ( i = 0; i < sz; i++ ) {
|
|
m_S.Append( Read100_BrepSurface( file ) );
|
|
}
|
|
/*
|
|
CRhinoChunk* pChunk;
|
|
CRhinoNurbsSurface* pSurface;
|
|
const int typecode, length;
|
|
for ( i = 0; i < sz; i++ ) {
|
|
file.ReadInt( &typecode );
|
|
if ( typecode == TCODE_RHINO_OBJECT_NURBS_SURFACE && length > 0 ) {
|
|
pSurface = (CRhinoNurbsSurface*)pChunk;
|
|
}
|
|
m_S.Append( pSurface );
|
|
}
|
|
*/
|
|
|
|
// read topology
|
|
|
|
// vertices
|
|
file.ReadInt( &sz );
|
|
m_V.Reserve(sz);
|
|
for ( i = 0; i < sz; i++ ) {
|
|
m_V.AppendNew();
|
|
m_V[i].Read(file);
|
|
}
|
|
|
|
// edges
|
|
file.ReadInt( &sz );
|
|
m_E.Reserve(sz);
|
|
for ( i = 0; i < sz; i++ ) {
|
|
m_E.AppendNew();
|
|
m_E[i].Read(file);
|
|
}
|
|
|
|
// trims
|
|
file.ReadInt( &sz );
|
|
m_T.Reserve(sz);
|
|
for ( i = 0; i < sz; i++ ) {
|
|
m_T.AppendNew();
|
|
m_T[i].Read(file);
|
|
}
|
|
|
|
// loops
|
|
file.ReadInt( &sz );
|
|
m_L.Reserve(sz);
|
|
for ( i = 0; i < sz; i++ ) {
|
|
m_L.AppendNew();
|
|
m_L[i].Read(file);
|
|
}
|
|
|
|
// faces
|
|
file.ReadInt( &sz );
|
|
m_F.Reserve(sz);
|
|
for ( i = 0; i < sz; i++ ) {
|
|
m_F.AppendNew();
|
|
m_F[i].Read(file);
|
|
}
|
|
|
|
// bounding box
|
|
file.ReadPoint( m_bbox.m_min );
|
|
file.ReadPoint( m_bbox.m_max );
|
|
|
|
// fill in missing information
|
|
ReadFillInMissingBoxes(*this);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ON_Brep::ReadOld101( ON_BinaryArchive& file )
|
|
{
|
|
ON_Object* pO = nullptr;
|
|
ON_Curve* pC = nullptr;
|
|
ON_Surface* pS = nullptr;
|
|
int i, count;
|
|
|
|
// 2d curves
|
|
file.ReadInt( &count );
|
|
m_C2.Reserve(count);
|
|
for ( i = 0; i < count; i++ )
|
|
{
|
|
pO = nullptr;
|
|
file.ReadObject( &pO );
|
|
pC = ON_Curve::Cast(pO);
|
|
if ( !pC )
|
|
delete pO; // ERROR!
|
|
m_C2.Append( pC );
|
|
pC = nullptr;
|
|
pO = nullptr;
|
|
}
|
|
|
|
// 3d curves
|
|
file.ReadInt( &count );
|
|
m_C3.Reserve(count);
|
|
for ( i = 0; i < count; i++ )
|
|
{
|
|
pO = nullptr;
|
|
file.ReadObject( &pO );
|
|
pC = ON_Curve::Cast(pO);
|
|
if ( !pC )
|
|
delete pO; // ERROR!
|
|
m_C3.Append( pC );
|
|
pC = nullptr;
|
|
pO = nullptr;
|
|
}
|
|
|
|
// untrimmed surfaces
|
|
file.ReadInt( &count );
|
|
m_S.Reserve(count);
|
|
for ( i = 0; i < count; i++ )
|
|
{
|
|
pO = nullptr;
|
|
file.ReadObject( &pO );
|
|
pS = ON_Surface::Cast(pO);
|
|
if ( !pS )
|
|
delete pO; // ERROR!
|
|
m_S.Append( pS );
|
|
pS = nullptr;
|
|
pO = nullptr;
|
|
}
|
|
|
|
// vertices
|
|
file.ReadInt( &count );
|
|
m_V.Reserve(count);
|
|
m_V.SetCount(count);
|
|
for ( i = 0; i < count; i++ )
|
|
{
|
|
m_V[i].Read(file);
|
|
}
|
|
|
|
// edges
|
|
file.ReadInt( &count );
|
|
m_E.Reserve(count);
|
|
m_E.SetCount(count);
|
|
for ( i = 0; i < count; i++ )
|
|
{
|
|
ON_BrepEdge& edge = m_E[i];
|
|
edge.Read(file);
|
|
edge.SetProxyCurve( edge.m_c3i >= 0 ? m_C3[edge.m_c3i] : 0 );
|
|
edge.m_brep = this;
|
|
}
|
|
|
|
// trims
|
|
file.ReadInt( &count );
|
|
m_T.Reserve(count);
|
|
m_T.SetCount(count);
|
|
for ( i = 0; i < count; i++ )
|
|
{
|
|
m_T[i].Read(file);
|
|
ON_BrepTrim& trim = m_T[i];
|
|
trim.SetProxyCurve( trim.m_c2i >= 0 ? m_C2[trim.m_c2i] : 0 );
|
|
trim.m_brep = this;
|
|
}
|
|
|
|
// loops
|
|
file.ReadInt( &count );
|
|
m_L.Reserve(count);
|
|
m_L.SetCount(count);
|
|
for ( i = 0; i < count; i++ )
|
|
{
|
|
m_L[i].Read(file);
|
|
m_L[i].m_brep = this;
|
|
}
|
|
|
|
// faces
|
|
file.ReadInt( &count );
|
|
m_F.Reserve(count);
|
|
m_F.SetCount(count);
|
|
for ( i = 0; i < count; i++ )
|
|
{
|
|
ON_BrepFace& face = m_F[i];
|
|
face.Read(file);
|
|
face.SetProxySurface(face.m_si >= 0 ? m_S[face.m_si] : 0);
|
|
face.m_brep = this;
|
|
}
|
|
|
|
// bounding box
|
|
file.ReadPoint( m_bbox.m_min );
|
|
file.ReadPoint( m_bbox.m_max );
|
|
|
|
// fill in missing information
|
|
ReadFillInMissingBoxes(*this);
|
|
|
|
return true;
|
|
}
|
|
|
|
ON_Curve* ON_Brep::Read100_BrepCurve( ON_BinaryArchive& ) const
|
|
{
|
|
// TODO - look at old Rhino I/O tookit code and read b-rep curves
|
|
return nullptr;
|
|
}
|
|
|
|
ON_Surface* ON_Brep::Read100_BrepSurface( ON_BinaryArchive& ) const
|
|
{
|
|
// TODO - look at old Rhino I/O tookit code and read b-rep surfaces
|
|
return nullptr;
|
|
}
|
|
|