////////////////////////////////////////////////////////////////////////////////
//
// studs3d.cpp -    Visual C++ - 
//
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <afxdllx.h>
#include "resource.h"

#ifndef  __STUDS3D_H
#include "studs3d.h"
#endif   

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif 

      
//-------------------------------------------------------------------------------
// 
// ---
AFX_EXTENSION_MODULE StepDLL = { NULL, NULL };


//------------------------------------------------------------------------------
//
// ---
IApplicationPtr pNewKompasAPI( NULL );  


//------------------------------------------------------------------------------
//
// ---
Shpeel * Shpeel::callbackCurrentShpeel  = NULL;
IPartPtr Shpeel::callbackCurrentPhantom = NULL;


//----------------------------------------------------------------------------------------------
//  ,    
// ---
LPCTSTR DoubleToStr( double value ) 
{
  static TCHAR res[20];
  _stprintf( res, _T("%g"), value );
  return res;
}


//------------------------------------------------------------------------------
//  ,    
// ---
LPTSTR LoadStr( int id ) 
{ 
  static TCHAR buf[512]; 
  //       
  ksConvertLangStrExT( StepDLL.hModule, id, buf, 512 );
  return buf;
}


//------------------------------------------------------------------------------
//  ,    
// ---
LPTSTR _LoadStr( int id ) 
{ 
  static TCHAR buf[512]; 
  //       
  LoadString( StepDLL.hModule, id, buf, 512 );
  return buf;
}


//------------------------------------------------------------------------------
//  ,  
// ---
int LibMessage( LPCTSTR str, int flags ) 
{
  int res = 0;

  if ( str && str[0] )                  //  
  {
    int enabse = IsEnableTaskAccess();  //  
    if ( enabse )                       //     
      EnableTaskAccess(0);              //  

    //     
    res = MessageBox( (HWND) GetHWindow(), str, LoadStr(IDR_LIBID), flags );

    if ( enabse )                       //      
      EnableTaskAccess(1);              //    
  }
  return res;
}


//------------------------------------------------------------------------------
//  ,  
// ---
int LibMessage( int strId, int flags ) 
{
  return LibMessage( LoadStr(strId), flags );
}


//------------------------------------------------------------------------------
//  ,    
// ---
void DumpError(_com_error& e)
{
	_bstr_t bstrSource(e.Source());
	_bstr_t bstrDescription(e.Description());
	CString str;
	str.Format( _T(" = %08lx"),   e.Error());
	str += _T("\n:");       
  str += e.ErrorMessage();
	str += _T("\n:");        
  str += bstrSource;
	str += _T("\n :"); 
  str += bstrDescription;
	LibMessage( str, MB_OK | MB_ICONERROR);	
}

/*
//------------------------------------------------------------------------------
//  ,    
// ---
void ShowError()
{
  IErrorInfoPtr ef;
  GetErrorInfo( NULL, &ef );
  BSTR bstrDescription;
  ef->GetDescription( &bstrDescription );
  USES_CONVERSION;
  LibMessage( OLE2T(bstrDescription), MB_OK | MB_ICONERROR );
}
*/

//-------------------------------------------------------------------------------
//  ,     API
// ---
void GetNewKompasAPI() 
{
	if ( !( IApplication* )pNewKompasAPI ) 
  {
		CString filename;
		if( GetModuleFileName(NULL, filename.GetBuffer(255), 255) ) 
    {
			filename.ReleaseBuffer( 255 );
			CString libname;

      #ifdef __LIGHT_VERSION__
        libname = _LoadStr( IDS_API7LT ); // klAPI7.dll
      #else
        libname = _LoadStr( IDS_API7 );   // kAPI7.dll
      #endif

			filename.Replace( filename.Right(filename.GetLength() - (filename.ReverseFind(_T('\\')) + 1)), 
												libname );

			HINSTANCE hAppAuto = LoadLibrary( filename ); //  kAPI7.dll
			if(  hAppAuto ) 
      {
				//      KompasApplication  
        typedef LPDISPATCH ( WINAPI *FCreateKompasApplication )(); 
				 
        FCreateKompasApplication pCreateKompasApplication = 
					(FCreateKompasApplication)GetProcAddress( hAppAuto, "CreateKompasApplication" );	
				if ( pCreateKompasApplication )
					pNewKompasAPI = IDispatchPtr( pCreateKompasApplication(), false/*AddRef*/ ); //   Application
				FreeLibrary( hAppAuto );  
			}
		}
	}
}


//-------------------------------------------------------------------------------
//   
//    DLL
// ---
extern "C" int APIENTRY
DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved )
{
  UNREFERENCED_PARAMETER( lpReserved );

  if ( dwReason == DLL_PROCESS_ATTACH )
  {
    TRACE0( "DLL Initializing!" );
 
    if ( !AfxInitExtensionModule( StepDLL, hInstance ) )
      return 0;

    new CDynLinkLibrary( StepDLL );
  }
  else if ( dwReason == DLL_PROCESS_DETACH )
  {

    BaseEvent::TerminateEvents();
    BaseEvent::DestroyList(); //   
    if ( pNewKompasAPI )
      pNewKompasAPI = NULL;    //  


    TRACE0( "DLL Terminating!" );
    AfxTermExtensionModule( StepDLL );
  }
  return 1;
}


//-------------------------------------------------------------------------------
//   
// ---
unsigned int WINAPI LIBRARYID()
{
	return IDR_LIBID;
}


//-------------------------------------------------------------------------------
//   
// ---
void WINAPI LIBRARYENTRY( unsigned int ) 
{
  GetNewKompasAPI();
  IDocument3DPtr pDocument3d( ksGetActive3dDocument(), false/*AddRef*/ ); //       
  if ( (bool)pDocument3d && !pDocument3d->IsDetail() )
  {
    Shpeel* shpeel = new Shpeel();
	  if ( shpeel ) 
    {
	  	shpeel->Draw3D( pDocument3d );
			delete shpeel;
		}
//  10     pDocument3d->RebuildDocument();
  }
  else
  {
    //       3D-
    ErrorT( LoadStr( IDS_3DDOCERROR ) ); //    
  }

	if ( ReturnResult() == etError10 ) //  
	  ResultNULL();
}


////////////////////////////////////////////////////////////////////////////////
//
//  
//
////////////////////////////////////////////////////////////////////////////////


//------------------------------------------------------------------------------
//     
// ---
static short GetClassStrForGost( short gost ) 
{
  short n = 0; 
  switch ( gost ) 
  {
    case 22032 :
    case 22034 :
    case 22036 :
    case 22038 :
    case 22040 :
    case 22042 : n = IDS_STUD_B; break; // B 
    case 22033 :
    case 22035 :
    case 22037 :
    case 22039 :
    case 22041 :
    case 22043 : n = IDS_STUD_A; break; // A
  }
  return n;
}


//------------------------------------------------------------------------------
//     
// ---
short GetGostForTypeAndKlass( short type, short klass ) 
{
	short n = 0;
  switch ( type ) 
  {
    case 0 : n = klass ? 22032 : 22033; break; // 1d    
    case 1 : n = klass ? 22034 : 22035; break; // 1,25 d         
    case 2 : n = klass ? 22036 : 22037; break; // 1,6 d
    case 3 : n = klass ? 22038 : 22039; break; // 2d         
    case 4 : n = klass ? 22040 : 22041; break; // 2,5 d 
    case 5 : n = klass ? 22042 : 22043; break; // b0         
  }                                                
  return n;                                             
}                                               
                                                        
                                                   
//------------------------------------------------------------------------------
//      
// ---
static short GetTypeStrForGost( short gost ) 
{
  short n = 0; 
  switch ( gost ) 
  {
    case 22032 :
    case 22033 : n = IDS_STUD_1D;   break; // 1d               
    case 22034 :                                           
    case 22035 : n = IDS_STUD_125D; break; // 1,25 d                       
    case 22036 :                                    
    case 22037 : n = IDS_STUD_16D;  break; // 1,6 d      
    case 22038 :                                    
    case 22039 : n = IDS_STUD_2D;   break; // 2d    
    case 22040 :                                    
    case 22041 : n = IDS_STUD_25D;  break; // 2,5 d 
    case 22042 :                                    
    case 22043 : n = IDS_STUD_B0;   break; // b0    
  }
  return n;
}


//------------------------------------------------------------------------------
//    ( *.loa)
// ---
static void GetGostLoa( short gost, short *gNumb, short *stNumb ) 
{
  switch ( gost ) 
  {
    case 22032 : *gNumb = STR_200; *stNumb = STR_220; break;
    case 22033 : *gNumb = STR_201; *stNumb = STR_221; break;
    case 22034 : *gNumb = STR_202; *stNumb = STR_222; break;
    case 22035 : *gNumb = STR_203; *stNumb = STR_223; break;
    case 22036 : *gNumb = STR_204; *stNumb = STR_224; break;
    case 22037 : *gNumb = STR_205; *stNumb = STR_225; break;
    case 22038 : *gNumb = STR_206; *stNumb = STR_226; break;
    case 22039 : *gNumb = STR_207; *stNumb = STR_227; break;
    case 22040 : *gNumb = STR_208; *stNumb = STR_228; break;
    case 22041 : *gNumb = STR_209; *stNumb = STR_229; break;
    case 22042 : *gNumb = STR_210; *stNumb = STR_230; break;
    case 22043 : *gNumb = STR_211; *stNumb = STR_231; break;
    default    : *gNumb = 0; *stNumb = 0;
  }
}


//------------------------------------------------------------------------------
//    ()
// ---
static short GetGostStr( short gost ) 
{
	short n = 0;
  switch ( gost ) 
  {
    case 22032 : n = STR_101;	break;
    case 22033 : n = STR_102; break;
    case 22034 : n = STR_103; break;
    case 22035 : n = STR_104; break;
    case 22036 : n = STR_105; break;
    case 22037 : n = STR_106; break;
    case 22038 : n = STR_107; break;
    case 22039 : n = STR_108; break;
    case 22040 : n = STR_109; break;
    case 22041 : n = STR_110; break;
    case 22042 : n = STR_111; break;
    case 22043 : n = STR_112; break;
  }              
  return n;
}


//-------------------------------------------------------------------------------
//   
// ---
int _ConnectDB( reference bd, LPCTSTR name ) 
{
  static TCHAR fullName[512];
  bool res = false;
  if( GetModuleFileName( StepDLL.hModule, fullName, 512 ) ) 
  {
    LPTSTR c = _tcsrchr( fullName, _T('\\'));
    if ( c ) 
    {
      *(c + 1) = _T('\0');
      _tcscat( fullName, name );
      OFSTRUCT ofs;
      if ( OpenFile(_bstr_t(fullName), &ofs, OF_EXIST) != HFILE_ERROR )
        res = true;
      else 
      {
        *(c + 1) = _T('\0');
        _tcscat( fullName, _T("load\\") );
        _tcscat( fullName, name );
        if ( OpenFile(_bstr_t(fullName), &ofs, OF_EXIST) != HFILE_ERROR )
          res = true;
      }
    }
  }
  return res ? ConnectDBT( bd, fullName ) : ConnectDBT( bd, (LPTSTR)name );
}


//------------------------------------------------------------------------------
//     varName  val
// ---
void SetVarValue( IVariableCollectionPtr& varArr, TCHAR* varName, double val ) 
{
	IVariablePtr var( varArr->GetByName( _bstr_t(varName), true, false), false/*AddRef*/ ); //  
  if ( var )
    var->SetValue( val ); //  
}  


//------------------------------------------------------------------------------
//      ( planar = true - ,
// planar = false -   )
// ---
bool IsSurface( IEntityPtr& entity, bool planar = true, double * = NULL ) 
{
	bool res = false;
//  K8+      ,            
  if ( (bool)entity && entity->IsCreated() ) 
  {
    IFaceDefinitionPtr faceDef( IUnknownPtr( entity->GetDefinition(), false/*AddRef*/ ) ); 
    if ( faceDef ) 
    {
      if ( planar && faceDef->IsPlanar() )
        res = true;
      if ( !planar && faceDef->IsCylinder() )
        res = true;
    }
  }
  return res;
} 


//------------------------------------------------------------------------------
//     
// ---
bool IsAxis( IEntityPtr& entity ) 
{
  if ( entity ) 
  {
  	return entity->IsIt( o3d_axis2Planes )        ||  //    
    				 entity->IsIt( o3d_axisOperation )    ||  //  
            	 entity->IsIt( o3d_axis2Points )    ||  //    
                 entity->IsIt( o3d_axisConeFace ) ||  //   
                 	 entity->IsIt( o3d_axisEdge );      //   
  }
  return false;
}
    
//------------------------------------------------------------------------------
//  
// --- 
void AddMates( Shpeel& obj, 
               IEntityCollectionPtr& collection, 
               IPart* p = NULL, 
               IMateConstraintCollection* mCol = NULL ) 
{
  IEntityPtr ent( collection->GetByIndex(0), false/*AddRef*/ );
  if ( (bool)ent && IsSurface(ent) ) // 
    if ( !obj.AddMate( mc_Coincidence, obj.GetDirectionElem(), 1, 0, ent, _T("Plane"), p, mCol )) 
    {
    	collection->SetByIndex( NULL, 0 );
    }

  ent.Attach( collection->GetByIndex(1) );
  if ( (bool)ent && IsSurface(ent, false) ) //  
    if ( !obj.AddMate( mc_Concentric, 0, 1, 0, ent, _T("Axis"), p, mCol )) 
    {
    	collection->SetByIndex( NULL, 1 );
    }

  ent.Attach( collection->GetByIndex(2) );
  if ( (bool)ent && IsAxis(ent) ) // 
    if ( !obj.AddMate( mc_Concentric, 0, 1, 0, ent, _T("Axis"), p, mCol )) 
    {
    	collection->SetByIndex( NULL, 2 );
    }
}


//------------------------------------------------------------------------------
//  
// ---
void DelMates( Shpeel& obj, IEntityCollectionPtr& collection ) 
{
  IEntityPtr ent( collection->GetByIndex(0), false );
  if ( (bool)ent && IsSurface(ent) ) // 
    obj.GetDoc()->RemoveMateConstraint( mc_Coincidence, ent, obj.GetEntityByName(_T("Plane"), obj.GetPart() ) );

  ent.Attach( collection->GetByIndex(1) );
  if ( (bool)ent && IsSurface(ent, false) ) //  
    obj.GetDoc()->RemoveMateConstraint( mc_Concentric, ent, obj.GetEntityByName(_T("Axis"), obj.GetPart() ) );

  ent.Attach( collection->GetByIndex(2) );
  if ( (bool)ent && IsAxis(ent) ) // 
    obj.GetDoc()->RemoveMateConstraint( mc_Concentric, ent, obj.GetEntityByName(_T("Axis"), obj.GetPart() ) );
}

//------------------------------------------------------------------------------
//  
// ---
int ReadShpeelBase( float d, ShpeelBase &base, SHPEEL * shpeel ) 
{
  TCHAR buf[256];
  ShpeelTmp shpeelTmp; 
  memset( &shpeelTmp, 0, sizeof(shpeelTmp) );

  _stprintf( buf, _T("t = 1 && d=%g"), d );
  if ( !ConditionT(base.bg,  base.rg2, buf) ) 
    return 0;

  int res = ReadRecord( base.bg, base.rg2, &shpeelTmp );
  if( res ) 
  {
    shpeel->d  = shpeelTmp.d;  //  
    shpeel->p1 = shpeelTmp.p1; //   
    shpeel->p2 = shpeelTmp.p2; //   
    shpeel->b1 = shpeelTmp.b1; //  
    shpeel->c  = shpeelTmp.c;  //   
  }

  return res;
}


//------------------------------------------------------------------------------
//   
//  1 -  0 -    -1 -    
// ---
int ReadShpeelStBase( ShpeelBase &base, SHPEEL * shpeel )
{
  TCHAR buf[256];
  ShpeelSTmp shpeelSTmp;
  memset( &shpeelSTmp, 0, sizeof(shpeelSTmp) );

  _stprintf( buf, _T("t = 1 && L=%g && d=%g"), shpeel->l, shpeel->d );
  if ( !ConditionT(base.bs,  base.rs2, buf) ) 
    return -1;
  
  int i = ReadRecord(  base.bs, base.rs2, &shpeelSTmp );
  if ( !i )  
  {
    _stprintf( buf, _T("t = 1 && d=%.1f"), shpeel->d);

    if ( !::ConditionT(base.bs,  base.rs2, buf) ) 
      return -1;

    ReadRecord( base.bs, base.rs2, &shpeelSTmp );
  }

  shpeel->l  = shpeelSTmp.l;
  shpeel->b  = shpeelSTmp.b;
  shpeel->m1 = shpeelSTmp.m1;
  shpeel->m2 = shpeelSTmp.m2;

  // ALLST -   
  if( shpeel->gost > 22041 && !(fabs(shpeel->b) > EPSILON) ) 
  {
    shpeel->f |= ALLST;
    shpeel->f &= ~ISPOLN; //  1  , .  2 
  }
  else
    shpeel->f &=~ ALLST;
  
  return 1;
}


////////////////////////////////////////////////////////////////////////////////
//
//   
//
////////////////////////////////////////////////////////////////////////////////

//------------------------------------------------------------------------------
//  
// ---
int Shpeel::OpenBase() 
{
  bBase.bg = CreateDBT( _T("TXT_DB") );
  bBase.bs = CreateDBT( _T("TXT_DB") );

  short gNumb, stNumb;
  GetGostLoa( tmp.gost, &gNumb, &stNumb );
  if( !_ConnectDB( bBase.bg, LoadStr( gNumb ) ) ) // 22032.loa ..
   return 0;
  else 
  {
    if( !_ConnectDB( bBase.bs, LoadStr( stNumb ) ) )  // st22032.loa ..
      return 0;
    else 
    {
      bBase.rg1 = Relation( bBase.bg );
        RIntT  (_T("t"));
        RFloatT(_T("d"));
      EndRelation();
      if ( !DoStatementT(bBase.bg, bBase.rg1, _T("1 2") ) ) 
        return 0;
      else 
      {
        bBase.rg2 = Relation( bBase.bg );
          RIntT  (_T("t"));
          RFloatT(_T("d"));
          RFloatT(_T(""));
          RFloatT(_T(""));
          RFloatT(_T(""));
          RFloatT(_T(""));
        EndRelation();
        if ( !DoStatementT( bBase.bg, bBase.rg2, _T("")) )
          return 0;
        else 
        {
          bBase.rs1 = Relation( bBase.bs );
            RIntT ( _T("t") );
            RFloatT( _T("L") );
            RFloatT( _T("d") );
          EndRelation();
          if ( !DoStatementT(bBase.bs, bBase.rs1, _T("1 2 3") ) )
            return 0;
          else 
          {
            bBase.rs2 = Relation( bBase.bs );
              RIntT (_T("t"));
              RFloatT(_T("L"));
              RFloatT(_T("d"));
              RFloatT(_T(""));
              RFloatT(_T(""));
              RFloatT(_T(""));
            EndRelation();
            if ( !DoStatementT( bBase.bs, bBase.rs2, _T("")) )
              return 0;
            else 
            {
              openBase = true;
              return 1;
            }
          }
        }
      }
    }
  }
}


//------------------------------------------------------------------------------
//  
// ---
void Shpeel::CloseBase()
{
	if ( bBase.bg )
	  DeleteDB( bBase.bg );
  if ( bBase.bs )
	  DeleteDB( bBase.bs );
  openBase = false;
}


//------------------------------------------------------------------------------
//  
// ---
int Shpeel::GetParam() 
{
  return part ? part->GetUserParam( &par, Size() ) : 0;
}


//------------------------------------------------------------------------------
// 
// ---
Shpeel::Shpeel() : part    ( NULL  ),
                   collect ( NULL  ),
                   collectChanged( false ),
                   changed( true )
{
  par.flagAttr    = 1;
  par.typeSwitch  = 0;
  par.ang         = 0;
  par.drawType    = 0;

  memset( &bBase, 0, sizeof(ShpeelBase) );
  if( !GetParam() ) 
  {
    Init();
  }
  else 
  {
    if ( !tmp.ver )
      tmp.ver = 1;
  }
}


//------------------------------------------------------------------------------
//  
// ---
Shpeel::~Shpeel()
{
  if ( openBase ) //   
    CloseBase();  //   
}


//------------------------------------------------------------------------------
//  
// ---
Shpeel::Shpeel( const Shpeel& other ) : part    ( NULL  ),
                                        collect ( NULL  ),
                                        collectChanged( false ),
                                        changed( true ),
                                        openBase( false )
{
  par.flagAttr    = 1;
  par.typeSwitch  = 0;
  par.ang         = 0;
  par.drawType    = 0;

  memcpy( &bBase, &other.bBase, sizeof(ShpeelBase) );
  Assign( other );
}


//------------------------------------------------------------------------------
//  
// ---
Shpeel* Shpeel::Dublicate() 
{
  return new Shpeel( *this );
}


//------------------------------------------------------------------------------
//
// ---
void Shpeel::Assign( const Shpeel& other ) 
{
  part        = other.part;
  flagMode    = other.flagMode;
  par         = other.par;
  collect     = other.collect;
  memcpy( &tmp, &other.tmp, sizeof(SHPEEL) );
}


//------------------------------------------------------------------------------
// 
// ---
void Shpeel::Init() 
{
  tmp.gost       = 22032;
  par.drawType   = ID_VID;
  par.ang        = 0;
  tmp.f          = 0;
  tmp.f         |= TAKEISPOLN;
  tmp.d          = 20;
  tmp.p1         = 2.5;
  tmp.p2         = 1.5;
  tmp.c          = 2.5;
  tmp.indexMassa = 0; // 0 -  1 -   3 -  2 - 
  tmp.ver        = 1;
  tmp.b1         = 20;
  tmp.klass      = 2; // klass=B
  tmp.l          = 90;
  tmp.b          = 46;
  tmp.m1         = 245.9f;
  tmp.m2         = 228.9f;
}


//------------------------------------------------------------------------------
//                
// ---
CString& Shpeel::GetFileName() 
{        
  static TCHAR fullName[512];
  bool res = false;
  if( GetModuleFileName( StepDLL.hModule, fullName, sizeof(fullName) ) ) 
  {
    TCHAR *c = _tcsrchr( fullName, _T('\\'));
    if ( c ) 
    {
      *(c + 1) = _T('\0');
      _tcscat( fullName, STUDS_FILE );
      OFSTRUCT ofs;
      if ( OpenFile(_bstr_t(fullName), &ofs, OF_EXIST) != HFILE_ERROR )
        res = true;
      else 
      {
        *(c + 1) = _T('\0');
        _tcscat( fullName, _T("model\\") );
        _tcscat( fullName, STUDS_FILE );
        if ( OpenFile(_bstr_t(fullName), &ofs, OF_EXIST) != HFILE_ERROR )
          res = true;
      }
    }
  }

  if( res )
  {
    _tcscat( fullName, STUDS_INPUT_PATH );
    fileName = fullName;
  }
  
  return fileName;
}


//------------------------------------------------------------------------------
//  
// ---
void Shpeel::SetParam( IPartPtr& pPart ) 
{
  //   
  if( !(bool)pPart )
    pPart = part;
    
  if( pPart ) 
  {
    //    
    IVariableCollectionPtr varArr( pPart->VariableCollection(), false/*AddRef*/ );
    if ( varArr ) 
    {
      float l, b1 = 0, b; //      - b1=0
      l = tmp.b1 + tmp.l; //   
      b = tmp.b;
      float step = tmp.f & PITCH ? tmp.p1 : tmp.p2;
      if( fabs(tmp.b1) < EPSILON ) //  22042,  22043
      { 
        if( fabs(tmp.b) > EPSILON ) 
          b1 = b;
      }
      else 
      {
        b1 = tmp.b1;
        if ( fabs(tmp.b) < EPSILON  )
          b = tmp.l - 0.5f * tmp.d - 2 * step;
      }
      
      //  
    	SetVarValue( varArr, _T("d"),      tmp.d                        ); //  
      float len = fabs(b1 - b) < EPSILON ? tmp.l - b1 : tmp.l;
    	SetVarValue( varArr, _T("l"),      len                          ); //  
    	SetVarValue( varArr, _T("b1"),     b1                           ); //   
    	SetVarValue( varArr, _T("c1"),     tmp.c                        ); //     
      if ( fabs(l - b1 - b) > EPSILON )
	    	SetVarValue( varArr, _T("l1"),   l - b1 - b                   ); //    
    	SetVarValue( varArr, _T("t"),      (step * 0.866 * 3 / 8)       ); //   
      int perf2 = ( !(tmp.f & ISPOLN) ) || 
                  ( tmp.f & ALLST ) ||                               // ALLST -   
                  ( fabs(l - b1 - b) < EPSILON ) ? 1 : 0;
    	SetVarValue( varArr, _T("cut1"),   perf2                        ); // /  2
    	SetVarValue( varArr, _T("f1"),    !(tmp.f & SIMPLE) ? 0.0 : 1.0 ); // / 

      //   
      TCHAR buf[255];
      _stprintf( buf, LoadStr( IDS_STUD_NAME ), tmp.d, tmp.l, tmp.gost ); //   
      pPart->SetName( _bstr_t(buf) ); //    

      //      
      pPart->RebuildModelEx(true);
      pPart->Update();                //  
    }

    pPart->SetUserParam( &par, Size(), 0, 0, -1 );
  }
}


//------------------------------------------------------------------------------
//  
// ---
bool Shpeel::AddMate( short constraintType, 
                      short direction, 
                      short fixed, 
                      double val,
                      IEntity* ent, 
                      LPCTSTR surfaceName, 
                      IPart* p,
                      IMateConstraintCollection* mCol ) 
{
  bool res = false;
  if ( !p && !mCol ) //  
  { 
    if ( doc->AddMateConstraint(constraintType, ent, GetEntityByName(surfaceName, part), direction, fixed, val) ) 
      res = true;
  }
  else //  
  {     
    IMateConstraintPtr mate(doc->GetMateConstraint(), false/*AddRef*/);
    if ( mate ) 
    {
      mate->SetConstraintType( constraintType );
      mate->SetDirection( direction );
      mate->SetFixed( fixed );
      mate->SetBaseObj(1, ent );
      // 
      mate->SetBaseObj(2, GetEntityByName(surfaceName, IPartPtr(p) ) );
      if (mate->Create()) 
      {
        mCol->AddMateConstraint( mate );
        res = true;
      }
    }
  }
  return res;
}


//------------------------------------------------------------------------------
//  
// ---
void Shpeel::SetMates( IRequestInfoPtr& info, bool delMates ) 
{
  IEntityCollectionPtr collection( !delMates ? info->GetEntityCollection()
  																					 : part->GetMateConstraintObjects(), false );
  if ( collection )
  {
    if ( (bool)doc && collection->GetCount() > 2 )
	    if ( !delMates )
  	  	AddMates( *this, collection );
      else
  	  	DelMates( *this, collection );

    if ( !delMates )
	    part->SetMateConstraintObjects( collection/*NULL*/ );
  }
}


//------------------------------------------------------------------------------
//   
// ---
reference Shpeel::EditSpcObj( reference spcObj )
{
  ISpecification3DPtr specification( doc->GetSpecification(), false/*AddRef*/ );
  if ( !flagMode && !par.flagAttr && !(bool)specification )
    return 0;

  if ( flagMode ) 
  {
    spcObj = specification->GetSpcObjForGeomWithLimit( NULL,             //   
                          						                 0,                //   
                                      				         part,
                                              				 1,                // 1 -   0-  
                                              				 STANDART_SECTION, //  
                                              				 81764182256.0 );
    if( !par.flagAttr )
      return spcObj;


    if ( spcObj && !ksSpcObjectEdit( spcObj ) )
      spcObj = 0;
  }
  bool flagMode = !!spcObj;
  if ( flagMode || ksSpcObjectCreate( NULL,                 //   
 																		  0,                    //   
                                      STANDART_SECTION, 0,  //    
                                      81764182256.0, 0) )   //  
  { 
    // 
    UINT uBuf = !!(tmp.f & ISPOLN );
    ksSpcVisible( SPC_NAME, 2, uBuf );
    if ( uBuf ) 
    {
      uBuf = 2;
      ksSpcChangeValue( SPC_NAME, 2, &uBuf, UINT_ATTR_TYPE  );
    }

    //  
    ksSpcChangeValue( SPC_NAME, 4, &tmp.d, FLOAT_ATTR_TYPE  );

    //   
    uBuf = !(tmp.f & PITCHOFF || !(tmp.f &PITCH));
    ksSpcVisible( SPC_NAME, 5, uBuf );
    ksSpcVisible( SPC_NAME, 6, uBuf ); // 
    if ( uBuf )
      ksSpcChangeValue( SPC_NAME, 6, &tmp.p2, FLOAT_ATTR_TYPE );

    //  
    uBuf = (UINT)tmp.l;
    ksSpcChangeValue( SPC_NAME, 9, &uBuf, UINT_ATTR_TYPE  );

    if( !flagMode ) 
    {
      ksSpcVisible( SPC_NAME, 7,  0 ); //   
      ksSpcVisible( SPC_NAME, 10, 0 ); //   
      ksSpcVisible( SPC_NAME, 11, 0 ); //  
      ksSpcVisible( SPC_NAME, 12, 0 ); //  
    }

    //  
    uBuf = tmp.gost;
    ksSpcChangeValue( SPC_NAME , 14, &uBuf, UINT_ATTR_TYPE  );
    
    float massa = tmp.f & ISPOLN ? tmp.m2 : tmp.m1;
    // 0 -  1 -   3 -  2 - 
    massa = massa*( !tmp.indexMassa ? 1 : tmp.indexMassa==1 ? 0.356f : tmp.indexMassa==3 ? 0.97f : 1.08f )/COUNT_MASSA;

    TCHAR buf[128];
    _stprintf( buf, _T("%f") , massa );
    ksSpcMassaT( buf ); //  

    //  
    specification->SpcIncludePart( part, false );

    return ksSpcObjectEnd();
  }
  return 0;
}


//-------------------------------------------------------------------------------
//    
// ---
bool Shpeel::DrawSpcObj( reference & spcObj ) 
{
  spcObj = 0;
  if( IsSpcObjCreate() ) 
  {
    if ( ReturnResult() == etError10 ) //  
      ResultNULL();

    spcObj = EditSpcObj( spcObj );
    if( !par.flagAttr && spcObj ) 
    {
      DeleteObj( spcObj );
      spcObj = 0;
    }
  }
  return !!spcObj;
}


//---------------------------------------------------------------------------------------------------- 
//   
// ---
void Shpeel::ShowParam()
{
  //  
  if ( paramGrid ) 
  {
    rowIndex = 1;

    // "b()  "
    AddDoubleToGrig( IDS_WRENCH_ENDING, tmp.b ); 
    // "b0()  "
    AddDoubleToGrig( IDS_SCREW_ENDING, tmp.b1 ); 
    // "p()  "
    float step = !(tmp.f & PITCHOFF || !(tmp.f & PITCH)) ? tmp.p1 : tmp.p2;
    AddDoubleToGrig( IDS_PITCH, step ); 
    // "c() "
    AddDoubleToGrig( IDS_FACET, tmp.c ); 
    // "m()  1000 "
    float massa = tmp.f & ISPOLN ? tmp.m2 : tmp.m1;
    // 0 -  1 -   3 -  2 - 
    massa = massa*( !tmp.indexMassa ? 1 : tmp.indexMassa==1 ? 0.356f : tmp.indexMassa==3 ? 0.97f : 1.08f );
    AddDoubleToGrig( IDS_MASSA_1000, massa ); 
  
    paramGrid->RowCount = rowIndex;
    paramGrid->UpdateParam();
  }   
}


//-------------------------------------------------------------------------------------
//  
// ---
long Shpeel::GetSlideID()
{
  if( tmp.gost > 22041 ) 
  {
    if ( tmp.f & ALLST ) // ALLST -   
      return SH22042_3;
    else 
    {
      if ( tmp.f & ISPOLN )
        return SH22042_2;
      else
        return SH22042_1;
    }
  }
  else 
  {
    if ( tmp.f & ISPOLN )
      return SH22032_2;
    else
      return SH22032_1;
  }
}


//-------------------------------------------------------------------------------------
//   
// ---
void Shpeel::OnChangeControlValue( long ctrlID, const VARIANT& newVal ) 
{
  switch ( ctrlID ) 
  {
    case IDP_SPC_OBJ: //  
      par.flagAttr = !par.flagAttr;
      break;

    case IDP_GOST: // 
    { 
      CString strGost = newVal.bstrVal;       
      short gost = (short)_ttoi( strGost.Left(5) );
    	if ( gost && gost != tmp.gost ) 
      {
        tmp.gost = gost;
        if ( ReadShpeelBase( tmp.d, bBase, &tmp ) && ReadShpeelStBase(bBase, &tmp ) ) //  
        {
          IPropertyListPtr diamList( GetPropertyControl(IDP_DIAM) );
          if( diamList )
            FillDiametr( diamList ); //   

          IPropertyListPtr lenghtList( GetPropertyControl(IDP_LENGHT) );
          if( lenghtList )
            FillLenght( lenghtList ); //   
        
          IPropertyListPtr screwEndingList( GetPropertyControl(IDP_SCREW_ENDING) );
          if( screwEndingList )
            //    
            screwEndingList->Value =  LoadStr( GetTypeStrForGost( tmp.gost ));

          IPropertyListPtr classList( GetPropertyControl(IDP_CLASS) );
          if( classList )
            //    
            classList->Value = LoadStr( GetClassStrForGost( tmp.gost ) ); 

          IPropertyMultiButtonPtr ispButtons( GetPropertyControl(IDP_ISP) );
          if( ispButtons )
          {
            //    2
            bool enable = tmp.f & ALLST ? false : true; // ALLST -   
            ispButtons->ButtonEnable [ IDP_BMP_G_I2 ] = enable;
            if( !enable )
              ispButtons->ButtonChecked[ IDP_BMP_G_I1 ] = !(tmp.f & ISPOLN ); //  1  , .  2 
          }

          //     (   -   )
          ShowParam(); 
          //    
          SetChanged(); 
        }
      }
      break;
    }      

    case IDP_DIAM: //  
    { 
      float diam = (float)newVal.dblVal; 
    	if ( fabs(diam - tmp.d ) > EPSILON ) 
      {
        if ( ReadShpeelBase( diam, bBase, &tmp ) && ReadShpeelStBase(bBase, &tmp ) ) //  
        {
          IPropertyListPtr lenghtList( GetPropertyControl(IDP_LENGHT) );
          if( lenghtList )
            FillLenght( lenghtList ); //   
          
          IPropertyMultiButtonPtr ispButtons( GetPropertyControl(IDP_ISP) );
          if( ispButtons )
          {
            //    2
            bool enable = tmp.f & ALLST ? false : true; // ALLST -   
            ispButtons->ButtonEnable [ IDP_BMP_G_I2 ] = enable;
            if( !enable )
              ispButtons->ButtonChecked[ IDP_BMP_G_I1 ] = !(tmp.f & ISPOLN ); //  1  , .  2 
          }

          //     (   -   )
          ShowParam();
          //    
          SetChanged(); 
        }
      }
      break;
    }
    case IDP_LENGHT: //   
    { 
      float lenght = (float)newVal.dblVal; 
    	if ( fabs(lenght - tmp.l ) > EPSILON ) 
      {
        tmp.l = lenght;

        //    
        SetChanged(); 
      }
      break;
    }
    case IDP_SCREW_ENDING: //     
    {
      CString strScrewEnding = newVal.bstrVal;    
      for ( int i = 0; i < 6; i++ )
      {
        if( strScrewEnding == LoadStr( IDS_STUD_1D + i ) )  
        {
          short gost = GetGostForTypeAndKlass( i, tmp.klass ); 
          if( gost != tmp.gost )
          { 
            IPropertyListPtr gostList( GetPropertyControl(IDP_GOST) );
            if( gostList )
            {
              //    
              LPCTSTR str = LoadStr( GetGostStr( gost ) );
              gostList->Value = str;
              OnChangeControlValue( IDP_GOST, _variant_t( str ) );
              return;
            }
          }
        }       
      } 
      break;
    }
    case IDP_CLASS: //    
    {
      CString strClass = newVal.bstrVal;    
      for ( int j = 0; j < 2; j++ )
      {
        if( strClass == LoadStr( IDS_STUD_A + j ) )  
        {
          IPropertyListPtr screwEndingList( GetPropertyControl(IDP_SCREW_ENDING) );
          if( screwEndingList ) 
          {
            CString strScrewEnding = screwEndingList->Value.bstrVal;
            for ( int i = 0; i < 6; i++ )
            {
              if( strScrewEnding == LoadStr( IDS_STUD_1D + i ) )  
              {
                short gost = GetGostForTypeAndKlass( i, j );
                if( gost != tmp.gost )
                {
                  IPropertyListPtr gostList( GetPropertyControl(IDP_GOST) );
                  if( gostList )
                  {
                    //    
                    LPCTSTR str = LoadStr( GetGostStr( gost ) );
                    gostList->Value = str;
                    OnChangeControlValue( IDP_GOST, _variant_t( str ) );
                    return;
                  }
                }
              }
            }             
          }
        }
      }
      break;
    }
    case IDP_MATERIAL: //    
    {
      CString strMaterial = newVal.bstrVal;    
      for ( int i = 0; i < 4; i++ )
      {
        if( strMaterial == LoadStr( IDS_MATERIAL_STEEL + i ) )  
        {
          if( i != tmp.indexMassa )
          {
            tmp.indexMassa = i;

            //     (  )
            ShowParam(); 
          }
        }
      } 
      break;
    }
  }
} 


//---------------------------------------------------------------------------------------------------- 
//   
// ---
void Shpeel::OnButtonClick( long buttonID ) 
{ 
  switch ( buttonID ) 
  { 
    case IDP_BMP_G_I1: //  1       
      tmp.f &= ~ISPOLN;

      //     (     ) 
      ShowParam(); 
      //    
      SetChanged(); 

      break;
       
    case IDP_BMP_G_I2: //  2
      tmp.f |= ISPOLN; 

      //     (     ) 
      ShowParam(); 
      //    
      SetChanged(); 

      break;

    case IDP_BMP_G_STEP : //  
    { 
      tmp.f & PITCH ? tmp.f &= ~PITCH : tmp.f |= PITCH;

      //     (   ) 
      ShowParam();

      break; 
    }
    case ID_SIMPLE : //          
      tmp.f & SIMPLE ? tmp.f &= ~SIMPLE : tmp.f |= SIMPLE;
      
      //    
      SetChanged();       
      
      break;
  }
}


//------------------------------------------------------------------------------
//   
// ---
void Shpeel::FillDiametr( IPropertyListPtr & diamList ) 
{
  if( openBase )
  {
    float lMin         = MAX_LENGTH; //    
    float lMax         = MIN_LENGTH; //    
    bool  enterInRange = false;      //       
   
    struct {
      short t;
      float d;
    } tmpD;
    memset( &tmpD, 0, sizeof(tmpD) );

    if ( ConditionT(bBase.bg, bBase.rg1, _T("t = 1")) ) 
    {
      int i = 1;
      while( i ) //     
      {                                 
        i = ReadRecord( bBase.bg, bBase.rg1, &tmpD ); //  
        if ( i ) //   
        {                                     
          //    
          diamList->Add( tmpD.d );

          if ( tmpD.d == tmp.d )
            enterInRange = true; //       
          if ( tmpD.d < lMin )
            lMin = tmpD.d;       //   
          if ( tmpD.d > lMax )                          
            lMax = tmpD.d;       //   
        }
      }
      if ( !enterInRange ) //          
        tmp.d = lMin;      //    
      if ( tmp.d < lMin )  //        
        tmp.d = lMin;      //    
      if ( tmp.d > lMax )  //        
        tmp.d = lMax;      //    
    
      //     
      diamList->Value = tmp.d;
    }
  } 
}


//------------------------------------------------------------------------------
//   
// ---
void Shpeel::FillLenght( IPropertyListPtr & lenghtList ) 
{
  if( openBase )
  {
    float lMin         = MAX_LENGTH; //    
    float lMax         = MIN_LENGTH; //    
    bool  enterInRange = false;      //       

    struct {
      short t;
      float L;
      float dr;
    } tmpL;
    memset( &tmpL, 0, sizeof(tmpL) ); 

    TCHAR buf[128];
    _stprintf( buf, _T("t = 1 && d=%.1f"), tmp.d );
  
    if ( ConditionT(bBase.bs, bBase.rs1, buf) ) 
    {
      int i = 1;
      while( i ) //     
      {    
        i = ReadRecord( bBase.bs, bBase.rs1, &tmpL ); //  
        if ( i ) //   
        {      
          //    
          lenghtList->Add( tmpL.L ); //    

          if ( tmpL.L == tmp.l )
            enterInRange = true; //       
          if ( tmpL.L < lMin )
            lMin = tmpL.L;       //   
          if ( tmpL.L > lMax )                          
            lMax = tmpL.L;       //   
        }
      }
      if ( !enterInRange ) //          
        tmp.l = lMin;      //    
      if ( tmp.l < lMin )  //        
        tmp.l = lMin;      //    
      if ( tmp.l > lMax )  //        
        tmp.l = lMax;      //    
    
      //     
      lenghtList->Value = tmp.l;
    }
  }
}


//-------------------------------------------------------------------------------
//     
// ---
void Shpeel::FillScrewEnding( IPropertyListPtr & screwEndingList )
{
  for ( int i = 0; i < 6; i++ )
    //    
    screwEndingList->Add( LoadStr( IDS_STUD_1D + i ) );  
  //    
  screwEndingList->Value = LoadStr( GetTypeStrForGost( tmp.gost ) );
}


//-------------------------------------------------------------------------------
//     
// ---
void Shpeel::FillClass( IPropertyListPtr & classList )
{
  for ( int i = 0; i < 2; i++ )
    //    
    classList->Add( LoadStr( IDS_STUD_A + i ) );  
  //    
  classList->Value = LoadStr( GetClassStrForGost( tmp.gost ) ); 
}


//-------------------------------------------------------------------------------
//   
// ---
void Shpeel::FillGost( IPropertyListPtr & gostList ) 
{
  for ( int i = 0; i < 12; i++ )
    //    
    gostList->Add( LoadStr( STR_101 + i ) );  
  //    
  gostList->Value = _variant_t( _bstr_t( LoadStr( GetGostStr( tmp.gost ) ) ) );
}
        

//-------------------------------------------------------------------------------
//    indexMassa
// 0 -  1 -   2 -  3 - 
// ---
static short GetMaterialStr( short indexMassa )
{
  short n = 0;
  if( indexMassa >= 0 && indexMassa <= 3 )
    n = IDS_MATERIAL_STEEL + indexMassa;
  return n;
}


//-------------------------------------------------------------------------------
//     
// ---
void Shpeel::FillMaterial( IPropertyListPtr & materialList ) 
{
  for ( int i = 0; i < 4; i++ )
    //    
    materialList->Add( LoadStr( IDS_MATERIAL_STEEL + i ) );  
  //   
  materialList->Value = LoadStr( GetMaterialStr( tmp.indexMassa ) ); // 0 -  1 -   3 -  2 - 
}


//-------------------------------------------------------------------------------
//   
// ---
void Shpeel::ShowControls() 
{
  //  
  IPropertyListPtr gostList( CreateStringList() );
  if ( gostList ) 
  {
    InitPropertyControl( gostList, IDP_GOST, IDS_GOST_TIPS, IDS_GOST_TIPS );
    FillGost( gostList ); //   
  }
  
  if ( openBase ) //   
    CloseBase();  //   

  //       
  if ( OpenBase() )                                  
  { 
    //   
    IPropertyListPtr diamList( CreateRealList() );
    if ( diamList ) 
    {
      InitPropertyControl( diamList, IDP_DIAM, IDS_DIAM_TIPS, IDS_DIAM_TIPS );
      FillDiametr( diamList ); //   
    }

    //   
    IPropertyListPtr lenghtList( CreateRealList() );
    if ( lenghtList ) 
    {
      InitPropertyControl( lenghtList, IDP_LENGHT, IDS_LENGHT_TIPS, IDS_LENGHT_TIPS );
      FillLenght( lenghtList ); //   
    }

    //    
    IPropertyListPtr screwEndingList( CreateStringList() );
    if ( screwEndingList ) 
    {
      InitPropertyControl( screwEndingList, IDP_SCREW_ENDING, IDS_SCREW_ENDING_TIPS, IDS_SCREW_ENDING_TIPS );
      FillScrewEnding( screwEndingList ); //     
    }
  }

  //   
  IPropertyListPtr classList( CreateStringList() );
  if ( classList ) 
  {
    InitPropertyControl( classList, IDP_CLASS, IDS_CLASS_TIPS, IDS_CLASS_TIPS );
    FillClass( classList ); //    
  }

  //  
  IPropertyListPtr materialList( CreateStringList() );
  if ( materialList ) 
  {
    InitPropertyControl( materialList, IDP_MATERIAL, IDS_MATERIAL_TIPS, IDS_MATERIAL_TIPS );
    FillMaterial( materialList ); //   
  }
  
  CreateSeparator(ksSeparatorDownName);

  // 
  IPropertyMultiButtonPtr ispButtons( CreateMultiButton(ksRadioButton) );
  if ( ispButtons ) 
  {
    InitPropertyControl( ispButtons, IDP_ISP, IDS_ISP_HINT, IDS_ISP_TIPS, TRUE, ksNameVerticalVisible );
    
    //   1
    AddButton( ispButtons, IDP_BMP_G_I1, !(tmp.f & ISPOLN ) );
    //    2
    bool enable = tmp.f & ALLST ? false : true; // ALLST -   
    //   2
    AddButton( ispButtons, IDP_BMP_G_I2, !!(tmp.f & ISPOLN ), enable );
  }

  CreateSeparator(ksSeparatorDownName);

  //  
  IPropertyMultiButtonPtr paramButtons( CreateMultiButton(ksCheckButton) );
  if ( paramButtons ) 
  {
    InitPropertyControl( paramButtons, IDP_FLAGS, IDS_FLAGS_TIPS, IDS_FLAGS_TIPS, TRUE, ksNameVerticalVisible );
    //  
    AddButton( paramButtons, IDP_BMP_G_STEP, !!(tmp.f & PITCH), !(tmp.f & PITCHOFF) );
    // 
    AddButton2( paramButtons, IDP_SIMPLE, IDP_BMP_G_SIMPLE, !!(tmp.f & SIMPLE), true );
  }

  //   
  if ( IsSpcObjCreate() ) 
  {
    IPropertyCheckBoxPtr checkBox( CreateCheckBox(!!par.flagAttr) );
    if ( checkBox ) 
      InitPropertyControl( checkBox, IDP_SPC_OBJ, IDS_SPC_OBJ_TIPS, IDS_SPC_OBJ_TIPS );
  }

  CreateTab( IDP_ELEMENT_PARAM );
}


//-------------------------------------------------------------------------------------
//  , ,     
// ---
void Shpeel::RedrawPhantom()
{
  if( Changed() )
  {
    //  
    if ( callbackCurrentPhantom )
    {
      SetParam( callbackCurrentPhantom ); 
      callbackCurrentPhantom->Update();
    }
    
    //    
    if ( slideBox ) 
    {
      long slideID    = (long)GetSlideID();
      long slideIDOld = slideBox->DrawingSlide;
      if( slideIDOld != slideID )
      {
        slideBox->DrawingSlide = slideID;
        slideBox->UpdateParam();
      }
    }

    SetChanged( false );
  }
}


//-------------------------------------------------------------------------------------
//  3D 
// ---
void Shpeel::Draw3D( IDocument3DPtr& _doc )  
{
  if ( _doc )
  {
    doc = _doc;
    flagMode = doc->IsEditMode() ;
    callbackCurrentShpeel = this;
    _bstr_t bstr;

    //  
    part = IPartPtr( doc->GetPart( flagMode ? pEdit_Part : pNew_Part ), false/*AddRef*/ );
    if ( part ) 
    {
      //       : par, : Size()
      if ( flagMode )
        GetParam();
      else
      {
        bstr = GetFileName();
        part->SetFileName( bstr );
      }

      IRequestInfoPtr info( doc->GetRequestInfo(part), false/*AddRef*/  );
      if ( info )
      {
        //     
        bstr = LoadStr( flagMode ? STR_SELECT_PLANE : STR_SELECT_POINT );
        info->SetPrompt( bstr );

        SetCallBackAndFilterFunction( info );

#ifndef WITHOUT_PHANTOM_VERSION
        info->CreatePhantom();                        // C 
        callbackCurrentPhantom = IPartPtr( info->GetIPhantom(), false ); //  
        if ( callbackCurrentPhantom )
          SetParam( callbackCurrentPhantom ); 
#endif

        long toolBarID = IDP_STUDS;
        long firstTabID = IDP_STUDS;
        SpecPropertyToolBarEnum toolBarType = pnEnterEscHelp;
        if( InitProcessParam( toolBarID, toolBarType, firstTabID ) )
        {
          procParam->AutoReduce = false;     
          info->SetProcessParam( procParam );            

          if( doc->UserGetPlacementAndEntity(3) ) 
          {
            
             bstr = GetFileName();

            SetParam( part );

            if ( IsCollectionEmpty(info) )   //  placement
            {
              IPlacementPtr place( info->GetPlacement(), false/*AddRef*/ ); 
              part->SetPlacement( place );
              part->UpdatePlacement();       //   
            }
            if ( flagMode || doc->SetPartFromFile( bstr, part, false ) ) 
            {
              if ( IsCollectionChange(info) )  //  Mate' 
              { 
                if ( flagMode )           //  
                  SetMates( info, true ); //  
                SetMates( info );         // C 
              }

              //  ,  
              part->SetStandardComponent( true );
            }

            reference spcObj;
            if ( DrawSpcObj( spcObj ) ) //   
            {                       
              //  
              ksEditWindowSpcObject( spcObj );
            }
          }
          EndProcess();
        }
#ifndef WITHOUT_PHANTOM_VERSION
        callbackCurrentPhantom = NULL;
#endif
      }     
      part = NULL;
    }
    callbackCurrentShpeel = NULL;
  }
  doc = NULL;
}


//------------------------------------------------------------------------------
//  
// ---
bool WINAPI Shpeel::SELECTFILTERPROC( IEntity* entity ) 
{
  bool res = false; //      
  if ( entity && callbackCurrentShpeel )                                  
  {                                 
  	IEntityPtr ePtr( entity );
    IPartPtr entPart( entity->GetParent(), false/*AddRef*/ ); //      
    if ( entPart != callbackCurrentShpeel->GetPart() )  
      //      ,    
      res = IsSurface( ePtr )        || 
            IsSurface( ePtr, false ) || 
            IsAxis( ePtr )           || 
            ePtr->IsIt( o3d_vertex ) ||
            ePtr->IsIt( o3d_pointCS );   
  }                                               
  return res;
}


//------------------------------------------------------------------------------
//   
//  collection ( 0 - , 1 - , 2 -  ) 
// ---
int WINAPI Shpeel::SELECTCALLBACKPROC( IEntity* entity, IRequestInfo* info ) 
{ 
  IEntityCollectionPtr collection( info ? info->GetEntityCollection() : NULL, false/*AddRef*/ );
  IMateConstraintCollectionPtr mateCollection (info ? info->GetMateConstraintCollection() : NULL, false/*AddRef*/);
  //   
  if ( mateCollection )
    mateCollection->Clear();
  if ( entity ) 
  {
    IEntityPtr ePtr( entity );
    if ( collection ) 
    {
      int res = 0;
      if ( IsSurface(ePtr) )
      {
        //        
        IEntityPtr oldPlane( collection->GetByIndex(0), false/*AddRef*/ );
        if ( oldPlane == ePtr )
          collection->SetByIndex( NULL, 0 ); //  
        else
          collection->SetByIndex( ePtr, 0 ); //  
        res = 1;
      }

      double diam;
      if ( IsSurface(ePtr, false, &diam) ) 
      {
        //        
        IEntityPtr oldPlane( collection->GetByIndex(1), false/*AddRef*/ );
        if ( oldPlane == ePtr )
          collection->SetByIndex( NULL, 1 ); //   
        else
        {
          collection->SetByIndex( ePtr, 1 ); //   
          collection->SetByIndex( NULL, 2 ); //  
        }
        res = 1;
      }

      if ( IsAxis(ePtr) ) 
      {
        //        
        IEntityPtr oldAxis( collection->GetByIndex(2), false/*AddRef*/ );
        if ( oldAxis == ePtr )
          collection->SetByIndex( NULL, 2 );  //  
        else
        {
          collection->SetByIndex( ePtr, 2 ); //  
          collection->SetByIndex( NULL, 1 ); //   
        }

        res = 1;
      }

      if ( res && callbackCurrentShpeel )
        callbackCurrentShpeel->GetCollectChanged() = true;

      //    
      info->SetPrompt( _bstr_t( LoadStr(STR_SELECT_PLANE)) );

#ifndef WITHOUT_PHANTOM_VERSION
      //   
      if ( (bool)mateCollection && callbackCurrentShpeel )
      {
        IPartPtr phantom ( info->GetIPhantom(), false/*AddRef*/ );
        if ( phantom )
          AddMates( *callbackCurrentShpeel, collection, phantom, mateCollection );
      }
#endif

      return res;
    }
  }
  else 
  {
  	if ( collection )
    	for ( int i = 0; i < 3; i++ )
        collection->SetByIndex( NULL, i ); // 

    //    
    info->SetPrompt( _bstr_t(LoadStr( STR_SELECT_PLANE )) );

    return 1;
  }

  return 0;
}


//------------------------------------------------------------------------------
//       
// ---
void Shpeel::SetCallBackAndFilterFunction( IRequestInfoPtr& info ) 
{
	info->SetFilterCallBack( SELECTFILTERPROC );
  info->SetCallBack( SELECTCALLBACKPROC );
}



//------------------------------------------------------------------------------
//    -  true    Mate'
// ---
bool Shpeel::IsCollectionChange( IRequestInfoPtr& info ) 
{
  bool res = true;  
  if ( !collectChanged ) //      -  
  {                             
    //         info  NULL'   
    res = false; //   
    IEntityCollectionPtr collection1( info->GetEntityCollection(),      false/*AddRef*/ ); //  
    IEntityCollectionPtr collection2( part->GetMateConstraintObjects(), false/*AddRef*/ ); //  
    if ( (bool)collection1 && (bool)collection2 && 
             ( collection1->GetCount() > 2 ) && 
             ( collection2->GetCount() > 2 ) ) 
    {
      for( int i = 0; i < 3; i++ ) //   
      {                        
        IEntityPtr ent1( collection1->GetByIndex(i), false/*AddRef*/ ); //   1
        IEntityPtr ent2( collection2->GetByIndex(i), false/*AddRef*/ ); //   2
        if ( ent1 != ent2 ) //    
        {                 
          res = true; // 
          break;
        }
      }
    }
  }
  return res; 
}

   
//------------------------------------------------------------------------------
//       
// ---
IEntityPtr Shpeel::GetEntityByName( const TCHAR * name, IPartPtr& p ) 
{
  IEntityPtr entity( NULL );
  if (!(bool)p )
    p = part;
  if ( part ) 
  {
    if ( !(bool)collect )  //    ,       - 
    	collect = IEntityCollectionPtr( p->EntityCollection(o3d_constrElement), false );;

    IEntityPtr findEntity( collect->GetByName( _bstr_t(name), true, true ), false/*AddRef*/ );
//      if ( findEntity ) {
//        IUnknownPtr defin( findEntity->GetDefinition(), false/*AddRef*/ );
//        if ( defin ) {
        entity = findEntity;
//        }
//      }
  }
  return entity;
}


//------------------------------------------------------------------------------
//   -  placement
// ---
bool Shpeel::IsCollectionEmpty( IRequestInfoPtr& info ) 
{
  bool res = true; //  
  IEntityCollectionPtr collection( info->GetEntityCollection(), false/*AddRef*/ ); //  
  if ( collection )
    for( int i = 0, count = collection->GetCount(); i < count; i++ )   //   
    {       
      IEntityPtr entity( collection->GetByIndex(i), false/*AddRef*/ ); //  
      if ( entity )                                       //    NULL
      {                                     
        res = false;                                      //   
        break;                                            //  
      }
    }
  return res; // 
}



















