// studs3d.cpp : Defines the initialization routines for the DLL.
//

#include "stdafx.h"
#include "studs3d.h"
#include <math.h>

#include <ksConstants.h>

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

//
//	Note!
//
//		If this DLL is dynamically linked against the MFC
//		DLLs, any functions exported from this DLL which
//		call into MFC must have the AFX_MANAGE_STATE macro
//		added at the very beginning of the function.
//
//		For example:
//
//		extern "C" BOOL PASCAL EXPORT ExportedFunction()
//		{
//			AFX_MANAGE_STATE(AfxGetStaticModuleState());
//			// normal function body here
//		}
//
//		It is very important that this macro appear in each
//		function, prior to any calls into MFC.  This means that
//		it must appear as the first statement within the 
//		function, even before any object variable declarations
//		as their constructors may generate calls into the MFC
//		DLL.
//
//		Please see MFC Technical Notes 33 and 58 for additional
//		details.
//

/////////////////////////////////////////////////////////////////////////////
// CStuds3dApp

BEGIN_MESSAGE_MAP(CStuds3dApp, CWinApp)
	//{{AFX_MSG_MAP(CStuds3dApp)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CStuds3dApp construction

CStuds3dApp::CStuds3dApp()
{
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CStuds3dApp object

CStuds3dApp theApp;

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

//-------------------------------------------------------------------------------
//
// ---
char * WINAPI LIBRARYNAME(){
	return "   Visual C++";
}

KompasObject kompas( NULL );
Shpeel* obj;

#define  MAX_COUNT_SPCOBJ 4     //      4
static reference spcObj[MAX_COUNT_SPCOBJ];

#define STANDART_SECTION     25
#define SPC_NAME       			 5           // 

#define EPSILON    0.001
#define STUDS_FILE "stud.l3d||_1"


//-------------------------------------------------------------------------------
//
// ---
void GetKompas() 
{
	if ( !kompas.m_lpDispatch ) 
  {
		CString filename;
		if( ::GetModuleFileName(NULL, filename.GetBuffer(255), 255) ) 
    {
			filename.ReleaseBuffer( 255 );
			CString libname;

      #ifdef __LIGHT_VERSION__
        libname.LoadString( IDS_STRING5 );  //klAPI5.dll
      #else
        libname.LoadString( IDS_STRING4 );  //kAPI5.dll
      #endif

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

			HINSTANCE hAppAuto = LoadLibrary( filename ); //  kAPI5.dll
			if(  hAppAuto ) 
      {
				typedef LPDISPATCH ( WINAPI *FCreateKompasObject )(); 
				FCreateKompasObject pCreateKompasObject = 
					(FCreateKompasObject)GetProcAddress( hAppAuto, "CreateKompasObject" );	
				if ( pCreateKompasObject ) 
					kompas = pCreateKompasObject();
				FreeLibrary( hAppAuto );
			}
		}
	}
}

//-------------------------------------------------------------------------------
//
// ---
void WINAPI LIBRARYENTRY( unsigned int ) {
	//      .exe ,     
	//   dll   define
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	GetKompas();
	if ( kompas.m_lpDispatch ) {
		Shpeel* par = new Shpeel();
		if ( par ) {
			//        GetMacroParam
			kompas.ksResultNULL();
			ksDocument3D doc( kompas.ActiveDocument3D() );
			if ( doc.m_lpDispatch && !doc.IsDetail() ) 
	  		par->Draw3D( doc );
			else {
				CString mess;
				mess.LoadString( IDS_3DDOCERROR ); //     
				kompas.ksError( mess );            //    
			}
			delete par;
		}
		if ( kompas.ksReturnResult() == etError10 )    //  10  "!  "
			kompas.ksResultNULL();
	}
}


////////////////////////////////////////////////////////////////////////////////
//
//  
//
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
//     : planar = true - ,
// false -  
// ---
bool IsSurface( ksEntity& entity, bool planar = true )
{
	bool res = false;
  if ( entity.m_lpDispatch ) 
  {
    if ( entity.IsIt(o3d_face) ) 
    {
			ksFaceDefinition faceDef( entity.GetDefinition() );
      if ( faceDef.m_lpDispatch ) 
      {
        if ( planar && faceDef.IsPlanar() )
          res = true;

        if ( !planar && faceDef.IsCylinder() ) 
          res = true;
      }
    }
  }
  return res;
}

//------------------------------------------------------------------------------
//     
// ---
bool IsAxis( ksEntity& entity ) {
  if ( entity.m_lpDispatch ) {
  	return entity.IsIt( o3d_axis2Planes )        ||  //    
    				 entity.IsIt( o3d_axisOperation )    ||  //  
            	 entity.IsIt( o3d_axis2Points )    ||  //    
                 entity.IsIt( o3d_axisConeFace ) ||  //   
                 	 entity.IsIt( o3d_axisEdge );      //   
  }
  return false;
}


//------------------------------------------------------------------------------
//  
// ---
bool WINAPI SELECTFILTERPROC( LPDISPATCH _entity ) 
{
  bool res = false;  
  if ( _entity ) 
  {                                    
		ksEntity entity( _entity );
		if ( entity.m_lpDispatch ) 
    {
  		ksPart entPart( entity.GetParent() ); //   
			if ( entPart != obj->GetPart() )      //   
				res = ::IsSurface( entity ) || 
              ::IsSurface( entity, false ) ||
							::IsAxis( entity );           //     
  	                                        // ,    
    }                                               
    // 
    entity.DetachDispatch();
	}

  return res;
}


//------------------------------------------------------------------------------
//   
// 0 - , 1 - , 2 -  -  collection
// ---
int WINAPI SELECTCALLBACKPROC( LPDISPATCH _entity, LPDISPATCH _info ) 
{
  int res = 0;
	ksEntity entity( _entity );   
	ksRequestInfo3D info( _info );

	if ( info ) 
  {
    ksEntityCollection collection( info.GetEntityCollection() );
    if ( entity )
    {
  	  if ( collection ) 
      {
			  if ( ::IsSurface(entity) ) 
        {
          //        
          ksEntity oldPlane( collection.GetByIndex(0) );
          if ( oldPlane == entity )
            collection.SetByIndex( NULL, 0 );   //  
          else
            collection.SetByIndex( entity, 0 ); //  
				  res = 1;
			  }
        else if ( ::IsSurface( entity, false ) ) 
        {
          //        
          ksEntity oldPlane( collection.GetByIndex(1) );
          if ( oldPlane == entity )
            collection.SetByIndex( NULL,   1 ); //   
          else
          {
            collection.SetByIndex( entity, 1 ); //   
            collection.SetByIndex( NULL,   2 ); //  
          }
				  res = 1;
			  }
  		  else if ( ::IsAxis(entity) ) 
        {
          //        
          ksEntity oldAxis( collection.GetByIndex(2) );
          if ( oldAxis == entity )
            collection.SetByIndex( NULL, 2 );   //  
          else
          {
            collection.SetByIndex( entity, 2 ); //  
            collection.SetByIndex( NULL,   1 ); //   
          }

				  res = 1;
			  }

			  if ( res )
				  obj->GetCollectChanged() = true;

			  CString mes;
			  mes.LoadString( STR_SELECT_PLANE ); //    
			  info.SetPrompt( mes );

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

			  CString mes;
			  mes.LoadString( STR_SELECT_PLANE ); //    
			  info.SetPrompt( mes ); 
			  res = 1;
    }
	}

  // 
  info.DetachDispatch();
  entity.DetachDispatch();

  return res;
}


//------------------------------------------------------------------------------
//  
// ---
void AddMates( Shpeel& object, ksDocument3D& doc, ksEntityCollection& collection ) {
  ksEntity ent( collection.GetByIndex(0) );
  if ( ent.m_lpDispatch && ::IsSurface(ent) ) {                   // 
		ksEntity partObj( NULL );
		object.GetEntityByName( "Plane", partObj );
    if ( !doc.AddMateConstraint(mc_Coincidence, ent, partObj,
    			object.GetDirectionElem(), 1, 0) ) {
    	collection.SetByIndex( NULL, 0 );
    }
	}

  ent = collection.GetByIndex( 1 ); //    =
//  ent.AttachDispatch( collection.GetByIndex(1) );  , ..  ASSERT(m_lpDispatch != NULL)
  if ( ent.m_lpDispatch && ::IsSurface(ent, false/*planar*/) ) {  //  
		ksEntity partObj( NULL );
		object.GetEntityByName("Axis", partObj );
    if ( !doc.AddMateConstraint(mc_Concentric, ent, partObj,
    			0, 1, 0) ) {
    	collection.SetByIndex( NULL, 1 );
    }
	}

  ent = collection.GetByIndex( 2 ); //    =
  if ( ent.m_lpDispatch && ::IsAxis(ent) ) {                      // 
		ksEntity partObj( NULL );
		object.GetEntityByName("Axis", partObj );
    if ( !doc.AddMateConstraint(mc_Concentric, ent, partObj,
    			0, 1, 0) ) {
    	collection.SetByIndex( NULL, 2 );
    }
	}
}

//------------------------------------------------------------------------------
//  
// ---
void DelMates( Shpeel& object, ksDocument3D& doc, ksEntityCollection& collection ) {
  ksEntity ent( collection.GetByIndex(0) );
  if ( ent.m_lpDispatch && ::IsSurface(ent) ) {                   // 
		ksEntity partObj( NULL );
		object.GetEntityByName("Plane", partObj );
    doc.RemoveMateConstraint( mc_Coincidence, ent, partObj );
	}

  ent = collection.GetByIndex( 1 ); //    =
//  ent.AttachDispatch( collection.GetByIndex(1) );  , ..  ASSERT(m_lpDispatch != NULL)
  if ( ent.m_lpDispatch && ::IsSurface(ent, false/*planar*/) ) {  //  
		ksEntity partObj( NULL );
		object.GetEntityByName("Axis", partObj );
    doc.RemoveMateConstraint( mc_Concentric, ent, partObj );
	}

  ent = collection.GetByIndex( 2 ); //    =
//  ent.AttachDispatch( collection.GetByIndex(2) );  , ..  ASSERT(m_lpDispatch != NULL)
  if ( ent.m_lpDispatch && ::IsAxis(ent) ) {                      // 
		ksEntity partObj( NULL );
		object.GetEntityByName("Axis", partObj );
    doc.RemoveMateConstraint( mc_Concentric, ent, partObj );
	}
}

//------------------------------------------------------------------------------
//       
// ---
void SetCallBackAndFilterFunction( ksRequestInfo3D& info ) {
	info.SetFilterCallBack( "SELECTFILTERPROC",   (long)theApp.m_hInstance, 0 );
  info.SetCallBack      ( "SELECTCALLBACKPROC", (long)theApp.m_hInstance, 0 );
}


////////////////////////////////////////////////////////////////////////////////
//
//   - 
//
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
// 
// ---
Shpeel::Shpeel()  
  : part        ( NULL  ),
	doc           ( NULL  ),
	specification ( NULL  ),
  collect       ( NULL  ),
	param    ( kompas.GetParamStruct(ko_UserParam) ),
	paramTmp ( kompas.GetParamStruct(ko_UserParam) ),
	paramSTmp( kompas.GetParamStruct(ko_UserParam) ),
	data     ( kompas.DataBaseObject()             ),
  collectChanged( false ) {
  par.flagAttr    = 1;
  par.typeSwitch  = 0;
  par.ang         = 0;
  par.drawType    = ID_VID;
  countObj        = 1;

	InitUserParam();

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

//------------------------------------------------------------------------------
//
// ---
void Shpeel::Init() {
  tmp.gost       = (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         = (float)245.9;
  tmp.m2         = (float)228.9;
}

//------------------------------------------------------------------------------
//  
// ---
Shpeel::Shpeel( const Shpeel& other ) 
	: param    ( kompas.GetParamStruct(ko_UserParam) ),
		paramTmp ( kompas.GetParamStruct(ko_UserParam) ),
		paramSTmp( kompas.GetParamStruct(ko_UserParam) ),
//	  part     ( other.part.m_lpDispatch             ),
		collect  ( NULL                                ),
		data     ( kompas.DataBaseObject()                ) {
//	if ( other.collect.m_lpDispatch )
//		collect.AttachDispatch( other.collect.m_lpDispatch, FALSE );
	openBase = false;
  ::memcpy( &base, &other.base, sizeof(ShpeelBase) );
  Assign( other );
	InitUserParam();
}

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

//------------------------------------------------------------------------------
//
// ---
void Shpeel::Assign( const Shpeel& other ) {
  collectChanged = other.collectChanged; // true -  
  countObj       = other.countObj;
  flagMode       = other.flagMode;
  par            = other.par;
	fileName       = other.fileName;
  ::memcpy( &tmp, &other.tmp, sizeof(SHPEEL) );
}

//-------------------------------------------------------------------------------------
//
//-------------------------------------------------------------------------------------
void Shpeel::_MessageBoxResult() {
  if ( kompas.ksReturnResult() ) {
    if ( kompas.ksReturnResult() == etError10 )    //  10  "!  "
      kompas.ksResultNULL();
    else
      kompas.ksMessageBoxResult();
  }
}

/*
struct ShpeelTmp {
  short t;   //     
  float d;   //  
  float p1;  //  
  float p2;  //  
  float b1;  //  
  float c;   //  
};
    lpShpeel->d  = shpeelTmp.d;    //  
    lpShpeel->p1 = shpeelTmp.p1;   //   
    lpShpeel->p2 = shpeelTmp.p2;   //   
    lpShpeel->b1 = shpeelTmp.b1;   //  
    lpShpeel->c  = shpeelTmp.c;    //   
*/
//-------------------------------------------------------------------------------
//
// ---
void Shpeel::InitUserParamTmp() {
	if ( paramTmp.m_lpDispatch ) {
		ksLtVariant			item( kompas.GetParamStruct(ko_LtVariant) );
		ksDynamicArray	arr	( kompas.GetDynamicArray(LTVARIANT_ARR) );
		if ( item.m_lpDispatch && arr.m_lpDispatch ) {
			paramTmp.Init();
			paramTmp.SetUserArray( arr );
			item.Init();
			item.SetShortVal( 0 );            // 0 - t
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.d );        // 1 - d
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.p1 );       // 2 - p1
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.p2 );       // 3 - p2
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.b1 );       // 4 - b1
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.c );        // 5 - c
			arr.ksAddArrayItem( -1, item );
		}
	}
}

//-------------------------------------------------------------------------------
//
// ---
void Shpeel::GetUserParamTmp() {
	if ( paramTmp.m_lpDispatch ) {
		ksLtVariant			item ( kompas.GetParamStruct(ko_LtVariant) );
		ksLtVariant			item1( kompas.GetParamStruct(ko_LtVariant) );
		ksDynamicArray	arr	 ( paramTmp.GetUserArray() );
		if ( item.m_lpDispatch && item1.m_lpDispatch && arr.m_lpDispatch 
					&& arr.ksGetArrayCount() >= 6 ) {
			item.Init();
			arr.ksGetArrayItem( 1, item ); // d
			tmp.d = item.GetFloatVal();
			arr.ksGetArrayItem( 2, item ); // p1
			tmp.p1 = item.GetFloatVal();
			arr.ksGetArrayItem( 3, item ); // p2
			tmp.p2 = item.GetFloatVal();
			arr.ksGetArrayItem( 4, item ); // b1
			tmp.b1 = item.GetFloatVal();
			arr.ksGetArrayItem( 5, item ); // c
			tmp.c = item.GetFloatVal();
		}
	}
}

/*
struct ShpeelSTmp {
  short t;   //     
  float l;   //  
  float d;   //  
  float b;   //  
  float m1;  //   1
  float m2;  //   2
};
lpShpeel->d
  lpShpeel->l  = shpeelSTmp.l;
  lpShpeel->b  = shpeelSTmp.b;
  lpShpeel->m1 = shpeelSTmp.m1;
  lpShpeel->m2 = shpeelSTmp.m2;
*/
//-------------------------------------------------------------------------------
//
// ---
void Shpeel::InitUserParamSTmp() {
	if ( paramSTmp.m_lpDispatch ) {
		ksLtVariant			item( kompas.GetParamStruct(ko_LtVariant) );
		ksDynamicArray	arr	( kompas.GetDynamicArray(LTVARIANT_ARR) );
		if ( item.m_lpDispatch && arr.m_lpDispatch ) {
			paramSTmp.Init();
			paramSTmp.SetUserArray( arr );
			item.Init();
			item.SetShortVal( 0 );            // 0 - t
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.l );        // 1 - l
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.d );        // 2 - d
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.b );        // 3 - b
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.m1 );       // 4 - m1
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.m2 );       // 5 - m2
			arr.ksAddArrayItem( -1, item );
		}
	}
}

//-------------------------------------------------------------------------------
//
// ---
void Shpeel::GetUserParamSTmp() {
	if ( paramSTmp.m_lpDispatch ) {
		ksLtVariant			item ( kompas.GetParamStruct(ko_LtVariant) );
		ksDynamicArray	arr	 ( paramSTmp.GetUserArray() );
		if ( item.m_lpDispatch && arr.m_lpDispatch 
					&& arr.ksGetArrayCount() >= 6 ) {
			item.Init();
			arr.ksGetArrayItem( 1, item ); // l
			tmp.l = item.GetFloatVal();
			arr.ksGetArrayItem( 2, item ); // d
			tmp.d = item.GetFloatVal();
			arr.ksGetArrayItem( 3, item ); // s
			tmp.b = item.GetFloatVal();
			arr.ksGetArrayItem( 4, item ); // m1
			tmp.m1 = item.GetFloatVal();
			arr.ksGetArrayItem( 5, item ); // m2
			tmp.m2 = item.GetFloatVal();
		}
		if ( tmp.gost > 22041 ) {
			if ( ::fabs(tmp.b) > 0.001 ) 
				tmp.f &=~ ALLST;
			else 
				tmp.f |= ALLST;
		}
	}
}

//------------------------------------------------------------------------------
//
// ---
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 GetFullName( char *name, char *fName  ) {
	CString bufName( name );    //      
	CString path;               //    
	CString modelName;          //     - 
  bool rez = false;           // 
  if( ::GetModuleFileName(theApp.m_hInstance, fName, 255) ) { //    rtw
		int ind   = bufName.Find( '|' ); //    . -           
		if ( ind > 0 )                   //    -    -  
			modelName = bufName.Right( bufName.GetLength() - ind );

		CString fileName( ind > 0 ? bufName.Left(ind) : bufName ); //    
		if ( !fileName.IsEmpty() ) {
			char *c = ::strrchr( fName, '\\'); //   rtw     
			if ( c ) {
				*(c + 1) = '\0';                 //    rtw
				path  = fName;                   //    
				path += fileName;

				OFSTRUCT ofs;
				if ( ::OpenFile(path, &ofs, OF_EXIST) != HFILE_ERROR ) //  
					rez = true;                    //  
				else {                           //   
					*(c + 1) = '\0';               //   
					path = fName;                  //     LOAD
					path += "LOAD\\";
					path += fileName;
					if ( ::OpenFile(path, &ofs, OF_EXIST) != HFILE_ERROR ) //  
						rez = true;                  //  
				}
			}
		}
	}
	if ( rez ) {                           //  
		::strcpy( fName, path );             //   
		::strcat( fName, modelName );
	}
	return rez;
}

//---------------------------------------------------------------------------
//
//---------------------------------------------------------------------------
int Shpeel::_ConnectDB( reference bd, char *name ) {
	char buf[255];
  return ::GetFullName( name, buf ) ? data.ksConnectDB( bd, buf  ) 
																		: data.ksConnectDB( bd, name );
}

//------------------------------------------------------------------------------
//       
// ---
bool Shpeel::OpenBase( bool initParam ) {
	//      .exe ,     
	//   dll   define
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	if ( initParam ) {
		InitUserParamTmp();
		InitUserParamSTmp();
	}

	if ( data.m_lpDispatch ) {
		CString buf;
		buf.LoadString( BASE_STR1 ); //
		base.bg = data.ksCreateDB( buf );   // TXT_DB
		base.bs = data.ksCreateDB( buf );   // TXT_DB

		int gNumb, stNumb;
		::NumberGost( tmp.gost, &gNumb, &stNumb );

		buf.LoadString( gNumb ); //
		if( _ConnectDB(base.bg, buf.GetBuffer(buf.GetLength())) ) { //"22032.loa"
			buf.LoadString( stNumb ); //
			if( _ConnectDB(base.bs, buf.GetBuffer(buf.GetLength())) ) { //"st22032.loa"
				buf.LoadString( STR_241 ); //
				base.rg1 = data.ksRelation( base.bg );
					data.ksRInt ( "t" );
					data.ksRChar( "d", 20, 0 );
				data.ksEndRelation();
				if ( data.ksDoStatement(base.bg, base.rg1, buf) ) { //"1"
					base.rg2 = data.ksRelation( base.bg );
						data.ksRInt  ( "t" );
						data.ksRFloat( "d" );
						data.ksRFloat( "" );
						data.ksRFloat( "" );
						data.ksRFloat( "" );
						data.ksRFloat( "" );
					data.ksEndRelation();
					if ( data.ksDoStatement(base.bg, base.rg2, "") ) { //TXT_ALL
						buf.LoadString( STR_243 ); //
						base.rs1 = data.ksRelation( base.bs );
							data.ksRInt  ( "t" );
							data.ksRChar ( "L", 20, 0 );
							data.ksRFloat( "d" );
						data.ksEndRelation();
						if ( data.ksDoStatement(base.bs, base.rs1, buf) ) { //"1 2"
							base.rs2 = data.ksRelation( base.bs );
								data.ksRInt  ( "t" );
								data.ksRFloat( "L" );
								data.ksRFloat( "d" );
								data.ksRFloat( "" );
								data.ksRFloat( "" );
								data.ksRFloat( "" );
							data.ksEndRelation();
							if ( data.ksDoStatement(base.bs, base.rs2, "") ) { // TXT_ALL
	              openBase = true;
								return true;
							}
						}
					}
				}
			}
		}
	}
	return false;
}

//------------------------------------------------------------------------------
//  
// ---
void Shpeel::CloseBase() {
	if ( base.bg ) {
	  data.ksDeleteDB( base.bg );
		base.bg = 0;
	}
  if ( base.bs ) {
	  data.ksDeleteDB( base.bs );
		base.bs = 0;
	}
  openBase = false;
}

//------------------------------------------------------------------------------
//  
// ---
int Shpeel::ReadShpeelBase( float d ) {
	CString  buf;
  char s[128];
	buf.LoadString( STR_245 ); //
  ::sprintf( s, buf, d );   //"d=%.0f"
  if ( data.ksCondition(base.bg, base.rg2, s) ) { 
		if ( data.ksReadRecord(base.bg, base.rg2, paramTmp) ) {
			GetUserParamTmp();
			return 1;
		}
	}
  return 0;
}

//------------------------------------------------------------------------------
//    
//   1 -  0 -    -1 -    
// ---
int Shpeel::ReadShpeelStBase() {
	CString  buf;
  char buf1[128];
	buf.LoadString( STR_246 ); //
  ::sprintf( buf1, buf, tmp.l, tmp.d );  // "L=%.0f && d=%.0f"

  if ( !data.ksCondition(base.bs,  base.rs2, buf1) ) { return -1; }
  int i = data.ksReadRecord( base.bs, base.rs2, paramSTmp );
  if ( !i )  {
		buf.LoadString( STR_245 ); //
    ::sprintf( buf1, buf, tmp.d);   //" d=%.0f "

    if ( !data.ksCondition(base.bs,  base.rs2, buf1) ) { return -1;}
    data.ksReadRecord( base.bs, base.rs2, paramSTmp );
  }
	GetUserParamSTmp();
  return 1;
}

/*
  float          ang;
  unsigned short flagAttr;
  short          drawType;
  BYTE           typeSwitch;  //       0 Placement 1 Curso

  float d;          //  
  float p1;         //  
  float p2;         //  
  float b1;         //    l1
  float c;          //  
  float l;          //  
  float b;          //    l0
  short f;          //  
  short klass;      //  
  short gost;       //  
  short ver;        //  
  float m1;         //  1 
  float m2;         //  2 
  short indexMassa; // 0- 1-   3- 2-
*/
//-------------------------------------------------------------------------------
//
// ---
void Shpeel::InitUserParam() {
	if ( param.m_lpDispatch ) {
		ksLtVariant			item( kompas.GetParamStruct(ko_LtVariant) );
		ksDynamicArray	arr	( kompas.GetDynamicArray(LTVARIANT_ARR) );
		if ( item.m_lpDispatch && arr.m_lpDispatch ) {
			param.Init();
			param.SetUserArray( arr );
			item.Init();
			item.SetFloatVal( par.ang );        // 0 - ang
			arr.ksAddArrayItem( -1, item );
			item.SetShortVal( par.flagAttr );   // 1 - flagAttr
			arr.ksAddArrayItem( -1, item );
			item.SetShortVal( par.drawType );   // 2 - drawType
			arr.ksAddArrayItem( -1, item );
			item.SetShortVal( par.typeSwitch ); // 3 - typeSwitch
			arr.ksAddArrayItem( -1, item );

			item.SetFloatVal( tmp.d );          // 4 - d
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.p1 );         // 5 - p1
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.p2 );         // 6 - p2
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.b1 );         // 7 - b1
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.c );          // 8 - c
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.l );          // 9 - l
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.b );          // 10 - b
			arr.ksAddArrayItem( -1, item );
			item.SetShortVal( tmp.f );          // 11 - f
			arr.ksAddArrayItem( -1, item );
			item.SetShortVal( tmp.klass );      // 12 - klass
			arr.ksAddArrayItem( -1, item );
			item.SetShortVal( tmp.gost );       // 13 - gost
			arr.ksAddArrayItem( -1, item );
			item.SetShortVal( tmp.ver );        // 14 - ver
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.m1 );         // 15 - m1
			arr.ksAddArrayItem( -1, item );
			item.SetFloatVal( tmp.m2 );         // 16 - m2
			arr.ksAddArrayItem( -1, item );
			item.SetShortVal( tmp.indexMassa ); // 17 - indexMassa
			arr.ksAddArrayItem( -1, item );
		}
	}
}

//-------------------------------------------------------------------------------
//
// ---
void Shpeel::SetUserParam() {
	if ( param.m_lpDispatch ) {
		ksLtVariant			item( kompas.GetParamStruct(ko_LtVariant) );
		ksDynamicArray	arr	( param.GetUserArray() );
		if ( item.m_lpDispatch && arr.m_lpDispatch && arr.ksGetArrayCount() >= 18 ) {
			item.Init();
			item.SetFloatVal( par.ang );        // 0 - ang
			arr.ksSetArrayItem( 0, item );
			item.SetShortVal( par.flagAttr );   // 1 - flagAttr
			arr.ksSetArrayItem( 1, item );
			item.SetShortVal( par.drawType );   // 2 - drawType
			arr.ksSetArrayItem( 2, item );
			item.SetShortVal( par.typeSwitch ); // 3 - typeSwitch
			arr.ksSetArrayItem( 3, item );

			item.SetFloatVal( tmp.d );          // 4 - d
			arr.ksSetArrayItem( 4, item );
			item.SetFloatVal( tmp.p1 );         // 5 - p1
			arr.ksSetArrayItem( 5, item );
			item.SetFloatVal( tmp.p2 );         // 6 - p2
			arr.ksSetArrayItem( 6, item );
			item.SetFloatVal( tmp.b1 );         // 7 - b1
			arr.ksSetArrayItem( 7, item );
			item.SetFloatVal( tmp.c );          // 8 - c
			arr.ksSetArrayItem( 8, item );
			item.SetFloatVal( tmp.l );          // 9 - l
			arr.ksSetArrayItem( 9, item );
			item.SetFloatVal( tmp.b );          // 10 - b
			arr.ksSetArrayItem( 10, item );
			item.SetShortVal( tmp.f );          // 11 - f
			arr.ksSetArrayItem( 11, item );
			item.SetShortVal( tmp.klass );      // 12 - klass
			arr.ksSetArrayItem( 12, item );
			item.SetShortVal( tmp.gost );       // 13 - gost
			arr.ksSetArrayItem( 13, item );
			item.SetShortVal( tmp.ver );        // 14 - ver
			arr.ksSetArrayItem( 14, item );
			item.SetFloatVal( tmp.m1 );         // 15 - m1
			arr.ksSetArrayItem( 15, item );
			item.SetFloatVal( tmp.m2 );         // 16 - m2
			arr.ksSetArrayItem( 16, item );
			item.SetShortVal( tmp.indexMassa ); // 17 - indexMassa
			arr.ksSetArrayItem( 17, item );
		}
	}
}

//-------------------------------------------------------------------------------
//
// ---
void Shpeel::GetUserParam() {
	if ( param.m_lpDispatch ) {
		ksLtVariant			item ( kompas.GetParamStruct(ko_LtVariant) );
		ksDynamicArray	arr	 ( param.GetUserArray() );
		if ( item.m_lpDispatch && arr.m_lpDispatch && arr.ksGetArrayCount() >= 18 ) {
			item.Init();
			arr.ksGetArrayItem( 0, item );
			par.ang = item.GetFloatVal();
			arr.ksGetArrayItem( 1, item );
			par.flagAttr = item.GetShortVal();
			arr.ksGetArrayItem( 2, item );
			par.drawType = item.GetShortVal();
			arr.ksGetArrayItem( 3, item );
			par.typeSwitch = (BYTE)item.GetShortVal();

			arr.ksGetArrayItem( 4, item );
			tmp.d = item.GetFloatVal();
			arr.ksGetArrayItem( 5, item );
			tmp.p1 = item.GetFloatVal();
			arr.ksGetArrayItem( 6, item );
			tmp.p2 = item.GetFloatVal();
			arr.ksGetArrayItem( 7, item );
			tmp.b1 = item.GetFloatVal();
			arr.ksGetArrayItem( 8, item );
			tmp.c = item.GetFloatVal();
			arr.ksGetArrayItem( 9, item );
			tmp.l = item.GetFloatVal();
			arr.ksGetArrayItem( 10, item );
			tmp.b = item.GetFloatVal();
			arr.ksGetArrayItem( 11, item );
			tmp.f = item.GetShortVal();
			arr.ksGetArrayItem( 12, item );
			tmp.klass = item.GetShortVal();
			arr.ksGetArrayItem( 13, item );
			tmp.gost = item.GetShortVal();
			arr.ksGetArrayItem( 14, item );
			tmp.ver = item.GetShortVal();
			arr.ksGetArrayItem( 15, item );
			tmp.m1 = item.GetFloatVal();
			arr.ksGetArrayItem( 16, item );
			tmp.m2 = item.GetFloatVal();
			arr.ksGetArrayItem( 17, item );
			tmp.indexMassa = item.GetShortVal();
		}
	}
}

//------------------------------------------------------------------------------
//
// ---
int Shpeel::GetParam() {
	if ( part.m_lpDispatch ) {
		part.GetUserParam( param );
		GetUserParam();
		return 1;
	}
  return 0; 
}

//-------------------------------------------------------------------------------
//       
// ---
void Shpeel::GetEntityByName( const char* name, ksEntity& entity ) {
  entity= NULL;
  if ( part.m_lpDispatch ) {
    if ( !collect.m_lpDispatch )  //    ,       - 
    	collect.AttachDispatch( part.EntityCollection(o3d_constrElement) );

    ksEntity findEntity( collect.GetByName(CString (name), true, true ) );
    if ( findEntity.m_lpDispatch ) 
      entity = findEntity;
  }
}


//-------------------------------------------------------------------------------
//   -  placement
// ---
bool Shpeel::IsCollectionEmpty( ksRequestInfo3D& info ) 
{
  bool res = true;
  ksEntityCollection collection( info.GetEntityCollection() ); //  
  if ( collection.m_lpDispatch )
    for( int i = 0, count = collection.GetCount(); i < count; i++ ) //   
    {       
      ksEntity ent( collection.GetByIndex(i) );        //  
      if ( ent.m_lpDispatch )                          //    NULL
      {                        
        res = false;                                   //   
        break;                                         //  
      }
    }
  return res; 
}


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


//-------------------------------------------------------------------------------
//
// ---
void Shpeel::SetMates( ksDocument3D& doc, ksRequestInfo3D& info, bool delMates ) 
{
  ksEntityCollection collection( !delMates ? info.GetEntityCollection()
  																				   : part.GetMateConstraintObjects() );
  if ( collection.m_lpDispatch ) 
  {
    if ( doc.m_lpDispatch && collection.GetCount() > 2 )
	    if ( !delMates )
  	  	::AddMates( *this, doc, collection );
      else
  	  	::DelMates( *this, doc, collection );

    if ( !delMates )
	    part.SetMateConstraintObjects( collection );
  }
}


//-------------------------------------------------------------------------------
//       
// ---
void Shpeel::SetCallBackAndFilterFunction( ksRequestInfo3D& info )
{
	::SetCallBackAndFilterFunction( info );
}


//------------------------------------------------------------------------------
//
// ---
reference  Shpeel::EditSpcObj( reference *spcObj )
{
  ksUserParam par1( kompas.GetParamStruct(ko_UserParam) );
 	ksLtVariant item( kompas.GetParamStruct(ko_LtVariant) );
	ksDynamicArray arr( kompas.GetDynamicArray(LTVARIANT_ARR) );
	if ( !par1.m_lpDispatch || !item.m_lpDispatch || !arr.m_lpDispatch )
		return 0;

	par1.Init();
	par1.SetUserArray( arr );
  item.Init();

  if ( !flagMode && !par.flagAttr && !specification.m_lpDispatch )
    return 0;

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


    if ( *spcObj && !specification.ksSpcObjectEdit( *spcObj ) )
      *spcObj  = 0;
  }
	bool flagMode = *spcObj ? true : false;
  if ( flagMode || specification.ksSpcObjectCreate(NULL,          //   
 															  						0,                    //   
                                            STANDART_SECTION, 0,  //    
                                            81764182256.0, 0) )   //  
  {
   // 
   unsigned int uBuf = !!(tmp.f & ISPOLN );
   specification.ksSpcVisible( SPC_NAME, 2, uBuf );
   if ( uBuf ) {
		 arr.ksClearArray();
		 item.SetUIntVal( 2 );
		 arr.ksAddArrayItem( -1, item );
     specification.ksSpcChangeValue( SPC_NAME, 2, par1, UINT_ATTR_TYPE );
   }

   //  
	 arr.ksClearArray();
	 item.SetFloatVal( tmp.d );
	 arr.ksAddArrayItem( -1, item );
   specification.ksSpcChangeValue( SPC_NAME, 4, par1, FLOAT_ATTR_TYPE  );

   //   
   uBuf = !(tmp.f & PITCHOFF  || !(tmp.f &PITCH));
   specification.ksSpcVisible( SPC_NAME, 5, uBuf );
   specification.ksSpcVisible( SPC_NAME, 6, uBuf ); // 
   if( uBuf ) //     
   {
		 arr.ksClearArray();
		 item.SetFloatVal( tmp.p2 );
		 arr.ksAddArrayItem( -1, item );
     specification.ksSpcChangeValue( SPC_NAME, 6, par1, FLOAT_ATTR_TYPE );
	 }

   //  
	 arr.ksClearArray();
	 item.SetUIntVal( (unsigned int)tmp.l );
	 arr.ksAddArrayItem( -1, item );
   specification.ksSpcChangeValue( SPC_NAME , 9, par1, UINT_ATTR_TYPE  );

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

   //  
	 arr.ksClearArray();
	 item.SetUIntVal( tmp.gost );
	 arr.ksAddArrayItem( -1, item );
   specification.ksSpcChangeValue( SPC_NAME , 14, par1, UINT_ATTR_TYPE  );
   float  massa  = tmp.f & ISPOLN ? tmp.m2 : tmp.m1;
   massa = (float)( massa * (!tmp.indexMassa 
										  						? 1 : tmp.indexMassa==1 
											  									? 0.356 : tmp.indexMassa==3 
												  														? 0.97 : 1.08) / COUNT_MASSA );
   char buf[128];
   sprintf( buf, "%f" , massa );
   specification.ksSpcMassa ( buf ); //  

   //  
   specification.D3SpcIncludePart( part, false );

   return specification.ksSpcObjectEnd();
 }
 return 0;
}


//-------------------------------------------------------------------------------
//
// ---
bool Shpeel::DrawSpcObj() 
{
  ::memset( spcObj, 0, sizeof(reference) * MAX_COUNT_SPCOBJ );
  if ( kompas.ksReturnResult() == etError10 ) //  
    kompas.ksResultNULL();

  spcObj[0] = obj->EditSpcObj( spcObj );
  if( !obj->par.flagAttr && spcObj ) 
  {
    for ( int i = 0, count = obj->GetObjCount(); i < count; i++ ) 
    {
      if ( spcObj[i] ) 
      {
        obj->doc.ksDeleteObj( spcObj[i] );
        spcObj[i] = 0;
      }
    }
  }
  return spcObj[0] ? true : false;
}

//-------------------------------------------------------------------------------
//   
// ---
void Shpeel::Draw3D( ksDocument3D &_doc )
{
  if ( _doc.m_lpDispatch ) 
  {
		doc           = _doc;
		specification = doc.GetSpecification();
    flagMode      = doc.IsEditMode() ;
    obj           = this;

    //  
    part = doc.GetPart( flagMode ? pEdit_Part : pNew_Part );
    if ( part.m_lpDispatch ) 
    {
      //       
      if ( flagMode )
        GetParam();
      else
        part.SetFileName( obj->SetFileName() );

      if ( obj->MacroElementParam() == IDOK ) 
      {
        bool ok = false;
        if ( flagMode )     //       mate'
        { 
         	SetParam( part ); //  
          ok = true;        //  
				}
        else                //  
        {             
          ksRequestInfo3D info( doc.GetRequestInfo(part.m_lpDispatch) );
          if ( info.m_lpDispatch ) 
          {
		  			CString prompt;
					 
		        prompt.LoadString( flagMode ? STR_SELECT_PLANE : STR_SELECT_POINT ); //    
            info.SetPrompt( prompt );
				  	SetCallBackAndFilterFunction( info );
            info.CreatePhantom();
					  ksPart phantom ( info.GetIPhantom() );
            if ( phantom )
              SetParam( phantom ); 
            
            //   
            if ( doc.UserGetPlacementAndEntity(3) ) 
            {
              ksPlacement lpace( info.GetPlacement() );
              part.SetPlacement( lpace );
              if ( flagMode || doc.SetPartFromFile( obj->SetFileName(), part, false/*externalFile*/ ) ) {
                SetParam( part );

                if ( IsCollectionChange(info) )  //  Mate' 
                { 
                  if ( flagMode )                //  
                    SetMates( doc, info, true ); //  

                  SetMates( doc, info );         //  
								}

                if ( IsCollectionEmpty(info) )   //  placement
                  part.UpdatePlacement();        //   
                
                //  ,  
                part.SetStandardComponent( true );
							}
						  DrawSpcObj();    //   

              if ( spcObj[0] ) //   
              {                       
                //   -  
			          for ( int i = 0, count = obj->GetObjCount(); i < count; i++ ) //{
              	  specification.ksEditWindowSpcObject( spcObj[i] );
			            ::memset( spcObj, 0, sizeof(reference) * MAX_COUNT_SPCOBJ );
							}
            }
          }
        }
      }
    }
    part.ReleaseDispatch();
  }
}


//------------------------------------------------------------------------------
//     varName  val
// ---
void SetVarValue( ksVariableCollection& varArr, char* varName, double val ) {
	ksVariable var( varArr.GetByName(varName, true, false) ); //  
  if ( var.m_lpDispatch )
    var.SetValue( val );                     //  
}


//------------------------------------------------------------------------------
//
// ---
void Shpeel::SetParam( ksPart& _part ) 
{
  //   
  if ( _part.m_lpDispatch ) 
  {
    //    
    ksVariableCollection varArr( _part.VariableCollection() );
    if ( varArr.m_lpDispatch ) 
    {
      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 = (float)(tmp.l - 0.5 * 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); // / 

      //   
      CString buf1;
			buf1.LoadString( IDS_STUD_NAME );               //     
      char buf[255];
      ::sprintf( buf, buf1, tmp.d, tmp.l, tmp.gost ); //   
      _part.SetName( buf );                           //    
      _part.Update();                                 //  

      //      
      _part.RebuildModel();
    }

		SetUserParam();
    _part.SetUserParam( param );
  }
}


//------------------------------------------------------------------------------
//  
// ---
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;
}


//------------------------------------------------------------------------------
//
// ---
CString&  Shpeel::SetFileName()
{
  char name[128];
  ::GetFullName( STUDS_FILE, name );
  fileName = name;
  return fileName;
}

