////////////////////////////////////////////////////////////////////////////////
//
// step3D3.cpp -    
// 
// 1.                     - ConstrAxisOperations 
// 2.                 - ConstrAxis2Point    
// 3.  ,      - ConstrAxisEdge      
// 4.  ,    , 
//                - ConstrElem   
// 5.                      - ConstrPlane3Point   
//
////////////////////////////////////////////////////////////////////////////////
#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 __STEP3D3_RH
#include "step3D3.rh"
#endif

#ifndef __STEP3D3_H
#include "step3D3.h"
#endif

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

HINSTANCE _hinst;

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


//-------------------------------------------------------------------------------
//   
// ---
void ConstrAxisOperations( IUEnv <IPart> & part );
void ConstrAxis2Point( IUEnv <IPart> & part );
void ConstrAxisEdge( IUEnv <IPart> & part );
void ConstrPlane3Point( IUEnv <IPart> & part );
void ConstrElem( IUEnv <IPart> & part );


//-------------------------------------------------------------------------------
//   
// ---
extern "C" void far __export __pascal LibraryEntry( unsigned int comm )
{
  LPDOCUMENT3D pDocument3d = ksGetActive3dDocument(); //       
  if ( pDocument3d )
  {
    //           ( pNew_Part -  ,
    // pEdit_Part -  , pTop_Part  -   )
    IUEnv <IPart> part( pDocument3d->GetPart( pTop_Part ) ); 
    if ( part )
    {
      switch ( comm )
      {
        case 1  : ConstrAxisOperations( part ); break; //   
        case 2  : ConstrAxis2Point    ( part ); break; //     
        case 3  : ConstrAxisEdge      ( part ); break; //  ,   
        case 4  : ConstrElem          ( part ); break; //  ,    ,      -
        case 5  : ConstrPlane3Point   ( part ); break; //    
      }
    }
    pDocument3d->Release();  //  , AddRef   
  }
  else
  {
    Error( _LoadStr( STR_3DDOCERROR ) ); //       3D-
  }
  if ( ReturnResult() == etError10 ) // !  
    ResultNULL(); //  
}


//-------------------------------------------------------------------------------
//   
// ---
void ConstrAxisOperations( IUEnv <IPart> & part ) 
{
  //   
  IUEnv <IEntity> entitySketch( part->NewEntity( o3d_sketch ) );
  if ( entitySketch )
  {
    //        
    LPUNKNOWN pDefinitionSketch = entitySketch->GetDefinition();
    if ( pDefinitionSketch )
    {
      //   
      IUPTR( SketchDefinition ) sketchDefinition( pDefinitionSketch );
      if ( sketchDefinition )
      {
        //     XOY
        IUEnv <IEntity> basePlane( part->GetDefaultEntity( o3d_planeXOY ) );
 
        //   
        sketchDefinition->SetPlane( basePlane.GetI() ); //   XOY   
 
        //  
        entitySketch->Create(); 
        
        //     
        if ( sketchDefinition->BeginEdit() )
        {      
          //   
          Circle( 20, 0, 10, 1 );
          LineSeg( 0, 0, 0, 5, 3 );
          //     
          sketchDefinition->EndEdit();
        }             

        //  
        IUEnv <IEntity> entityRotate( part->NewEntity( o3d_baseRotated ) );
        if ( entityRotate ) 
        {
          //        
          LPUNKNOWN pDefinitionRotate = entityRotate->GetDefinition();  
          if ( pDefinitionRotate ) 
          {
            //    
            IUPTR( BaseRotatedDefinition ) baseRotatedDefinition( pDefinitionRotate ); 
            if ( baseRotatedDefinition ) 
            {
              //    
              IUPTR( RotatedParam ) rotatedParam( baseRotatedDefinition->RotatedParam() );
              if ( rotatedParam ) 
              {
                rotatedParam->SetDirection( dtBoth );  //   ( dtNormal	-  ,
                                                       // dtReverse -  , dtBoth -   ,
                                                       // dtMiddlePlane -    )
                rotatedParam->SetToroidShape( false ); //   ( TRUE - , FALSE -  )
              }           
              //     
              baseRotatedDefinition->SetThinParam( true,   //    
                                                   dtBoth, //     ( dtNormal	-  ,
                                                           // dtReverse -  , dtBoth -   ,
                                                           // dtMiddlePlane -    )
                                                   1,      //     
                                                   1 );    //        
              //       
              baseRotatedDefinition->SetSideParam( true,   //   ( TRUE - , FALSE -  )
                                                   180 );  //   
              baseRotatedDefinition->SetSideParam( false, 180 ); 
              baseRotatedDefinition->SetSketch( entitySketch.GetI() ); //    
              entityRotate->Create(); //   
            }
            pDefinitionRotate->Release(); //  , AddRef   
          }
        }

        //   
        IUEnv <IEntity> entityAxisOperation( part->NewEntity( o3d_axisOperation ) );
        if ( entityAxisOperation ) 
        {
          //        
          LPUNKNOWN pDefinitionAxisOperation = entityAxisOperation->GetDefinition();  
          if ( pDefinitionAxisOperation ) 
          {
            //   
            IUPTR( AxisOperationsDefinition ) axisOperationsDefinition( pDefinitionAxisOperation );
            if ( axisOperationsDefinition ) 
            {
              axisOperationsDefinition->SetOperation( entityRotate.GetI() ); //    
              entityAxisOperation->Create(); // C  
            }
            pDefinitionAxisOperation->Release(); //  , AddRef   
          }
        }
        Message( " " );
      }
      pDefinitionSketch->Release(); //  , AddRef    
    }
  }
}


//-------------------------------------------------------------------------------
//     
// ---
void ConstrAxis2Point( IUEnv <IPart> & part ) 
{
  //   
  IUEnv <IEntity> entitySketch( part->NewEntity( o3d_sketch ) );
  if ( entitySketch )
  {
    //        
    LPUNKNOWN pDefinitionSketch = entitySketch->GetDefinition();
    if ( pDefinitionSketch )
    {
      //   
      IUPTR( SketchDefinition ) sketchDefinition( pDefinitionSketch );
      if ( sketchDefinition )
      {
        //     XOY
        IUEnv <IEntity> basePlane( part->GetDefaultEntity( o3d_planeXOY ) );
 
        //   
        sketchDefinition->SetPlane( basePlane.GetI() ); //   XOY   
 
        //  
        entitySketch->Create(); 
        
        //     
        if ( sketchDefinition->BeginEdit() )
        {
          //    - 
          LineSeg(  50,  50, -50,  50, 1 );
          LineSeg(  50, -50, -50, -50, 1 );
          LineSeg(  50, -50,  50,  50, 1 );
          LineSeg( -50, -50, -50,  50, 1 );
          //     
          sketchDefinition->EndEdit();                  
        }

        //   
        IUEnv <IEntity> entityExtrusion( part->NewEntity( o3d_baseExtrusion ) );
        if ( entityExtrusion ) 
        {
          //        
          LPUNKNOWN pDefinitionExtrusion = entityExtrusion->GetDefinition();     
          if ( pDefinitionExtrusion ) 
          {
            //    
            IUPTR( BaseExtrusionDefinition ) baseExtrusionDefinition( pDefinitionExtrusion ); 
            if ( baseExtrusionDefinition ) 
            {
              baseExtrusionDefinition->SetDirectionType( dtNormal );  //   ( dtNormal	-  ,
                                                                      // dtReverse -  , dtBoth -   ,
                                                                      // dtMiddlePlane -    )
              //      
              baseExtrusionDefinition->SetSideParam( true,    //   ( TRUE -  , FALSE -   )
                                                     etBlind, //   ( etBlind	-   ,
                                                              // etThroughAll -   , etUpToVertexTo -    ,
                                                              // etUpToVertexFrom -    , etUpToSurfaceTo	-    ,
                                                              // etUpToSurfaceFrom	-    , etUpToNearSurface	-    )
                                                     20,      //  
                                                     0,       //  
                                                     false ); //   ( TRUE -  , FALSE -   )
              //     
              baseExtrusionDefinition->SetThinParam( true,   //    
                                                     dtBoth, //     ( dtNormal	-  ,
                                                             // dtReverse -  , dtBoth -   ,
                                                             // dtMiddlePlane -    )
                                                     20,     //     
                                                     20 );   //       
              baseExtrusionDefinition->SetSketch( entitySketch.GetI() ); //   
              entityExtrusion->Create(); //   
            }
            pDefinitionExtrusion->Release(); //  , AddRef   
          }
        }
      }
      pDefinitionSketch->Release(); //  , AddRef   
    }

    //    
    //          -     
    IUPTR( EntityCollection ) entityCollection( part->EntityCollection( o3d_vertex ) );     
    if ( entityCollection && entityCollection->GetCount() ) 
    {
      //     
      IUEnv <IEntity> entityAxis2Point( part->NewEntity( o3d_axis2Points ) );
      if ( entityAxis2Point ) 
      {
        //        
        LPUNKNOWN pDefinitionAxis2Point = entityAxis2Point->GetDefinition();
        if ( pDefinitionAxis2Point ) 
        {
          //   ,     
          IUPTR( Axis2PointsDefinition ) axis2PointsDefinition( pDefinitionAxis2Point );
          if ( axis2PointsDefinition ) 
          {
            //        
            axis2PointsDefinition->SetPoint( 1,                                   //   (1  2)
                                             entityCollection->GetByIndex( 0 ) ); //    
            axis2PointsDefinition->SetPoint( 2, entityCollection->GetByIndex( entityCollection->GetCount()- 1 ) );
            entityAxis2Point->Create(); //   ,    
          }
          pDefinitionAxis2Point->Release(); //  , AddRef   
        }
      }
    }
  }
}


//-------------------------------------------------------------------------------
//  ,   
// ---
void ConstrAxisEdge( IUEnv <IPart> & part ) 
{
  //   
  IUEnv <IEntity> entitySketch( part->NewEntity( o3d_sketch ) );
  if ( entitySketch )
  {
    //        
    LPUNKNOWN pDefinitionSketch = entitySketch->GetDefinition();
    if ( pDefinitionSketch )
    {
      //   
      IUPTR( SketchDefinition ) sketchDefinition( pDefinitionSketch );
      if ( sketchDefinition )
      {
        //     XOY
        IUEnv <IEntity> basePlane( part->GetDefaultEntity( o3d_planeXOY ) );
 
        //   
        sketchDefinition->SetPlane( basePlane.GetI() ); //   XOY   
 
        //  
        entitySketch->Create(); 
        
        //     
        if ( sketchDefinition->BeginEdit() )
        { 
          //    - 
          LineSeg(  50,  50, -50,  50, 1 );
          LineSeg(  50, -50, -50, -50, 1 );
          LineSeg(  50, -50,  50,  50, 1 );
          LineSeg( -50, -50, -50,  50, 1 );
          //     
          sketchDefinition->EndEdit();  
        }

        //   
        IUEnv <IEntity> entityExtrusion( part->NewEntity( o3d_baseExtrusion ) );
        if ( entityExtrusion ) 
        {
          //        
          LPUNKNOWN pDefinitionExtrusion = entityExtrusion->GetDefinition();     
          if ( pDefinitionExtrusion ) 
          {
            //    
            IUPTR( BaseExtrusionDefinition ) baseExtrusionDefinition( pDefinitionExtrusion ); 
            if ( baseExtrusionDefinition ) 
            {
              baseExtrusionDefinition->SetDirectionType( dtNormal );  //   ( dtNormal	-  ,
                                                                      // dtReverse -  , dtBoth -   ,
                                                                      // dtMiddlePlane -    )
              //      
              baseExtrusionDefinition->SetSideParam( true,    //   ( TRUE -  , FALSE -   )
                                                     etBlind, //   ( etBlind	-   ,
                                                              // etThroughAll -   , etUpToVertexTo -    ,
                                                              // etUpToVertexFrom -    , etUpToSurfaceTo	-    ,
                                                              // etUpToSurfaceFrom	-    , etUpToNearSurface	-    )
                                                     20,      //  
                                                     0,       //  
                                                     false ); //   ( TRUE -  , FALSE -   )
              //     
              baseExtrusionDefinition->SetThinParam( true,   //    
                                                     dtBoth, //     ( dtNormal	-  ,
                                                             // dtReverse -  , dtBoth -   ,
                                                             // dtMiddlePlane -    )
                                                     20,     //     
                                                     20 );   //       
              baseExtrusionDefinition->SetSketch( entitySketch.GetI() ); //   
              entityExtrusion->Create(); //   
            }
            pDefinitionExtrusion->Release(); //  , AddRef   
          }
        }
      }
      pDefinitionSketch->Release(); //  , AddRef   
    }
       
    //   
    //          -    
    IUPTR( EntityCollection ) entityCollection( part->EntityCollection( o3d_edge ) );
    if ( entityCollection && entityCollection->GetCount() ) 
    {
      //    
      IUEnv <IEntity> entityAxisEdge( part->NewEntity( o3d_axisEdge ) );
      if ( entityAxisEdge ) 
      {
        //        
        LPUNKNOWN pDefinitionAxisEdge = entityAxisEdge->GetDefinition();     
        if ( pDefinitionAxisEdge ) 
        {
          //   ,    
          IUPTR( AxisEdgeDefinition ) axisEdgeDefinition( pDefinitionAxisEdge );
          if ( axisEdgeDefinition ) 
          {
            //      
            axisEdgeDefinition->SetEdge( entityCollection->GetByIndex( 0 ) );
            entityAxisEdge->Create(); //   ,    
          }
          pDefinitionAxisEdge->Release(); //  , AddRef   
        }
      }
    }
  }
}


//-------------------------------------------------------------------------------
//    
// ---
void ConstrPlane3Point( IUEnv <IPart> & part )
{
  //   
  IUEnv <IEntity> entitySketch( part->NewEntity( o3d_sketch ) );
  if ( entitySketch )
  {
    //        
    LPUNKNOWN pDefinitionSketch = entitySketch->GetDefinition();
    if ( pDefinitionSketch )
    {
      //   
      IUPTR( SketchDefinition ) sketchDefinition( pDefinitionSketch );
      if ( sketchDefinition )
      {
        //     XOY
        IUEnv <IEntity> basePlane( part->GetDefaultEntity( o3d_planeXOY ) );
 
        //   
        sketchDefinition->SetPlane( basePlane.GetI() ); //   XOY   
 
        //  
        entitySketch->Create(); 
        
        //     
        if ( sketchDefinition->BeginEdit() )
        {
          //    - 
          LineSeg(  50,  50, -50,  50, 1 );
          LineSeg(  50, -50, -50, -50, 1 );
          LineSeg(  50, -50,  50,  50, 1 );
          LineSeg( -50, -50, -50,  50, 1 );
          //     
          sketchDefinition->EndEdit();
        }

        //   
        IUEnv <IEntity> entityExtrusion( part->NewEntity( o3d_baseExtrusion ) );
        if ( entityExtrusion ) 
        {
          //        
          LPUNKNOWN pDefinitionExtrusion = entityExtrusion->GetDefinition();     
          if ( pDefinitionExtrusion ) 
          {
            //    
            IUPTR( BaseExtrusionDefinition ) baseExtrusionDefinition( pDefinitionExtrusion ); 
            if ( baseExtrusionDefinition ) 
            {
              baseExtrusionDefinition->SetDirectionType( dtNormal );  //   ( dtNormal	-  ,
                                                                      // dtReverse -  , dtBoth -   ,
                                                                      // dtMiddlePlane -    )
              //      
              baseExtrusionDefinition->SetSideParam( true,    //   ( TRUE -  , FALSE -   )
                                                     etBlind, //   ( etBlind	-   ,
                                                              // etThroughAll -   , etUpToVertexTo -    ,
                                                              // etUpToVertexFrom -    , etUpToSurfaceTo	-    ,
                                                              // etUpToSurfaceFrom	-    , etUpToNearSurface	-    )
                                                     20,      //  
                                                     30,      //   
                                                     false ); //   ( TRUE -  , FALSE -   )
              //     
              baseExtrusionDefinition->SetThinParam( true,   //    
                                                     dtBoth, //     ( dtNormal	-  ,
                                                             // dtReverse -  , dtBoth -   ,
                                                             // dtMiddlePlane -    )
                                                     10,     //     
                                                     10 );   //       
              baseExtrusionDefinition->SetSketch( entitySketch.GetI() ); //   
              entityExtrusion->Create(); //   
            }
            pDefinitionExtrusion->Release(); //  , AddRef   
          }
        }
      }
      pDefinitionSketch->Release(); //  , AddRef   
    }

    //    
    //          -   
    IUPTR( EntityCollection ) entityCollection( part->EntityCollection( o3d_vertex ) );
    if ( entityCollection && entityCollection->GetCount() > 2 ) 
    {
      //  ,    
      IUEnv <IEntity> entityPlane3Point( part->NewEntity( o3d_plane3Points ) );
      if ( entityPlane3Point ) 
      {
        //        
        LPUNKNOWN pDefinitionPlane3Point = entityPlane3Point->GetDefinition();     
        if ( pDefinitionPlane3Point ) 
        {
          //  ,    
          IUPTR( Plane3PointsDefinition ) plane3PointDefinition( pDefinitionPlane3Point );
          if ( plane3PointDefinition ) 
          {
            //        
            plane3PointDefinition->SetPoint( 1,                                    //   ( 1  3)
                                             entityCollection->GetByIndex( 0 ) );  //    
            plane3PointDefinition->SetPoint( 2, entityCollection->GetByIndex( 1 ) );
            plane3PointDefinition->SetPoint( 3, entityCollection->GetByIndex( 2 ) );
            entityPlane3Point->Create(); //  ,    
          }
          pDefinitionPlane3Point->Release(); //  , AddRef   
        }
      }
    }
  }
}


//-------------------------------------------------------------------------------
//   ,          
// ---
void ConstrElem( IUEnv <IPart> & part ) 
{
  //   
  IUEnv <IEntity> entityPlaneOffset( part->NewEntity( o3d_planeOffset ) );
  if ( entityPlaneOffset ) 
  {
    //        
    LPUNKNOWN pDefinitionPlaneOffset = entityPlaneOffset->GetDefinition();     
    if ( pDefinitionPlaneOffset ) 
    {
      //    
      IUPTR( PlaneOffsetDefinition ) planeOffsetDefinition( pDefinitionPlaneOffset );
      if ( planeOffsetDefinition ) 
      {
        //    
        planeOffsetDefinition->SetOffset( 150 ); //    
        
        //     XOY
        IUEnv <IEntity> basePlane( part->GetDefaultEntity( o3d_planeXOY ) );
        BSTR b = SysAllocString( L"XOY" );
        basePlane->SetName( b ); //    
        SysFreeString( b );  
        basePlane->Update(); //    

        planeOffsetDefinition->SetPlane( basePlane.GetI() ); //   XOY   

        planeOffsetDefinition->SetDirection( false ); //      ( TRUE -  , FALSE -   )
        b = SysAllocString( L" " );
        entityPlaneOffset->SetName( b ); //    
        SysFreeString( b );

        entityPlaneOffset->Create(); //   

        Message( "   " );  
        planeOffsetDefinition->SetOffset( 50 ); //     
        //     YOZ
        basePlane.SetI( part->GetDefaultEntity( o3d_planeYOZ ) );
        b = SysAllocString( L"YOZ" ); 
        basePlane->SetName( b ); //    
        SysFreeString( b );
        basePlane->Update(); //    
       
        planeOffsetDefinition->SetPlane( basePlane.GetI() ); //   YOZ   
        planeOffsetDefinition->SetDirection( true );        //      
        
        entityPlaneOffset->Update(); //    

        Message( "    " );

        //     XOY
        basePlane.SetI( part->GetDefaultEntity( o3d_planeXOY ) );
        b = SysAllocString( L"XOY" );
        basePlane->SetName( b ); //    
        SysFreeString( b );  
        basePlane->Update(); //    

        //     
        IUEnv <IEntity> entityAxis2Planes( part->NewEntity( o3d_axis2Planes ) );
        if ( entityAxis2Planes ) 
        {
          //        
          LPUNKNOWN pDefinitionAxis2Planes = entityAxis2Planes->GetDefinition();     
          if ( pDefinitionAxis2Planes ) 
          {
            //   ,      
            IUPTR( Axis2PlanesDefinition ) axis2PlanesDefinition( pDefinitionAxis2Planes );
            if ( axis2PlanesDefinition ) 
            {
              axis2PlanesDefinition->SetPlane( 1, entityPlaneOffset.GetI() ); //    -  
              axis2PlanesDefinition->SetPlane( 2, basePlane.GetI() ); //    -  XOY
              b = SysAllocString( L"   " );
              entityAxis2Planes->SetName( b ); //   
              SysFreeString( b );
              entityAxis2Planes->Create();  //  ,     

              Message( "       " );

              //     XOZ
              basePlane.SetI( part->GetDefaultEntity( o3d_planeXOZ ) );
              b = SysAllocString( L"XOZ" );
              basePlane->SetName( b ); //    
              SysFreeString( b );  
              basePlane->Update(); //    
                                     
              axis2PlanesDefinition->SetPlane( 2, basePlane.GetI() ); //    -  XOZ
              entityAxis2Planes->Update(); //    

              Message( "     \n    45" );

              //       
              IUEnv <IEntity> entityPlaneAngle( part->NewEntity( o3d_planeAngle ) );
              if ( entityPlaneAngle ) 
              {
                //        
                LPUNKNOWN pDefinitionPlaneAngle = entityPlaneAngle->GetDefinition();     
                if ( pDefinitionPlaneAngle ) 
                {
                  //       
                  IUPTR( PlaneAngleDefinition ) planeAngleDefinition( pDefinitionPlaneAngle );
                  if ( planeAngleDefinition ) 
                  {
                    planeAngleDefinition->SetAngle( 45 ); //     
                    planeAngleDefinition->SetPlane( entityPlaneOffset.GetI() ); //   -  
                    planeAngleDefinition->SetAxis( entityAxis2Planes.GetI() ); //   - ,     
                    b = SysAllocString( L"     " );
                    entityPlaneAngle->SetName( b );  //   
                    SysFreeString( b );
                    entityPlaneAngle->Create(); //       

                    Message( "    " );

                    planeAngleDefinition->SetPlane( basePlane.GetI() ); //   XOZ   
                    entityPlaneAngle->Update(); //    
                  }
                  pDefinitionPlaneAngle->Release(); //  , AddRef   
                }
              }
            }
            pDefinitionAxis2Planes->Release(); //  , AddRef   
          }
        }
      }
      pDefinitionPlaneOffset->Release(); //  , AddRef   
    }
  }
}