// Name        : Elements A / Элементы А
// Version     : 23 dec 2013
// Author      : LODka3D
// Discription : Примеры создания примитивов не добавляя треугольники, а 
//               функциями ЛОДки.  

{$INCLUDE 'vectorgeometry.dws'} 
{$INCLUDE 'addpoints.dws'}

  // Функция в которой в ЛОДку добавляются примитивы.
procedure LODPCreatePrimitive;
var
  b1, b2 : Boolean;
  m1, m2 : TMatrix;
  i1, Elem1, Cnt1, Cnt2  : Integer;
  sPt0, sPtM, sTr0 : string;
  f1, f2,  fl1, fl2, fl3, fl4, fl5, fl6, fl7 : Float;
begin
  LOD('SetPMessage', '');

    // Читаем из окошек параметры установленные пользователем.
  Elem1 := StrToInt(LOD('GetPControl', 'Element'));
  Cnt1  := StrToInt(LOD('GetPControl', 'Cnt1'));
  Cnt2  := StrToInt(LOD('GetPControl', 'Cnt2'));
  b1    := LOD('GetPControl', 'Boolean1') <> '0'; 
  b2    := LOD('GetPControl', 'Boolean2') <> '0';
  fl1   := StrToFloat(LOD('GetPControl', 'Float1')); 
  fl2   := StrToFloat(LOD('GetPControl', 'Float2')); 
  fl3   := StrToFloat(LOD('GetPControl', 'Float3')); 
  fl4   := StrToFloat(LOD('GetPControl', 'Float4')); 
  fl5   := StrToFloat(LOD('GetPControl', 'Float5')); 
  fl6   := StrToFloat(LOD('GetPControl', 'Float6')); 
  fl7   := StrToFloat(LOD('GetPControl', 'Float7')); 
  sPt0  := LOD('GetPPointsCount'); sPtM := sMaxInt; // Читаем число точек.
  sTr0  := LOD('GetPTrigsCount');                // Читаем число треугольников.
  m1    := IdentityHmgMatrix; // Начальная матрица.
  
    // Создаём разные объекты в зависимости от выбора пользователя.
  if Elem1 = 0 then begin // Cube  
    m1[3] := VectorMake(0, 0, 0.5);    // Ставим матрице положение (0, 0, 0.5)   
    Add4Pt(m1, 0.5, 0.5); // Добавляем 4 точки по матрице m1 масштаба 0.5-0.5 .
      // Выбираем точки. sPt0 и sPtM - диапазон точек с которым работаем.
    LOD('PSelectPt', '1', sPt0, sPtM); 
      // Создаём плоскость по точкам проецируя их на плоскость x-y, заданную
      //  перпендикуляром к её поверхности (0;0;1).
    LOD('PTriangulate', '(0;0;1)', sPt0, sPtM); 
    LOD('PSelectTr', '1', sTr0, sPtM);    // Выбираем созданные треугольники.
    LOD('PHollow', '1', '2', sPt0, sPtM); // Создаём из плоскости объём ( куб ).
    LOD('PSelectTr', '1', sTr0, sPtM);    // Выбираем все треугольники.
      // Авторасчёт групп сглаживания. 30 - предельный угол в градусах.
    LOD('PAutosmooth', '30', sPt0, sPtM); 
      // Автоотекстуривание коробкой. 0.002 - объединять точки, которые ближе 
      //  чем на 0.002. 
    LOD('PCoverTxBox', '0.002', spt0, sPtM);
       
  end else if Elem1 = 1 then begin // Box
    m1[3] := VectorMake(0, 0, -0.5);   
    Add4Pt(m1, 0.5, 0.5, b1);
    LOD('PSelectPt', '1', sPt0, sPtM);
    LOD('PTriangulate', '(0; 0; -1)', sPt0, sPtM);
    LOD('PSelectTr', '1', sTr0, sPtM);
    LOD('PHollow', '1', '1', sPt0, sPtM);
    LOD('PSelectTr', '1', sTr0, sPtM);
    LOD('PHollow', FloatToStr(fl5), '2', sPt0, sPtM);
    if fl5 < 0 then LOD('PInvSelNormal', spt0, sPtM);
    LOD('PSelectTr', '1', sTr0, sPtM);
    LOD('PAutosmooth', '30', sPt0, sPtM);      
    LOD('PCoverTxPlane', '(1;0;0)', '(0;1;0)', '0.002', spt0, sPtM);
    
  end else if Elem1 = 2 then begin // Cylinder
    m1[3] := VectorMake(0, 0, 0.5);   
    AddCircle(m1, Cnt1, fl3, fl4, fl1, fl2, b1, true);
    LOD('PSelectPt', '1', sPt0, sPtM);
    LOD('PTriangulate', '(0; 0; 1)', sPt0, sPtM);
    LOD('PSelectTr', '1', sTr0, sPtM);
    LOD('PHollow', '1', '2', sPt0, sPtM);
    LOD('PSelectTr', '1', sTr0, sPtM);    
    LOD('PAutosmooth', '30', sPt0, sPtM);
    LOD('PCoverTxCyl', '(1;0;0)', '(0;0;1)', '0.002', spt0, sPtM);
      // Отекстуриваем верх и низ.
    LOD('PSelectTr', '0', sTr0, sPtM);
    LOD('PSelectTrSphere', '(0;0; 0.5)', FloatToStr(fl3*1.01), '1', '1', sPt0, sPtM);
    LOD('PSelectTrSphere', '(0;0;-0.5)', FloatToStr(fl3*1.01), '1', '1', sPt0, sPtM);
    LOD('PCoverTxPlane', '(1;0;0)', '(0;1;0)', '0.002', spt0, sPtM);
    
  end else if Elem1 = 3 then begin // Annaulus
    m1[3] := VectorMake(0, 0, 0.5);   
    AddCircle(m1, Cnt1, fl3, fl4, fl1, fl2, b1, true);
    AddCircle(m1, Cnt1, fl3*0.5, fl4*0.5, fl1, fl2, b1, true);
    LOD('PSelectPt', '1', sPt0, sPtM);
    LOD('PTriangulate', '(0; 0; 1)', sPt0, sPtM);
      // Выделить треугольники попадающие в сферу позиции (0;0;0.5) и 
      //  радиуса fl3*0.5 . 
    LOD('PSelectTrSphere', '(0;0;0.5)', FloatToStr(fl3*0.5), '1', '1', sPt0, sPtM);
    LOD('PDeleteSelTr', sPt0, sPtM);
    LOD('PSelectTr', '1', sTr0, sPtM);
    LOD('PHollow', '1', '2', '0', '1000');
    LOD('PSelectTr', '1', sTr0, sPtM);    
    LOD('PAutosmooth', '30', sPt0, sPtM);
    LOD('PCoverTxCyl', '(1;0;0)', '(0;0;1)', '0.002', spt0, sPtM);
      // Отекстуриваем верх и низ.
    LOD('PSelectTr', '0', sTr0, sPtM);
    LOD('PSelectTrSphere', '(0;0; 0.5)', FloatToStr(fl3*1.01), '1', '1', sPt0, sPtM);
    LOD('PSelectTrSphere', '(0;0;-0.5)', FloatToStr(fl3*1.01), '1', '1', sPt0, sPtM);
    LOD('PCoverTxPlane', '(1;0;0)', '(0;1;0)', '0.002', spt0, sPtM);
    
  end else if Elem1 = 4 then begin // 2 Cylinders
    AddCircle(m1, Cnt1, fl3, fl4, fl1, fl2, b1, true);
    AddCircle(m1, Cnt1, fl3*0.5, fl4*0.5, fl1, fl2, b1, true);
    LOD('PSelectPt', '1', sPt0, sPtM);
    LOD('PTriangulate', '(0; 0; 1)', sPt0, sPtM);
    LOD('PSelectTr', '1', sTr0, sPtM);
    LOD('PHollow', '0.5', '2', '0', '1000');
    LOD('PSelectTr', '0', sTr0, sPtM);
    LOD('PSelectTrSphere', '(0;0;0)', FloatToStr(fl3*0.5), '1', '1', sPt0, sPtM);
      // Вытягиваем выделенные треугольники вверх, по вектору '(0;0;1)'.
    LOD('PStretchTr', '(0;0;1)', '0.5', sPt0, sPtM);
    LOD('PSelectTr', '1', sTr0, sPtM);    
    LOD('PAutosmooth', '30', sPt0, sPtM);
    LOD('PCoverTxCyl', '(1;0;0)', '(0;0;1)', '0.002', spt0, sPtM);
      // Отекстуриваем верх и низ.
    LOD('PSelectTr', '0', sTr0, sPtM);
    LOD('PSelectTrSphere', '(0;0; 0.5)', FloatToStr(fl3*0.51), '1', '1', sPt0, sPtM);
    LOD('PSelectTrSphere', '(0;0;-0.5)', FloatToStr(fl3*1.01), '1', '1', sPt0, sPtM);
    LOD('PCoverTxPlane', '(1;0;0)', '(0;1;0)', '0.002', spt0, sPtM);
    
  end else if Elem1 = 5 then begin // Oval
    m1[3] := VectorMake(+0.5, 0, 0.5);   
    AddCircle(m1, Cnt1 div 2,  fl3, fl4,  270, 180,  b1, true);
    m1[3] := VectorMake(-0.5, 0, 0.5);   
    AddCircle(m1, Cnt1 div 2,  fl3, fl4,   90, 180,  b1, true);
    if b1 then begin
      m1[3] := VectorMake(+0.5, 0, 0.5);   
      AddCircle(m1, Cnt1,  fl6, fl6, 0, 360,  b1, true);
      m1[3] := VectorMake(-0.5, 0, 0.5);   
      AddCircle(m1, Cnt1,  fl6, fl6, 0, 360,  b1, true);
    end;  
    LOD('PSelectPt', '1', sPt0, sPtM);
    LOD('PTriangulate', '(0; 0; 1)', sPt0, sPtM);
      // Создание отверстий. Удаляем лишние треугольники, выделяя их сферой.
    if b1 then begin
      LOD('PSelectTr', '0', sTr0, sPtM);
      LOD('PSelectTrSphere', '( 0.5;0;0.5)', FloatToStr(fl6*1.01), '1', '1', sPt0, sPtM);
      LOD('PSelectTrSphere', '(-0.5;0;0.5)', FloatToStr(fl6*1.01), '1', '1', sPt0, sPtM);
      LOD('PDeleteSelTr', sPt0, sPtM);
    end;  
    LOD('PSelectTr', '1', sTr0, sPtM);
    LOD('PHollow', '1', '2', sPt0, sPtM);
    LOD('PSelectTr', '1', sTr0, sPtM);
    LOD('PAutosmooth', '30', sPt0, sPtM);      
    LOD('PCoverTxPlane', '(1;0;0)', '(0;1;0)', '0.002', spt0, sPtM);
    LOD('AddPMessage', 'b1 - hole'#13#10'float3,4,6 - radius'#13#10
      +'cnt1,2 - parts count'#13#10#13#10);
    
  end else if Elem1 = 6 then begin // AntiOval
    if b1 then begin // Антиовал вдоль оси Y
      m1[3] := VectorMake(0, +1, 0.5);   
      AddCircle(m1, Cnt1 div 2,  fl3, fl4,  180, 180,  b1, true);
      m1[3] := VectorMake(0, -1, 0.5);   
      AddCircle(m1, Cnt1 div 2,  fl3, fl4,    0, 180,  b1, true);
        // Добавляем 4 точки, а то триугольники будут слишком длинными.
      m1[3] := VectorMake(0, 0, 0.5);   
      Add4Pt(m1, 0.5, 0.5, b1);
    end else begin // Антиовал вдоль оси X
      m1[3] := VectorMake(+1, 0, 0.5);   
      AddCircle(m1, Cnt1 div 2,  fl3, fl4,   90, 180,  b1, true);
      m1[3] := VectorMake(-1, 0, 0.5);   
      AddCircle(m1, Cnt1 div 2,  fl3, fl4,  270, 180,  b1, true);
      m1[3] := VectorMake(0, 0, 0.5);   
      Add4Pt(m1, 0.5, 0.5, b1);
    end;  
    LOD('PSelectPt', '1', sPt0, sPtM);
    LOD('PTriangulate', '(0; 0; 1)', sPt0, sPtM);
      // Выделяем сферой и удаляем лишние треугольники с боков.
    LOD('PSelectTr', '0', sTr0, sPtM);
    if b1 then begin
      LOD('PSelectTrSphere', '(0; 1;0.5)', FloatToStr(fl3*1.01), '1', '1', sPt0, sPtM);
      LOD('PSelectTrSphere', '(0;-1;0.5)', FloatToStr(fl3*1.01), '1', '1', sPt0, sPtM);
    end else begin
      LOD('PSelectTrSphere', '( 1;0;0.5)', FloatToStr(fl3*1.01), '1', '1', sPt0, sPtM);
      LOD('PSelectTrSphere', '(-1;0;0.5)', FloatToStr(fl3*1.01), '1', '1', sPt0, sPtM);
    end;
    LOD('PDeleteSelTr', sPt0, sPtM);
      // Доделываем антиовал.
    LOD('PSelectTr', '1', sTr0, sPtM);
    LOD('PHollow', '1', '2', sPt0, sPtM);
    LOD('PSelectTr', '1', sTr0, sPtM);
    LOD('PAutosmooth', '30', sPt0, sPtM);      
    LOD('PCoverTxPlane', '(1;0;0)', '(0;1;0)', '0.002', spt0, sPtM);
    
  end else if Elem1 = 7 then begin // Round cube 2D 
        // Добавляем точки по четырём четвертьокружностям.
    m1[3] := VectorMake(+0.5, +0.5, 0.5);   
    AddCircle(m1, Cnt1 div 4,  fl3, fl4,    0, 90,  b1, true);
    m1[3] := VectorMake(-0.5, +0.5, 0.5);   
    AddCircle(m1, Cnt1 div 4,  fl3, fl4,   90, 90,  b1, true);
    m1[3] := VectorMake(-0.5, -0.5, 0.5);   
    AddCircle(m1, Cnt1 div 4,  fl3, fl4,  180, 90,  b1, true);
    m1[3] := VectorMake(+0.5, -0.5, 0.5);   
    AddCircle(m1, Cnt1 div 4,  fl3, fl4,  270, 90,  b1, true);
    LOD('PSelectPt', '1', sPt0, sPtM);
    LOD('PTriangulate', '(0; 0; 1)', sPt0, sPtM);
    if b1 then begin
        // Создаём дыру удаляя средние треугольники.      
      LOD('PSelectTrSphere', '(0;0;0.5)', FloatToStr(fl3*0.5), '1', '1', sPt0, sPtM);
      LOD('PDeleteSelTr', sPt0, sPtM);
    end;
    LOD('PSelectTr', '1', sTr0, sPtM);
    LOD('PHollow', '1', '2', sPt0, sPtM);
    LOD('PSelectTr', '1', sTr0, sPtM);
    LOD('PAutosmooth', '40', sPt0, sPtM);      
    LOD('PCoverTxPlane', '(1;0;0)', '(0;1;0)', '0.002', spt0, sPtM);
    LOD('AddPMessage', 'b1 - hole'#13#10#13#10);
    
  end else if Elem1 = 8 then begin // Corner 
    m1[3] := VectorMake(0, 0, 0);       
    AddCircle(m1, Cnt1,  fl3, fl4,    90, 180, b1, true);
    AddCircle(m1, Cnt2,  fl6, fl6,     0, 360, b1, true);
    Add1Pt(VectorMake(0.5, 0.5,m1[3][2]));
    Add1Pt(VectorMake(0.5,-0.5,m1[3][2]));
    LOD('PSelectPt', '1', sPt0, sPtM);
    LOD('PTriangulate', '(0; 0; -1)', sPt0, sPtM);
    LOD('PSelectTr', '0', sTr0, sPtM);
      // Создаём дыру удаляя средние треугольники.      
    LOD('PSelectTrSphere', VectorToStr(m1[3]), FloatToStr(fl6*1.01), '1', '1', sPt0, sPtM);
    LOD('PDeleteSelTr', sPt0, sPtM);
      // Клонируем петлю, и ставим вторую петлю вертикально на матрицу m2. 
    LOD('PSelectTr', '1', sTr0, sPtM);
    LOD('PCloneSelTr', '1', sTr0, sMaxInt);
    m2 := m1;
    m2[0] := VectorMake(0,  0, -1);
    m2[1] := VectorMake(0, -1,  0);
    m2[3] := VectorMake(0.5, 0, 0.5);
    LOD('PSelPtToMatrix', MatrixToStr(m2), '1', spt0, sMaxInt);
    LOD('PSelectPt', '1', sPt0, sPtM);
      // Сдвигаем все точки вниз на 0.5.
    m1[3] := VectorMake(0, 0, 0.5);       
    LOD('PSelPtToMatrix', MatrixToStr(m1), '1', spt0, sMaxInt);
      // Объединяем близкие точки, чтобы фигура была единой.
    if b1 then   
      LOD('PCombNearSelPt', '0.001', sPt0, sMaxInt);      
    // LOD('PSnapPt', '0.001', sPt0, sMaxInt);
      // Придаём уголку объём.
    LOD('PSelectTr', '1', sTr0, sPtM);
    LOD('PHollow', FloatToStr(fl1), '2', sPt0, sPtM);
    if fl1 < 0 then LOD('PInvSelNormal', spt0, sPtM);
    LOD('PSelectTr', '1', sTr0, sPtM);
    LOD('PAutosmooth', '40', sPt0, sPtM);
    LOD('PCoverTxBox', '0.002', spt0, sPtM);      
  end else if Elem1 = 9 then begin // Sphere
    m1[3] := VectorMake(0, 0, 0);       
      // Ставим две точки, вверху сферы и внизу.
    Add1Pt(VectorMake(0,0,+0.5));
    Add1Pt(VectorMake(0,0,-0.5));
      // Расставляем вершины по поясам сферы. 
    Cnt1 := EnsureRange(Cnt1, 3, 1000);
    Cnt2 := EnsureRange(Cnt2, 3, 1000);
    Cnt2 := (Cnt2 div 2)*2 +1; // Без этого при чётных числах получается дыра.
    for i1 := 0 to Cnt2 -1 do begin
      f1 := cPiDiv2 +(i1+1)*(cPi/(Cnt2+1));
      m1[3] := VectorMake(0, 0, Sin(f1)*0.5);
      f2 := Cos(f1)*0.5;
      AddCircle(m1, Cnt1,  f2, f2, fl1, fl2, b1, false);
    end;
      // Триангулируем, строим группы сглаживания, отекстуриваем.
    LOD('PSelectPtBox', MatrixToStr(m1), '(-1;-1;-0.001)', '(1;1;1)', '1', '1', sPt0, sMaxInt);
    LOD('PTriangulate', '(0; 0; 1)', sPt0, sPtM);
    LOD('PSelectPt', '0', sPt0, sPtM);
    LOD('PSelectPtBox', '', '(-1;-1;-1)', '(1;1;0.001)', '1', '1', sPt0, sMaxInt);
    LOD('PTriangulate', '(0; 0; -1)', sPt0, sPtM);
    LOD('PSelectTr', '1', sTr0, sPtM);
    LOD('PAutosmooth', '180', sTr0, sPtM);
    LOD('PCoverTxCyl', '(1;0;0)', '(0;0;1)', '0.002', spt0, sPtM);
    // LOD('PCoverTxBox', '0.002', spt0, sPtM); // Вариант отекстуривания.    
  // end else if Elem1 = 10 then begin // ...
  end else begin
    // 
  end;

    // Делаем деселект всем вершинам и треугольникам.
  // LOD('PSelectPt', '0', sTr0, sPtM); LOD('PSelectTr', '0', sTr0, sPtM);

    // Выводит дог функции LOD. Для отладки, чтобы посмотреть порядок вызова  
    //  функций через LOD и с какими параметрами они вызывалась. 
  LOD('AddPMessage', LOD('GetLODLog'));
end;

procedure LODPCreateControls;
var
  St1 : TLODStr;
begin
  LOD('AddPControl', 'Boolean1', 'Bool', '',   'Boolean 1', '');
  LOD('AddPControl', 'Boolean2', 'Bool', '',   'Boolean 2', '');

  LOD('AddPControl', 'Cnt1',     'Int',  '18', 'Count 1',   '', '0', '1000');
  LOD('AddPControl', 'Cnt2',     'Int',  '18', 'Count 2',   '', '0', '1000');

  LOD('AddPControl', 'Float1', 'Float', '0.1', 'Float1', '', sMinInt, sMaxInt);
  LOD('AddPControl', 'Float2', 'Float', '360', 'Float2', '', sMinInt, sMaxInt);
  LOD('AddPControl', 'Float3', 'Float', '0.5', 'Float3', '', sMinInt, sMaxInt);
  LOD('AddPControl', 'Float4', 'Float', '0.5', 'Float4', '', sMinInt, sMaxInt);
  LOD('AddPControl', 'Float5', 'Float', '-0.2', 'Float5', '', sMinInt, sMaxInt);
  LOD('AddPControl', 'Float6', 'Float', '0.2', 'Float6', '', sMinInt, sMaxInt);
  LOD('AddPControl', 'Float7', 'Float', '0.2', 'Float7', '', sMinInt, sMaxInt);

  LOD('AddPControl',    'Element', 'Combo',   '0', 'Mode', 'Select element',
   'Cube'#13#10'Box'#13#10'Cylinder'#13#10'Annaulus'#13#10
   +'2 Cylinders'#13#10'Oval'#13#10'AntiOval'#13#10'RoundCube'#13#10
   +'Coner'#13#10'Sphere');

  // if LOD('GetLanguage') = '25' then begin 
  // end else begin
  // end;
end;
