////////////////////////////////////////////////////////////////////////////////
//
// studs3d.cpp -    Visual C++ - 
//
////////////////////////////////////////////////////////////////////////////////
#ifndef VCL_H
#include <vcl.h>
#endif

#ifndef __WINDOWS_
#include <windows.h>
#endif

#ifndef __STDIO_H
#include <stdio.h>
#endif

#ifndef  __MATH_H
#include <math.h>
#endif

#pragma hdrstop

#include <objbase.h>
#include <initguid.h>

#ifndef __LIBHPPAR_H
#include "libhppar.h"
#endif

#ifndef __STUDS3D_RH
#include "studs3D.rh"
#endif

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

#include "ksConstants.h"

#if !defined(_IFUNC)
# define _IFUNC STDMETHODCALLTYPE
#endif

HINSTANCE _hinst;

//-------------------------------------------------------------------------------
//  
// ---
Shpeel* obj;
static reference spcObj;


//------------------------------------------------------------------------------
//    
// ---
LPTSTR _LoadStr( int id )
{ 
  static char buf[512]; 
  //       
  ksConvertLangStrEx( _hinst, id, buf, 512 );
  return buf;
}


//-------------------------------------------------------------------------------
//   
// ---
extern "C" unsigned int far __export __pascal LibraryId()
{
	return IDR_LIBID;
}


//-------------------------------------------------------------------------------
//   
// ---
extern "C" void far __export __pascal LibraryEntry( unsigned int )
{
  LPDOCUMENT3D pDocument3d = ksGetActive3dDocument(); //       
  if ( pDocument3d && !pDocument3d->IsDetail() )
  {
    Shpeel* shpeel = new Shpeel();
	  if ( shpeel ) 
    {
	  	shpeel->Draw3D( pDocument3d );
			delete shpeel;
		}
    pDocument3d->Release(); //  , AddRef   
  }
  else
  {
    //       3D-
    Error( _LoadStr( STR_3DDOCERROR ) ); //    
  }

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


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


//------------------------------------------------------------------------------
//    ( *.loa)
// ---
static void NumberGost( int gost, int *gNumb, int *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;
  }
}


//------------------------------------------------------------------------------
//    ()
// ---
static int NumberStr( int gost ) 
{
	int n;
  switch ( gost ) 
  {
    case 22032 : n = STR59;	break;
    case 22033 : n = STR60;  break;
    case 22034 : n = STR61;  break;
    case 22035 : n = STR62;  break;
    case 22036 : n = STR63;  break;
    case 22037 : n = STR64;  break;
    case 22038 : n = STR65;  break;
    case 22039 : n = STR66;  break;
    case 22040 : n = STR67;  break;
    case 22041 : n = STR68;  break;
    case 22042 : n = STR69;  break;
    case 22043 : n = STR70;  break;
  }
  return n;
}


//-------------------------------------------------------------------------------
//   
// ---
int _ConnectDB( reference bd, char *name ) 
{
  static char fullName[512];
  bool res = false;
  if( GetModuleFileName( _hinst, fullName, sizeof(fullName) ) )
  {
    char *c = strrchr( fullName, '\\');
    if ( c ) 
    {
      *(c + 1) = '\0';
      strcat( fullName, name );
      OFSTRUCT ofs;
      if ( OpenFile(fullName, &ofs, OF_EXIST) != HFILE_ERROR )
        res = true;
      else 
      {
        *(c + 1) = '\0';
        strcat( fullName, "load\\" );
        strcat( fullName, name );
        if ( OpenFile(fullName , &ofs, OF_EXIST) != HFILE_ERROR )
          res = true;
      }
    }
  }
  return res ? ConnectDB( bd, fullName ) : ConnectDB( bd, name );
}


//------------------------------------------------------------------------------
//     varName  val
// ---
void SetVarValue( IUEnv<IVariableCollection>& varArr, char* varName, double val )
{
  WideString wstr(varName);
	IUEnv<IVariable> var( varArr.GetI()->GetByName( wstr, true, false) ); //  
  if ( var )
    var.GetI()->SetValue( val ); //  
}  


//------------------------------------------------------------------------------
//      ( planar = true - ,
// planar = false -   )
// ---
bool IsSurface( LPENTITY entity, bool planar = true, double * = NULL ) 
{
	bool res = false; 
  if ( entity ) 
  {
    LPUNKNOWN defin = entity->GetDefinition(); 
    if ( defin ) 
    {
			IUPTR(FaceDefinition) faceDef( defin );
      if ( faceDef ) 
      {
        if ( planar && faceDef->IsPlanar() )
          res = true;

        if ( !planar && faceDef->IsCylinder() )
          res = true;
      }
     	defin->Release();
    }
  }
  return res;
} 


//------------------------------------------------------------------------------
//     
// ---
bool IsAxis( LPENTITY 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, LPDOCUMENT3D doc, IUEnv<IEntityCollection>& collection ) 
{
  IUEnv<IEntity> entity( collection.GetI()->GetByIndex(0) );
  if ( entity && IsSurface(entity.GetI()) ) // 
    if ( !doc->AddMateConstraint(mc_Coincidence, entity.GetI(), obj.GetEntityByName("Plane"), obj.GetDirectionElem(), 1, 0) ) 
    {
    	collection.GetI()->SetByIndex( NULL, 0 );
    }

  entity.SetI( collection.GetI()->GetByIndex(1) );
  if ( entity && IsSurface(entity.GetI(), false/*planar*/) ) //  
    if ( !doc->AddMateConstraint(mc_Concentric, entity.GetI(), obj.GetEntityByName("Axis"), 0, 1, 0) ) 
    {
    	collection.GetI()->SetByIndex( NULL, 1 );
    }

  entity.SetI( collection.GetI()->GetByIndex(2) );
  if ( entity && IsAxis(entity.GetI()) ) // 
    if ( !doc->AddMateConstraint(mc_Concentric, entity.GetI(), obj.GetEntityByName("Axis"), 0, 1, 0) ) 
    {
    	collection.GetI()->SetByIndex( NULL, 2 );
    }
}

//------------------------------------------------------------------------------
//  
// ---
void DelMates( Shpeel& obj, LPDOCUMENT3D doc, IUEnv<IEntityCollection>& collection ) 
{
  IUEnv<IEntity> entity( collection.GetI()->GetByIndex(0) );
  if ( entity && IsSurface(entity.GetI()) ) // 
    doc->RemoveMateConstraint( mc_Coincidence, entity.GetI(), obj.GetEntityByName("Plane") );

  entity.SetI( collection.GetI()->GetByIndex(1) );
  if ( entity && IsSurface(entity.GetI(), false /*planar*/) ) //  
    doc->RemoveMateConstraint( mc_Concentric, entity.GetI(), obj.GetEntityByName("Axis") );

  entity.SetI( collection.GetI()->GetByIndex(2) );
  if ( entity && IsAxis(entity.GetI()) ) // 
    doc->RemoveMateConstraint( mc_Concentric, entity.GetI(), obj.GetEntityByName("Axis") );
}

 
//------------------------------------------------------------------------------
//    
// ---
int Shpeel::ReadShpeelBase( float d )
{
  char buf[128];
  ::sprintf( buf, "t = 1 and d=%.1f", d );
  if ( !::Condition(bBase.bg,  bBase.rg2, buf) ) { return 0;}

  ShpeelTmp shpeelTmp;
  int rez = ::ReadRecord( bBase.bg, bBase.rg2, &shpeelTmp );
  if( rez ) 
  {
    tmp.d  = shpeelTmp.d;  //  
    tmp.p1 = shpeelTmp.p1; //  
    tmp.p2 = shpeelTmp.p2; //  
    tmp.b1 = shpeelTmp.b1; //  
    tmp.c  = shpeelTmp.c;  //  
  }
  return  rez;
}


//------------------------------------------------------------------------------
//   
//  1 -  0 -    -1 -    
// ---
int Shpeel::ReadShpeelStBase()
{
  char buf[128];
  ::sprintf( buf, "t = 1 && L=%.1f & d=%.1f", tmp.l, tmp.d );
  if ( !::Condition(bBase.bs, bBase.rs2, buf) ) { return -1;}

  ShpeelSTmp shpeelSTmp;
  int i = ::ReadRecord( bBase.bs, bBase.rs2, &shpeelSTmp );
  if ( !i )  
  {
    ::sprintf( buf, "t = 1 and d=%.1f", tmp.d);
    if ( !::Condition(bBase.bs,  bBase.rs2, buf) ) { return -1;}

    ::ReadRecord( bBase.bs, bBase.rs2, &shpeelSTmp );
  }

  tmp.l  = shpeelSTmp.l;
  tmp.b  = shpeelSTmp.b;
  tmp.m1 = shpeelSTmp.m1;
  tmp.m2 = shpeelSTmp.m2;
  if ( tmp.gost > 22041 )
  {
    if ( fabs(tmp.b) > 0.001 )
    {
      tmp.f &=~ ALLST;
    }
    else 
    {
      tmp.f |= ALLST;
    }
  } 
  return 1;
}


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

  int gNumb, stNumb;
  ::NumberGost( 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 );
        ::RInt  ("t");
        ::RChar( "d", 20, 0 );
      ::EndRelation();
      if ( !::DoStatement(bBase.bg, bBase.rg1, "1 2" ) ) 
        return 0;
      else 
      {
        bBase.rg2 = ::Relation( bBase.bg );
          ::RInt  ("t");
          ::RFloat("d");
          ::RFloat("");
          ::RFloat("");
          ::RFloat("");
          ::RFloat("");
        ::EndRelation();
        if ( !::DoStatement( bBase.bg, bBase.rg2, "") )
          return 0;
        else 
        {
          bBase.rs1 = ::Relation( bBase.bs );
            ::RInt ( "t" );
            ::RChar( "L",20,0 );
            ::RFloat( "d" );
          ::EndRelation();
          if ( !::DoStatement(bBase.bs, bBase.rs1, "1 2 3" ) )
            return 0;
          else 
          {
            bBase.rs2 = ::Relation( bBase.bs );
              ::RInt ("t");
              ::RFloat("L");
              ::RFloat("d");
              ::RFloat("");
              ::RFloat("");
              ::RFloat("");
            ::EndRelation();
            if ( !::DoStatement( bBase.bs, bBase.rs2, "") )
              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 ),
                   openBase      ( false )
{
  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( const Shpeel& other ) : part    ( NULL  ),
                                        collect ( NULL  ),
                                        collectChanged( 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.SetI( other.collect.GetI() );

  if ( other.collect.GetI() )
    other.collect.GetI()->AddRef();

  ::memcpy( &tmp, &other.tmp, sizeof(SHPEEL) );
}


//------------------------------------------------------------------------------
// 
// ---
void Shpeel::Init() 
{
  tmp.gost       = (unsigned short)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;
  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;
}


//------------------------------------------------------------------------------
//                
// ---
String& Shpeel::SetFileName()
{
  static char fullName[512];
  bool res = false;
  if( GetModuleFileName( _hinst, fullName, sizeof(fullName) ) )
  {
    char *c = strrchr( fullName, '\\');
    if ( c ) 
    {
      *(c + 1) = '\0';
      strcat( fullName, STUDS_FILE );
      OFSTRUCT ofs;
      if ( OpenFile(fullName, &ofs, OF_EXIST) != HFILE_ERROR )
        res = true;
      else 
      {
        *(c + 1) = '\0';
        strcat( fullName, "model\\" );
        strcat( fullName, STUDS_FILE );
        if ( OpenFile(fullName , &ofs, OF_EXIST) != HFILE_ERROR )
          res = true;
      }
    }
  }

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


//------------------------------------------------------------------------------
//  
// ---
void Shpeel::SetParam() 
{
  //   
  if( part ) 
  {
    //    
    IUEnv<IVariableCollection> varArr( part->VariableCollection() );
    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) < 0.001 ) //  22042,  22043
      { 
        if( fabs(tmp.b) > 0.001 ) 
          b1 = b;
      }
      else 
      {
        b1 = tmp.b1;
        if ( fabs(tmp.b) < 0.001  )
          b = tmp.l - 0.5f * tmp.d - 2 * step;
      }
      
      //  
    	::SetVarValue( varArr, "d",      tmp.d                        ); //  
      float len = fabs(b1 - b) < 0.001 ? tmp.l - b1 : tmp.l;
    	::SetVarValue( varArr, "l",      len                          ); //  
    	::SetVarValue( varArr, "b1",     b1                           ); //   
    	::SetVarValue( varArr, "c1",     tmp.c                        ); //     
      if ( fabs(l - b1 - b) > 0.001 )
	    	::SetVarValue( varArr, "l1",   l - b1 - b                   ); //    
    	::SetVarValue( varArr, "t",      (step * 0.866 * 3 / 8)       ); //   
      int perf2 = ( !(tmp.f & ISPOLN) ) || ( tmp.f & ALLST ) || ( fabs(l - b1 - b) < 0.001 ) ? 1 : 0;
    	::SetVarValue( varArr, "cut1",   perf2                        ); // /  2
    	::SetVarValue( varArr, "f1",     !(tmp.f & SIMPLE) ? 0.0 /**/ : 1.0 /**/ ); // / 

      //   
      char buf[255];
      ::sprintf( buf, _LoadStr( STR_STUD_NAME ), tmp.d, tmp.l, tmp.gost ); //   
      WideString wstr(buf);
      part->SetName( wstr ); //    
      part->Update();        //  

      //      
      part->RebuildModel();
    }

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


//------------------------------------------------------------------------------
//  
// ---
int Shpeel::ChoiceMenuId() 
{

  switch ( par.drawType )
  {
    case ID_VID    : // 
      return  !par.typeSwitch ?  MENU_22032_1 : MENU_22032_3;
    case ID_TOPVID : //  
      return  !par.typeSwitch ?  MENU_22032_2 : MENU_22032_4;
  }

  return 0;
}


//------------------------------------------------------------------------------
//   
// ---
reference Shpeel::EditSpcObj( reference spcObj )
{
  IUPTR( Specification3D ) specification( doc->GetSpecification() );
  if ( !flagMode && !par.flagAttr && !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;
    massa = massa*( !tmp.indexMassa ? 1 : tmp.indexMassa==1 ? 0.356f : tmp.indexMassa==3 ? 0.97f : 1.08f )/COUNT_MASSA;

    char buf[128];
    sprintf( buf, "%f" , massa );
    ksSpcMassa ( buf ); //  

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

    return ::ksSpcObjectEnd();
  }
  return 0;
}


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

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



//-------------------------------------------------------------------------------------
//  3D 
// ---
void Shpeel::Draw3D( LPDOCUMENT3D _doc )
{
  if ( _doc )
  {
    doc = _doc;
    flagMode = doc->IsEditMode() ;
    obj = this;

    //  
    part = doc->GetPart( flagMode ? pEdit_Part : pNew_Part );
    if ( part ) 
    {
      //       
      if ( flagMode )
        GetParam();

      if ( obj->MacroElementParam()== IDOK )
      {
        IUEnv<IRequestInfo> info( doc->GetRequestInfo(part) );
        if ( info )
        {
          //    
          WideString wstr( _LoadStr( flagMode ? STR_SELECT_PLANE : STR_SELECT_POINT ) );
          info->SetPrompt( wstr );
          SetCallBackAndFilterFunction( info );
          if ( doc->UserGetPlacementAndEntity(3) )
          {
            part->SetPlacement( info->GetPlacement() );
            wstr = obj->SetFileName();
            //  ,  
            part->SetStandardComponent( true );
            SetParam();

            if ( IsCollectionEmpty(info) )   //  placement
              part->UpdatePlacement();       //   
            if ( flagMode || doc->SetPartFromFile( wstr, part, false ) )
            {
              if ( IsCollectionChange(info) )  //  Mate' 
              {
                if ( flagMode )                //  
                  SetMates( doc, info, true ); //  
                SetMates( doc, info );         // C 
              }
            }
						DrawSpcObj(); //   

            if ( spcObj ) //   
            {
              //  
             	::ksEditWindowSpcObject( spcObj );
              spcObj = 0;
            }
          }
        }
      }
      part->Release();
    }
  }
}


//------------------------------------------------------------------------------
//  
// ---
bool WINAPI SELECTFILTERPROC( LPENTITY entity ) 
{
  bool res = false; //      
  if ( entity )                                  
  {                                 
  	IUEnv<IPart> entPart( entity->GetParent() ); //      
    if ( entPart.GetI() != obj->GetPart() )  
      //      ,    
      res = IsSurface( entity ) || 
            IsSurface( entity, false /*planar*/ ) || 
            IsAxis( entity );   
  }                                               
  return res;
}


//------------------------------------------------------------------------------
//   
//  collection ( 0 - , 1 - , 2 -  ) 
// ---
int WINAPI SELECTCALLBACKPROC( LPENTITY entity, LPREQUESTINFO info ) 
{
  IUEnv<IEntityCollection> collection( info ? info->GetEntityCollection() : NULL );

  if ( entity && info )
  {
    if ( collection ) 
    {
      int res = 0;
      if ( IsSurface(entity) ) 
      {
        //        
        IUEnv<IEntity> oldPlane( collection->GetByIndex(0) );
        if ( oldPlane.GetI() == entity )
          collection->SetByIndex( NULL,   0 ); //  
        else
          collection->SetByIndex( entity, 0 ); //  

        res = 1;
      }

      double diam;
      if ( IsSurface(entity, false /*planar*/, &diam) )
      {
        //        
        IUEnv<IEntity> oldPlane( collection->GetByIndex(1) );
        if ( oldPlane.GetI() == entity )
          collection->SetByIndex( NULL,   1 ); //   
        else
        {
          collection->SetByIndex( entity, 1 ); //   
          collection->SetByIndex( NULL,   2 ); //  
        }       
        res = 1;
      }

      if ( IsAxis(entity) ) 
      {
        //        
        IUEnv<IEntity> oldAxis( collection->GetByIndex(2) );
        if ( oldAxis.GetI() == entity )
          collection->SetByIndex( NULL,   2 ); //  
        else
        {
          collection->SetByIndex( entity, 2 ); //  
          collection->SetByIndex( NULL,   1 ); //   
        }
        res = 1;
      }

      
      if ( res )
        obj->GetCollectChanged() = true;
      //    
      WideString wstr( _LoadStr( STR_SELECT_PLANE ) );
      info->SetPrompt( wstr );
      
      return res;
    }
  }
  else 
  {
  	if ( collection )
    {
      for ( int i = 0; i < 3; i++ )
        collection->SetByIndex( NULL, i ); // 
      //    
      WideString wstr( _LoadStr( STR_SELECT_PLANE ) );
      info->SetPrompt( wstr );
    }
    return 1;
  }
  return 0;
}


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


//------------------------------------------------------------------------------
//    -  true    Mate'
// ---
bool Shpeel::IsCollectionChange( IUEnv<IRequestInfo>& info ) 
{
  bool res = true;  
  if ( !collectChanged ) //      -  
  {                             
    //         info  NULL'   
    res = false; //   
    IUEnv<IEntityCollection> collection1( info.GetI()->GetEntityCollection() ); //  
    IUEnv<IEntityCollection> collection2( part->GetMateConstraintObjects()  );  //  
    if ( collection1 && collection2 && 
         ( collection1->GetCount() > 2 ) && 
         ( collection2->GetCount() > 2 ) ) 
    {
      for( int i = 0; i < 3; i++ ) //   
      {                        
        IUEnv<IEntity> ent1( collection1->GetByIndex(i) ); //   1
        IUEnv<IEntity> ent2( collection2->GetByIndex(i) ); //   2
        if ( ent1.GetI() != ent2.GetI() ) //    
        {                 
          res = true; // 
          break;
        }
      }
    }
  }
  return res; 
}



//------------------------------------------------------------------------------
//  
// ---
void Shpeel::SetMates( LPDOCUMENT3D doc, IUEnv<IRequestInfo>& info, bool delMates ) 
{
  IUEnv<IEntityCollection> collection( !delMates ? info.GetI()->GetEntityCollection() : part->GetMateConstraintObjects() );
  if ( collection ) 
  {
    if ( doc && collection.GetI()->GetCount() > 2 )
	    if ( !delMates )
  	  	::AddMates( *this, doc, collection );
      else
  	  	::DelMates( *this, doc, collection );

    if ( !delMates )
	    part->SetMateConstraintObjects( collection.GetI() );
  }
}

   
//------------------------------------------------------------------------------
//       
// ---
LPENTITY Shpeel::GetEntityByName( const char * name ) 
{
  LPENTITY entity = NULL;
  if ( part ) 
  {
    if ( !collect )  //    ,       - 
    	collect.SetI( part->EntityCollection(o3d_constrElement) );

    WideString wstr(name);
    LPENTITY findEntity = collect->GetByName( wstr, true, true );
    if ( findEntity ) 
    {
      LPUNKNOWN defin = findEntity->GetDefinition();
      if ( defin ) 
      {
        entity = findEntity;
        defin->Release();
      }
      if ( !entity )
        findEntity->Release();
    }
  }
  return entity;
}


//------------------------------------------------------------------------------
//   -  placement
// ---
bool Shpeel::IsCollectionEmpty( IUEnv<IRequestInfo>& info ) 
{
  bool res = true; //  
  IUEnv<IEntityCollection> collection( info.GetI()->GetEntityCollection() ); //  
  if ( collection )
    for( int i = 0, count = collection->GetCount(); i < count; i++ ) //   
    {       
      IUEnv<IEntity> entity( collection->GetByIndex(i) ); //  
      if ( entity )                                       //    NULL
      {                                     
        res = false;                                      //   
        break;                                            //  
      }
    }
  return res; // 
}



















