//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <windows.h>
#include <math.h>
#include <stdio.h>
#include <Ks_TLB.h>
#include <ldefin2d.h>
#include <ldefin3d.h>
#include <ksConstants.h>

#include "base.h"
//---------------------------------------------------------------------------
//   Important note about DLL memory management when your DLL uses the
//   static version of the RunTime Library:
//
//   If your DLL exports any functions that pass String objects (or structs/
//   classes containing nested Strings) as parameter or function results,
//   you will need to add the library MEMMGR.LIB to both the DLL project and
//   any other projects that use the DLL.  You will also need to use MEMMGR.LIB
//   if any other projects which use the DLL will be performing new or delete
//   operations on any non-TObject-derived classes which are exported from the
//   DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
//   EXE's to use the BORLNDMM.DLL as their memory manager.  In these cases,
//   the file BORLNDMM.DLL should be deployed along with your DLL.
//
//   To avoid using BORLNDMM.DLL, pass string information using "char *" or
//   ShortString parameters.
//
//   If your DLL uses the dynamic version of the RTL, you do not need to
//   explicitly add MEMMGR.LIB as this will be done implicitly for you
//---------------------------------------------------------------------------
HINSTANCE _hinst;

#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
  _hinst = hinst;
  return 1;
}
//---------------------------------------------------------------------------

//------------------------------------------------------------------------------
//
// ---
extern "C" IDispatch* far __export WINAPI CreateKompasObject();

KompasObject* kompas = NULL;
Shpeel* obj;

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

extern "C" char * far __export __pascal LibraryName(){
	return  "   C++Builder";
}

#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"

//------------------------------------------------------------------------------
//
// ---
extern "C" void far __export __pascal  LibraryEntry( UINT Comm ) {
  kompas = (KompasObject*)::CreateKompasObject();
  Application->Handle =(HWND)kompas->ksGetHWindow();
  if ( kompas )
  { Shpeel* par = new Shpeel();
    if(par)
    { kompas->ksResultNULL();
      ksDocument3D* doc = (ksDocument3D*)kompas->ActiveDocument3D();
      if ( doc && (doc->IsDetail() ==false ) )
        par->Draw3D( doc );
      else
        kompas->ksError( StringToOleStr("      ") );
    }
    kompas->Release();
  }
}

////////////////////////////////////////////////////////////////////////////////
//
//  
//
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
//     : planar = true - ,
// false -  
// ---
bool IsSurface( ksEntity* entity, bool planar = true, double *diam = NULL ) {
	bool rez = false;                                //  
  if ( entity ) {
    if ( entity->IsIt(o3d_face) ) {
			ksFaceDefinition* faceDef = (ksFaceDefinition*)entity->GetDefinition();
      if ( faceDef ) {
        if ( planar && (faceDef->IsPlanar() ==true) )
          rez = true;

        if ( !planar && (faceDef->IsCylinder() ==true) )
          rez = true;
      }
    }
  }
  return rez;
}

//------------------------------------------------------------------------------
//     
// ---
bool IsAxis( ksEntity* entity ) {
  if ( entity ) {
  	return ( entity->IsIt( o3d_axis2Planes ) ==true)       ||  //    
    	       ( entity->IsIt( o3d_axisOperation ) ==true)    ||  //  
               ( entity->IsIt( o3d_axis2Points ) ==true)    ||  //    
               ( entity->IsIt( o3d_axisConeFace ) ==true) ||  //   
               ( entity->IsIt( o3d_axisEdge ) ==true);      //   
  }
  return false;
}

//------------------------------------------------------------------------------
//  
// ---
bool WINAPI SELECTFILTERPROC( ksEntity*  entity ) {
  bool rez = false;                                 //  
  if ( entity ) {                                  //   
  		  ksPart* entPart = (ksPart*)entity->GetParent();         //   
			if ( entPart != obj->GetPart() )       //   
				rez = ::IsSurface( entity ) || ::IsSurface( entity, false/*planar*/ )
								|| ::IsAxis( entity );                //     
		}                                               // ,    

  return rez;
}

//------------------------------------------------------------------------------
//   
// 0 - , 1 - , 2 -  -  collection
// ---
int WINAPI SELECTCALLBACKPROC( ksEntity* entity, ksRequestInfo3D* info ) {
    char buf[128];

		ksEntityCollection* collection =  info ? (ksEntityCollection*)info->GetEntityCollection() : NULL ;
		if ( entity ) {
			if ( collection ) {
				int rez = 0;
				if ( ::IsSurface(entity) ) {
          //        
          ksEntity * oldPlane = (ksEntity*)collection->GetByIndex(0);
          if ( oldPlane == entity )
            collection->SetByIndex( NULL, 0 );   //  
          else
          collection->SetByIndex( entity, 0 ); //  
					rez = 1;
				}

				double diam;
				if ( ::IsSurface(entity, false/*planar*/, &diam) ) {
          //        
          ksEntity * oldPlane = (ksEntity*)collection->GetByIndex(1);
          if ( oldPlane == entity )
            collection->SetByIndex( NULL,   1 ); //   
          else
          {
            collection->SetByIndex( entity, 1 ); //   
            collection->SetByIndex( NULL,   2 ); //  
          } 
					rez = 1;
				}

				if ( ::IsAxis(entity) ) {
          //        
          ksEntity * oldAxis = (ksEntity*)collection->GetByIndex(2);
          if ( oldAxis == entity )
            collection->SetByIndex( NULL,   2 ); //  
          else
          {
            collection->SetByIndex( entity, 2 ); //  
            collection->SetByIndex( NULL,   1 ); //   
          }
					rez = 1;
				}

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

        LoadString( _hinst, STR_SELECT_PLANE, buf, 128 );   //    
				info->prompt = WideString(buf);
				return rez;
			}
		}
		else {
  		if ( collection )
    		for ( int i = 0; i < 3; i++ )
					collection->SetByIndex( NULL, i ); // 

			LoadString( _hinst, STR_SELECT_PLANE, buf, 128 );   //    
			info->prompt = WideString(buf);
			return 1;
		}
  return 0;
}

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

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

  ent = (ksEntity*)collection->GetByIndex( 2 ); //    =
  if ( ent && ::IsAxis(ent) ) {                      // 
    if ( doc->AddMateConstraint(mc_Concentric, ent, object->GetEntityByName("Axis"),
    			0, 1, 0) ==false) {
    	collection->SetByIndex( NULL, 2 );
    }
  }
}

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

  ent = (ksEntity*)collection->GetByIndex( 1 ); //    =
  if ( ent && ::IsSurface(ent, false/*planar*/) ) {  //  
    doc->RemoveMateConstraint( mc_Concentric, ent, object->GetEntityByName("Axis") );
  }

  ent = (ksEntity*)collection->GetByIndex( 2 ); //    =
  if ( ent && ::IsAxis(ent) ) {                      // 
    doc->RemoveMateConstraint( mc_Concentric, ent, object->GetEntityByName("Axis") );
  }
}

//------------------------------------------------------------------------------
//       
// ---
void SetCallBackAndFilterFunction( ksRequestInfo3D* info ) {
  info->SetFilterCallBack( WideString("SELECTFILTERPROC"),  (long)_hinst, 0 );
  info->SetCallBack      ( WideString("SELECTCALLBACKPROC"), (long)_hinst, 0 );
}

////////////////////////////////////////////////////////////////////////////////
//
//   - 
//
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
// 
// ---
Shpeel::Shpeel()  
  : part          ( NULL  ),
    doc           ( NULL  ),
    specification ( NULL  ),
    collect       ( NULL  ),
    param         ( (ksUserParam *)kompas->GetParamStruct(ko_UserParam) ),
    paramTmp      ( (ksUserParam *)kompas->GetParamStruct(ko_UserParam) ),
    paramSTmp     ( (ksUserParam *)kompas->GetParamStruct(ko_UserParam) ),
    data          ( (ksDataBaseObject *)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    ( (ksUserParam *)kompas->GetParamStruct(ko_UserParam) ),
	  paramTmp ( (ksUserParam *)kompas->GetParamStruct(ko_UserParam) ),
	  paramSTmp( (ksUserParam *)kompas->GetParamStruct(ko_UserParam) ),
          collect  ( NULL ),
	  data     ( (ksDataBaseObject *)kompas->DataBaseObject()                ) {
  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();
  }
}

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

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

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

//-------------------------------------------------------------------------------
//
// ---
void Shpeel::GetUserParamSTmp() {
	if ( paramSTmp ) {
		ksLtVariant* item = (ksLtVariant*)kompas->GetParamStruct(ko_LtVariant);
		ksDynamicArray*	arr =  (ksDynamicArray*)paramSTmp->GetUserArray();
		if ( item && arr
			       	&& arr->ksGetArrayCount() >= 6 ) {
			item->Init();
			arr->ksGetArrayItem( 1, item ); // l
			tmp.l = item->floatVal;
			arr->ksGetArrayItem( 2, item ); // d
			tmp.d = item->floatVal;
			arr->ksGetArrayItem( 3, item ); // s
			tmp.b = item->floatVal;
			arr->ksGetArrayItem( 4, item ); // m1
			tmp.m1 = item->floatVal;
			arr->ksGetArrayItem( 5, item ); // m2
			tmp.m2 = item->floatVal;
		}
		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  ) {
  char* bufName = ::strnewdup( name );
  char* buffer = NULL;
  bool rez = false;
  if( ::GetModuleFileName(_hinst, fName, _MAX_PATH) ) {
    char *c = ::strchr( bufName, '|' );
    if ( c ) {
      buffer = ::strnewdup( c );
      *c = '\0';
    }

    c = ::strrchr( fName, '\\' );
    if ( c ) {
      *( c + 1 ) = '\0';
      strcat( fName, bufName );
      OFSTRUCT ofs;
      if ( OpenFile(fName , &ofs, OF_EXIST) != HFILE_ERROR )
        rez = true;
      else {
        *(c + 1) = '\0';
        strcat( fName, "LOAD\\" );
        strcat( fName, bufName );
        if ( OpenFile(fName , &ofs, OF_EXIST) != HFILE_ERROR )
          rez = true;
        else {
#ifndef MODEL_LIB
          *(c+1) = '\0';
          strcat( fName, "MODEL\\" );
          strcat( fName, bufName );
          rez = OpenFile(fName , &ofs, OF_EXIST) != HFILE_ERROR ? true : false;
#endif
        }
      }
    }
  }

  if ( buffer ) {
    strcat( fName, buffer );
    delete [] buffer;
  }

  delete [] bufName;
  return rez;
}

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

//------------------------------------------------------------------------------
//       
// ---
bool Shpeel::OpenBase( bool initParam ) {

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

	if ( data ) {
		char buf[128]; //
                LoadString( _hinst, BASE_STR1, buf, 128 );

		base.bg = data->ksCreateDB( WideString(buf) );   // TXT_DB
		base.bs = data->ksCreateDB( WideString(buf) );   // TXT_DB

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

                LoadString( _hinst, gNumb, buf, 128 );
		if( _ConnectDB(base.bg, buf) ) { //"22032.loa"
                        LoadString( _hinst, stNumb, buf, 128 );
			if( _ConnectDB(base.bs, buf) ) { //"st22032.loa"
                                LoadString( _hinst, STR_241, buf, 128 );
				base.rg1 = data->ksRelation( base.bg );
				        data->ksRInt ( WideString("t") );
			                data->ksRChar( WideString("d"), 20, 0 );
				data->ksEndRelation();
				if ( data->ksDoStatement(base.bg, base.rg1,WideString(buf)) ) { //"1 2"
					base.rg2 = data->ksRelation( base.bg );
						data->ksRInt  ( WideString("t") );
						data->ksRFloat( WideString("d") );
						data->ksRFloat( WideString("") );
						data->ksRFloat( WideString("") );
						data->ksRFloat( WideString("") );
						data->ksRFloat( WideString("") );
					data->ksEndRelation();
					if ( data->ksDoStatement(base.bg, base.rg2, WideString("")) ) { //TXT_ALL
                                                LoadString( _hinst, STR_243, buf, 128 );
						base.rs1 = data->ksRelation( base.bs );
							data->ksRInt  ( WideString("t") );
							data->ksRChar ( WideString("L"), 20, 0 );
							data->ksRFloat( WideString("d") );
						data->ksEndRelation();
						if ( data->ksDoStatement(base.bs, base.rs1,WideString(buf)) ) { //"1 2 3"
							base.rs2 = data->ksRelation( base.bs );
								data->ksRInt  ( WideString("t") );
								data->ksRFloat( WideString("L") );
								data->ksRFloat( WideString("d") );
								data->ksRFloat( WideString("") );
								data->ksRFloat( WideString("") );
								data->ksRFloat( WideString("") );
							data->ksEndRelation();
							if ( data->ksDoStatement(base.bs, base.rs2, WideString("")) ) { // 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 ) {
  char buf[128];
  char s[128];

  LoadString( _hinst, STR_245, buf, 128 );
  ::sprintf( s, buf, d );   //"d=%.1f"
  if ( data->ksCondition(base.bg, base.rg2, WideString(s)) ) {
		if ( data->ksReadRecord(base.bg, base.rg2, paramTmp) ) {
			GetUserParamTmp();
			return 1;
		}
	}
  return 0;
}

//------------------------------------------------------------------------------
//    
//   1 -  0 -    -1 -    
// ---
int Shpeel::ReadShpeelStBase() {
  char buf[128],buf1[128];

  LoadString( _hinst, STR_246, buf, 128 );
  ::sprintf( buf1, buf, tmp.l, tmp.d );  // "L=%.1f && d=%.1f"

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

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

//-------------------------------------------------------------------------------
//
// ---
void Shpeel::InitUserParam() {
	if ( param ) {
		ksLtVariant*	item( (ksLtVariant*)kompas->GetParamStruct(ko_LtVariant) );
		ksDynamicArray*	arr	( (ksDynamicArray*)kompas->GetDynamicArray(LTVARIANT_ARR) );
		if ( item && arr ) {
			param->Init();
			param->SetUserArray( arr );
			item->Init();
			item->floatVal = par.ang;           // 0 - ang
			arr->ksAddArrayItem( -1, item );
			item->shortVal = par.flagAttr;      // 1 - flagAttr
			arr->ksAddArrayItem( -1, item );
			item->shortVal = par.drawType;      // 2 - drawType
			arr->ksAddArrayItem( -1, item );
			item->shortVal = par.typeSwitch;    // 3 - typeSwitch
			arr->ksAddArrayItem( -1, item );

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

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

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


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

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

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

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

    ksEntity* findEntity = (ksEntity*)collect->GetByName( WideString(name), true/*testFullName*/, true/*testIgnoreCase*/);
    if ( findEntity ) {
      LPUNKNOWN defin = findEntity->GetDefinition();
      if ( defin ) {
        entity = findEntity;
        defin->Release();
      }
      if ( !entity )
        findEntity->Release();
    }
  }
  return entity;
}


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

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

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

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

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

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

	par1->Init();
	par1->SetUserArray( arr );
  item->Init();

  if ( !flagMode && !par.flagAttr && !specification )
    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->uIntVal = 2;
		 arr->ksAddArrayItem( -1, item );
     specification->ksSpcChangeValue( SPC_NAME, 2, par1, UINT_ATTR_TYPE );
   }

   // 
	 arr->ksClearArray();
	 item->floatVal = 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->floatVal = tmp.p2;
		 arr->ksAddArrayItem( -1, item );
     specification->ksSpcChangeValue( SPC_NAME, 6, par1, FLOAT_ATTR_TYPE );
	 }

   // 
	 arr->ksClearArray();
	 item->uIntVal = (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->uIntVal = 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 ( WideString(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 )    //  10  "!  "
    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 )
{
  char buf[128];

  if ( _doc ) {
    doc           = _doc;
    specification = (ksSpecification*)doc->GetSpecification();
    flagMode      = doc->IsEditMode() ;
    obj           = this;

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

      if ( obj->MacroElementParam() == IDOK ) {

        ksRequestInfo3D* info = (ksRequestInfo3D*)doc->GetRequestInfo(part);
        if ( info /*&& obj->OpenElemBase()*/ ) {
          if(flagMode)
	    LoadString( _hinst, STR_SELECT_PLANE, buf, 128 );
          else
            LoadString( _hinst, STR_SELECT_POINT, buf, 128 );
	  info->prompt = WideString(buf); //    
          
          SetCallBackAndFilterFunction( info );
          if ( doc->UserGetPlacementAndEntity(3) ) {
            part->SetPlacement( info->GetPlacement() );
            if ( flagMode || (doc->SetPartFromFile( obj->SetFileName(), part, false/*externalFile*/ ) ==true)) {
              SetParam();

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

                SetMates( doc, info );                     //  
              }

              if ( IsCollectionEmpty(info) ) //  placement
                part->UpdatePlacement();      //   
              // ,  
              part->standardComponent = 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 );
            }

          }
        }
//        obj->CloseElemBase();
      }

      part->Release();
    }
  }
}

//------------------------------------------------------------------------------
//     varName  val
// ---
void SetVarValue( ksVariableCollection* varArr, char* varName, double val ) {
	ksVariable* var = (ksVariable*)varArr->GetByName(WideString(varName), true, false); //  
  if ( var )
    var->value = val;                     //  
}

//------------------------------------------------------------------------------
//
// ---
void Shpeel::SetParam() {
  //  
  if ( part ) {
    //   
    ksVariableCollection* varArr = (ksVariableCollection*)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 = (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/**/ ); // / 

      //   
      char buf[255],buf1[128];
      LoadString( _hinst, IDS_STUD_NAME, buf1, 128 );              //     

      ::sprintf( buf, buf1, tmp.d, tmp.l, tmp.gost );  //   
      part->name = WideString(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;
}

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


