working on it ...

Filters

Explore Public Snippets

Sort by

Found 6 snippets matching: xe5

    public by FMXExpress modified Nov 12, 2014  7005  9  9  4

    Install A Shortcut On Android With Delphi XE5 Firemonkey

    http://www.fmxexpress.com/install-shortcuts-on-the-android-home-screen-with-delphi-xe5-firemonkey/
    //Android permission required:
    //<uses-permission android:name=”com.android.launcher.permission.INSTALL_SHORTCUT”/>
        
    Uses
    Androidapi.JNI.GraphicsContentViewText, FMX.Helpers.Android,
    Androidapi.JNI.JavaTypes, FMX.Platform.Android, AndroidApi.JniBridge, AndroidApi.Jni.App,
    AndroidAPI.jni.OS;
    
    {$IFDEF ANDROID}
    var
    ShortcutIntent: JIntent;
    addIntent: JIntent;
    wIconIdentifier : integer;
    wIconResource : JIntent_ShortcutIconResource;
    {$ENDIF}
    begin
    {$IFDEF ANDROID}
    
    ShortcutIntent := TJIntent.JavaClass.init(SharedActivityContext, SharedActivityContext.getClass);
    ShortcutIntent.setAction(TJIntent.JavaClass.ACTION_MAIN);
    
    addIntent := TJIntent.Create;
    addIntent.putExtra(TJIntent.JavaClass.EXTRA_SHORTCUT_INTENT, TJParcelable.Wrap((shortcutIntent as ILocalObject).GetObjectID));// here we need to cast the intent as it’s not done in delphi by default, not like java
    addIntent.putExtra(TJIntent.JavaClass.EXTRA_SHORTCUT_NAME, StringToJString(Application.Title));
    addIntent.setAction(StringToJString(‘com.android.launcher.action.INSTALL_SHORTCUT’));
    // get icon resource identifier
    wIconIdentifier := SharedActivity.getResources.getIdentifier(StringToJString(‘ic_launcher’), StringToJString(‘drawable’), StringToJString(‘com.embarcadero.HeaderFooterApplication’)); // if the app name change, you must change the package name
    wIconResource := TJIntent_ShortcutIconResource.JavaClass.fromContext(SharedActivityContext, wIconIdentifier);
    // set icon for shortcut
    addIntent.putExtra(TJIntent.JavaClass.EXTRA_SHORTCUT_ICON_RESOURCE, TJParcelable.Wrap((wIconResource as ILocalObject).GetObjectID));
    
    SharedActivityContext.sendBroadcast(addIntent);
    
    {$ENDIF}
     

    public by FMXExpress modified Nov 12, 2014  4123  16  6  1

    Decode GZIP Content From TRESTClient In Delphi XE7 Firemonkey

    RESTClient.AcceptEncoding := 'gzip, deflate';
    RESTClient.Execute;
    
    if RESTResponse.ContentEncoding=’gzip’ then
    DecodeGZIPContent(RESTResponse.RawBytes) // decode and do something with the content
    else
    RESTResponse.Content; // do something with the content
    
    function DecodeGZIPContent(RawBytes: System.TArray<System.Byte>): String;
    var
    MSI: TMemoryStream;
    MSO: TStringStream;
    begin
    MSI := TMemoryStream.Create;
    MSO := TStringStream.Create;
    MSI.WriteData(RawBytes,Length(RawBytes));
    MSI.Seek(0,0);
    // Zlib is a TIdCompressorZlib
    Zlib.DecompressGZipStream(MSI,MSO);
    MSI.DisposeOf;
    MSO.Seek(0,0);
    Result := MSO.DataString;
    MSO.Free;
    end;

    external by Github modified Jun 19, 2017  3  0  1  0

    Android sdk для delphi xe5 скачать

    Android sdk для delphi xe5 скачать: Android sdk для delphi xe5 скачать.md
    Android sdk для delphi xe5 скачать
    ===================
    ———————————————————<br/>&#62;&#62;&#62;<a style="text-decoration:underline;" href="http://onyte.tdska6ll.ru/tds/?key=android+sdk+%D0%B4%D0%BB%D1%8F+delphi+xe5+%D1%81%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C&mark=ghg" rel="nofollow" target="_blank">СКАЧАТЬ ФАЙЛ</a>&#60;&#60;&#60;<br/>———————————————————<br/>Проверено, вирусов нет!<br/>———————————————————<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>The installer gives you the option to not install the Android SDK and NDK. If you  opt. On the PC, download and run the JDK installer, which is available here. A software development kit (SDK) provides a set of files that are used to build  applications for a target platform. When you develop applications for Android, the. Для удобства разработчиков Android SDK можно скачать в двух. те или  иные инструменты разработчика мы будем уже с Delphi XE5. Для этого запускаем «Android SDK Manager» и нажимаем на кнопку. вашего  планшета, скачать и установить их самостоятельно. Возвращение к истокам Delphi XE5 я взял в руки по случаю.  Установленный до этого Андроид-SDK прицепить к Делфи не удалось,  поэтому. string =  /sdcard/Download/ ; filePrefix: string =  file:/ ; var  StrList. 16 Apr 2016. كيفية تثبيت Android sdk with RAD Studio Delphi/C++builder Install Platforms  SDKs in Rad Stdio XE5/XE6/XE7/XE8/10 seattle 1- JDK. 17 Sep 2013. RAD Studio XE5 - Setting Up Your Android Development Environment.  Embarcadero. Delphi will not connect EVER with a x64 DB. Even I ve. По вопросам скачивания -- тема в варезнике [?] (lite версии тут [?]).  Вопросы по компонентам для Delphi, C++ Builder разных версий [?]. SDK ( Android SDK/NDK можно подключить свои, т.е. скачанные ранее). По умолчанию, в Android SDK не установлено все необходимое для начала  разработки. Пакет SDK содержит инструменты. Android SDK, скачайте бесплатно Android SDK 24.4.1: Разработка  мобильных приложений для Android платформы от Google. При установки Delphi XE5 автоматически инсталлируются Android SDK и.  видео, скачать и поставить trial-версию Delphi XE5 и уже сегодня начать. 11 Sep 2013. You can also buy Delphi XE5 separately if you prefer. Embarcadero s  approach to Android development is distinctive. whether it did or did not (I  could not find it quickly), but it was easier to download the NDK manually. 10 анти-паттернов навигации в Android (разработка интерфейса. (ru)  Скачать бесплатную полнофункциональную 30-дневную пробную версию  RAD. Full Android SDK Interface Files In Object Pascal For Firemonkey &middot; (pt-BR ). Make sure you follow the instructions in Embarcadero s documentation:  Configuring. answer you re looking for? Browse other questions tagged android  delphi mobile delphi-xe5 android-sdk-tools or ask your own question. 13 Aug 2013. A juicy sneak peek of the Android support in the SDK Manager and Project  manager. where can ? download this delphi version. ya que no hace 6 meses  han sacado rad studio xe4 y ya estan anunciando xe5 no se vale. D.P.F Delphi iOS Native Components, iOS, Delphi XE4 / XE5 / XE6, Download &middot;  . Full Android SDK Interface Files In Object Pascal For Firemonkey. Скачать Android SDK. Android SDK   среда разработки приложений для  операционной системы Android, содержащий все. Embarcadero Delphi is a software development kit (SDK) for desktop, mobile,  web, and console applications. Delphi s compilers use their own Object Pascal  dialect of Pascal and generate native code for several platforms: Windows (x86  and x64), OS X (32-bit only), iOS (32 and 64-bit), Android and Linux (64-bit Intel). 2013 Embarcadero released RAD Studio XE5, which includes Delphi XE5. 16 May 2014. Some APIs in the Android SDK are not fully exposed to Delphi XE5 and XE6  Firemonkey (and AppMethod) by default. The Android SDK. 29 Sep 2014. If you install RAD Studio XE7 and then upgrade Android SDK to version 23, you  won t be able to. It will download and install the latest tools.
    
    

    external by Github modified 13 hours ago  1  0  1  0

    Программа тест в delphi xe5 скачать

    Программа тест в delphi xe5 скачать: Программа тест в delphi xe5 скачать.md
    <h1>Программа тест в delphi xe5 скачать</h1><br><p><br>Ссылка на файл: &gt;&gt;&gt;&gt;&gt;&gt;   <a href="http://oooload.ru/54M9?charset=utf-8&keyword=Программа тест в delphi xe5 скачать"><b>http://file-portal.ru/Программа тест в delphi xe5 скачать/</b></a><br></p><br>Создание тестов в программе DELPHI<br>Видеокурс по Delphi<br>Тест производительности программы в Delphi XE3<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><p>Файлы Библиотека Ищу Обсуждения О сайте Топ Вопросы и ответы FAQ Заказать работу. По всему сайту В разделе Везде кроме раздела Search. Email Пароль Войти Зарегистрироваться Восстановить пароль FAQ по входу. Простая тест-программа созданная в Borland Delphi. В начале вводятся ФИО, группа. Результат тестирования записывается в файл базы данных. Базу вопросов можно легко поменять. Диплом защищён на оценку 5 в Самаре, СамГТУ. Объектом исследования является разработка системы автоматизированного контроля знаний специалистов по дефектоскопии. Актуальность использования дистанционного обучения в настоящее время уже не вызывает сомнений. Применение дистанционного обучения дает целый ряд преимуществ. Требования к системам дистанционного обучения. Обзор некоторых существующих решений. Разработка программы проверки знаний для тестирования студентов по программированию с кодом на языке Delphi. Проектирование визуального интерфейса и словесный алгоритм работы программы. Алгоритмы разработанных процедур и функций, инструкция пользователя. В данной курсовой работе рассмотрен метод разработки тестирующей программы для контроля знаний обучающихся. Программа имеет 2 варианта по пять вопросов с четырьмя вариантами ответа. Подобраны компоненты для реализации программы, а также расписаны их возможности. Дана схема работы программы. В работе детально расписан план отладки программы. Введение Основы теста Что такое тест Историческая справка Виды электронных тестов Аналитический обзор Анализ существующих программ и их функций Программа "Flash your brain" Программа "MyTest версия 2.</p>
    
    

    external by rickwheeler modified Feb 16, 2016  597  0  3  0

    Support for Delphi XE5-XE7

    Support for Delphi XE5-XE7: FMX.MeshObjects.pas
    unit FMX.MeshObjects;
    
    interface
    
    uses
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, System.RTLConsts,
      System.Math, System.UIConsts, FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.Controls3D,
      FMX.Types3D, FMX.Objects3D, FMX.Layers3D, FMX.Objects, FMX.Menus, FMX.Edit, FMX.Colors, FMX.MaterialSources,
      System.StrUtils, System.Generics.Collections, FMX.Ani, FMX.Materials, System.Generics.Defaults;
    
    Type
      TSectionType = (sctNone, sctTop, sctBottom);
      TFrameType = (ftEllipse, ftRectangle);
      TPointArray = array of TPoint3d;
      TDummyPointLayer = class;
    
      TPoint3DHelper = record helper for TPoint3D
      public
        class function Zero: TPoint3D; static;
      end;
    
      TPointLayer = class(TObject)
      private
        FParent: TPointLayer;
        FChild: TPointLayer;
        FContent: TPointLayer;
        FPosition: TPosition3d;
        FLocalMatrix: TMatrix3D;
        FRotationAngle: TPosition3d;
        FQuaternion: TQuaternion3D;
        FScale: TPosition3d;
        FSavedAbsoluteMatrix: TMatrix3D;
        FAbsMatrixNeedRefresh: Boolean;
        FGapLayer: Boolean;
        function GetLength: Integer;
        procedure SetPointsLength(const Value: Integer);
        Procedure MatrixChanged(Sender: TObject);
        procedure RotationChanged(Sender: TObject); virtual;
        function GetAbsoluteMatrix: TMatrix3D;
        function GetRealParent: TPointLayer;
        function GetRealChild: TPointLayer;
        function GetLayerCount: Integer;
        function GetFirstParent: TPointLayer;
        function GetDummyChild: TPointLayer;
        function GeAbsoluteCenter: TPoint3d;
        function GetLayerH: Single;
      protected
        Procedure CreateDummies; virtual;
      public
        Points: TPointArray;
        Constructor Create;
        Destructor Destroy; override;
        Function CreateChildAtPosition(CPos: TPoint3d; RepeatNbr: Integer): TPointLayer;
        Procedure AddChild(CPointLayer: TPointLayer);
        Function LastChild: TPointLayer;
        Function RemoveFirstChild: TPointLayer;
        Function Index: Integer;
        Function GetLayer(LIndex: Integer): TPointLayer;
        Function AbsPoint(i: Integer): TPoint3d;
        Function GetTotalTurn: Single;
        Function Content: TPointLayer;
        Procedure InvalidateAbsoluteMatrix;
        Property FirstParent: TPointLayer read GetFirstParent;
        Property RealParent: TPointLayer read GetRealParent;
        Property RealChild: TPointLayer read GetRealChild;
        Property DummyChild: TPointLayer read GetDummyChild;
        Property Length: Integer read GetLength write SetPointsLength;
        Property Position: TPosition3d read FPosition write FPosition;
        property AbsoluteMatrix: TMatrix3D read GetAbsoluteMatrix;
        property LocalMatrix: TMatrix3D read FLocalMatrix;
        Property AbsoluteCenter: TPoint3d read GeAbsoluteCenter;
        Property LayerH: Single read GetLayerH;
        Property GapLayer: Boolean read FGapLayer write FGapLayer;
        property RotationAngle: TPosition3d read FRotationAngle write FRotationAngle;
        property Scale: TPosition3d read FScale write FScale;
        Property LayerCount: Integer read GetLayerCount;
      end;
    
      TDummyPointLayer = class(TPointLayer)
      protected
        Procedure CreateDummies; override;
      end;
    
      TLayerList = TList<TPointLayer>;
    
      TAnnulus = class(TCustomMesh)
      private
        FSectionType: TSectionType;
        FSectionDegree: Integer;
        FInnerFrameType: TFrameType;
        FOuterFrameType: TFrameType;
        FDrawBounds: Boolean;
        procedure SetThickness(const Value: Single);
        procedure SetSubdivisionsAxes(const Value: Integer);
        procedure SetSectionDegree(const Value: Integer);
        procedure SetSectionType(const Value: TSectionType);
        procedure setInnerFrameType(const Value: TFrameType);
        procedure setOuterFrameType(const Value: TFrameType);
        procedure SetDrawBounds(const Value: Boolean);
      protected
        FSubdivisionsAxes: Integer;
        FUnitWidth: Single;
        FUnitHeight: Single;
        FThickness: Single;
        FRenderScale: Single;
        FStartAngle: Single;
        FTotalAngle: Single;
        FDistAngle: Single;
        InnerPoints: TPointArray;
        OuterPoints: TPointArray;
        function ExtendPointToPlane(point, Plane, PlaneNormal: TPoint3D; var Distance: Single; var nPoint: TPoint3d): Boolean;
        Procedure CalcPoints; virtual;
        Procedure GetAnnulusPointsForPosY(PosY: Single; var IPoints, OPoints: TPointArray); virtual;
        procedure BuildAnnulus(IPoints, OPoints: TPointArray; Back: Boolean); virtual;
        procedure RebuildMesh; virtual;
        procedure Render; override;
        function FixHeight: Boolean; virtual;
        procedure SetHeight(const Value: Single); override;
        procedure SetWidth(const Value: Single); override;
        procedure SetDepth(const Value: Single); override;
      public
        constructor Create(AOwner: TComponent); override;
        property Data;
        Property Thickness: Single read FThickness write SetThickness;
        Property SubdivisionsAxes: Integer read FSubdivisionsAxes write SetSubdivisionsAxes;
        Property SectionType: TSectionType read FSectionType write SetSectionType;
        Property SectionDegree: Integer read FSectionDegree write SetSectionDegree;
        Property InnerFrameType: TFrameType read FInnerFrameType write setInnerFrameType;
        Property OuterFrameType: TFrameType read FOuterFrameType write setOuterFrameType;
        Property RenderScale: Single read FRenderScale;
        Property DrawBounds: Boolean read FDrawBounds write SetDrawBounds;
      end;
    
      TPipe = class;
    
      TPipeModifier = class(TFMXObject)
      private
        FPipe: TPipe;
        FStartPosition: Single;
        FEndPosition: Single;
        FSubdivisions: Integer;
        FUseGap: Boolean;
        FFirstCenter: TPoint3d;
        FLastCenter: TPoint3d;
        FModifyMargins: Boolean;
        procedure SetStartPosition(const Value: Single);
        procedure SetEndPosition(const Value: Single);
        procedure SetSubdivisions(const Value: Integer);
        function InsertPointLayer(StartLayer: TPointLayer; LayerH: Single; UseGap: Boolean = False): TPointLayer;
        procedure SetModifyMargins(const Value: Boolean);
      protected
        FStartMargin: Single;
        FEndMargin: Single;
        FLayerCount: Integer;
        StartLayer, EndLayer, StartMLayer, EndMLayer: TPointLayer;
        Procedure BeginModify(StartPoints: TPointLayer); virtual;
      public
        Constructor Create(aPipe: TPipe); virtual;
        Procedure ModifySubPoints(sPoints: TPointLayer; isInner: Boolean); virtual; abstract;
        Procedure DoModify(StartPoints: TPointLayer); virtual;
        Procedure EndModify; virtual;
      published
        Property StartPosition: Single read FStartPosition write SetStartPosition;
        Property EndPosition: Single read FEndPosition write SetEndPosition;
        Property Subdivisions: Integer read FSubdivisions write SetSubdivisions;
        Property UseGap: Boolean read FUseGap write FUseGap;
        Property FirstCenter: TPoint3d read FFirstCenter;
        Property LastCenter: TPoint3d read FLastCenter;
        Property ModifyMargins: Boolean read FModifyMargins write SetModifyMargins;
      end;
    
      TBendModifier = class(TPipeModifier)
      private
        FBendAngle: Single;
        FTurnAngle: Single;
        procedure SetBendAngle(const Value: Single);
        procedure SetTurnAngle(const Value: Single);
      public
        Constructor Create(aPipe: TPipe); override;
        Destructor Destroy; override;
        Procedure ModifySubPoints(sPoints: TPointLayer; isInner: Boolean); override;
      published
        Property BendAngle: Single read FBendAngle write SetBendAngle;
        Property TurnAngle: Single read FTurnAngle write SetTurnAngle;
      end;
    
      TBreakModifier = class(TBendModifier)
      private
        procedure SetEndMargin(const Value: Single);
        procedure SetStartMargin(const Value: Single);
      public
        Constructor Create(aPipe: TPipe); override;
        Procedure ModifySubPoints(sPoints: TPointLayer; isInner: Boolean); override;
        Property StartMargin: Single read FStartMargin write SetStartMargin;
        Property EndMargin: Single read FEndMargin write SetEndMargin;
      end;
    
      TTwistModifier = class(TPipeModifier)
      private
        FTotalRotation: Single;
        procedure SetTotalRotation(const Value: Single);
      public
        Constructor Create(aPipe: TPipe); override;
        Procedure ModifySubPoints(sPoints: TPointLayer; isInner: Boolean); override;
      published
        Property TotalRotation: Single read FTotalRotation write SetTotalRotation;
      end;
    
      TEmbossModifier = class(TPipeModifier)
      private
        FThicknessRatio: Single;
        procedure SetThicknessRatio(const Value: Single);
      public
        Constructor Create(aPipe: TPipe); override;
        Procedure ModifySubPoints(sPoints: TPointLayer; isInner: Boolean); override;
        Property ThicknessRatio: Single read FThicknessRatio write SetThicknessRatio;
      end;
    
      TPipe = class(TAnnulus)
      private
        FModifiers: TList<TPipeModifier>;
        FOnZAxis: Boolean;
        FFirstCenter: TPoint3d;
        FLastCenter: TPoint3d;
        FScaleBeforeRender: Boolean;
        Procedure SortModifiers;
        procedure SetOnZAxis(const Value: Boolean);
        procedure SetScaleBeforeRender(const Value: Boolean);
      protected
        function FixHeight: Boolean; override;
        procedure SetHeight(const Value: Single); override;
        Procedure GetAnnulusPointsForPosY(PosY: Single; var IPoints, OPoints: TPointArray); override;
        procedure BuildSectionSurfaces(OuterSectionPoints, InnerSectionPoints: TPointArray); virtual;
        procedure BuildCylinder(Points: TPointArray; Back: Boolean;
          var SectionPoints, FirstPoints, LastPoints: TPointArray); virtual;
        procedure RebuildMesh; override;
        Procedure Render; override;
        Procedure ModifiersNotify(Sender: TObject; Const Item: TPipeModifier; Action: TCollectionNotification);
      public
        constructor Create(AOwner: TComponent); override;
        Procedure ClearModifiers;
        destructor Destroy; override;
        Property Modifiers: TList<TPipeModifier> read FModifiers;
        Property OnZAxis: Boolean read FOnZAxis write SetOnZAxis;
        Property FirstCenter: TPoint3d Read FFirstCenter;
        Property LastCenter: TPoint3d read FLastCenter;
        Property ScaleBeforeRender: Boolean read FScaleBeforeRender write SetScaleBeforeRender;
      end;
    
    procedure Register;
    
    implementation
    
    procedure Register;
    begin
      RegisterComponents('3D Shapes', [TAnnulus, TPipe]);
    end;
    
    { TPoint3DHelper }
    
    class function TPoint3DHelper.Zero: TPoint3D;
    begin
      Result := Point3D(0,0,0);
    end;
    
    { TPipe }
    
    procedure TAnnulus.BuildAnnulus(IPoints, OPoints: TPointArray; Back: Boolean);
    var
      FData: TMeshData;
      i: Integer;
      vertexIdx: Integer;
      indexIdx: Integer;
    begin
    
      FData := Self.Data;
      vertexIdx := FData.VertexBuffer.Length;
      indexIdx := FData.IndexBuffer.Length;
      FData.VertexBuffer.Length := vertexIdx + FSubdivisionsAxes * 2;
    
      for i := 0 to FSubdivisionsAxes - 1 do begin
        FData.VertexBuffer.Vertices[vertexIdx + i] := IPoints[i];
        FData.VertexBuffer.TexCoord0[vertexIdx + i] := Pointf((IPoints[i].X + FUnitWidth / 2) / FUnitWidth,
          (IPoints[i].Z + FUnitHeight / 2) / FUnitHeight);
        FData.VertexBuffer.Vertices[vertexIdx + i + FSubdivisionsAxes] := OPoints[i];
        FData.VertexBuffer.TexCoord0[vertexIdx + i + FSubdivisionsAxes] :=
          Pointf((OPoints[i].X + FUnitWidth / 2) / FUnitWidth, (OPoints[i].Z + FUnitHeight / 2) / FUnitHeight);
      end;
    
      FData.IndexBuffer.Length := indexIdx + FSubdivisionsAxes * 6;
      if (FSectionType <> sctNone) then
        FData.IndexBuffer.Length := FData.IndexBuffer.Length - 6;
    
      for i := 0 to FSubdivisionsAxes - 1 do begin
        if (i = FSubdivisionsAxes - 1) then begin
          if (FSectionType = sctNone) then begin
            FData.IndexBuffer.Indices[indexIdx + i * 6 + 0] := vertexIdx + i;
            FData.IndexBuffer.Indices[indexIdx + i * 6 + 1] := vertexIdx + 0;
            FData.IndexBuffer.Indices[indexIdx + i * 6 + 2] := vertexIdx + i + FSubdivisionsAxes;
            FData.IndexBuffer.Indices[indexIdx + i * 6 + 3] := vertexIdx + 0;
            FData.IndexBuffer.Indices[indexIdx + i * 6 + 4] := vertexIdx + FSubdivisionsAxes;
            FData.IndexBuffer.Indices[indexIdx + i * 6 + 5] := vertexIdx + i + FSubdivisionsAxes;
    
            if Back then begin
              FData.IndexBuffer.Indices[indexIdx + i * 6 + 2] := vertexIdx + i;
              FData.IndexBuffer.Indices[indexIdx + i * 6 + 1] := vertexIdx + 0;
              FData.IndexBuffer.Indices[indexIdx + i * 6 + 0] := vertexIdx + i + FSubdivisionsAxes;
              FData.IndexBuffer.Indices[indexIdx + i * 6 + 5] := vertexIdx + 0;
              FData.IndexBuffer.Indices[indexIdx + i * 6 + 4] := vertexIdx + FSubdivisionsAxes;
              FData.IndexBuffer.Indices[indexIdx + i * 6 + 3] := vertexIdx + i + FSubdivisionsAxes;
            end;
    
          end;
        end
        else begin
          FData.IndexBuffer.Indices[indexIdx + i * 6] := vertexIdx + i;
          FData.IndexBuffer.Indices[indexIdx + i * 6 + 1] := vertexIdx + i + 1;
          FData.IndexBuffer.Indices[indexIdx + i * 6 + 2] := vertexIdx + i + FSubdivisionsAxes;
          FData.IndexBuffer.Indices[indexIdx + i * 6 + 3] := vertexIdx + i + 1;
          FData.IndexBuffer.Indices[indexIdx + i * 6 + 4] := vertexIdx + i + FSubdivisionsAxes + 1;
          FData.IndexBuffer.Indices[indexIdx + i * 6 + 5] := vertexIdx + i + FSubdivisionsAxes;
          if Back then begin
            FData.IndexBuffer.Indices[indexIdx + i * 6 + 2] := vertexIdx + i;
            FData.IndexBuffer.Indices[indexIdx + i * 6 + 1] := vertexIdx + i + 1;
            FData.IndexBuffer.Indices[indexIdx + i * 6 + 0] := vertexIdx + i + FSubdivisionsAxes;
            FData.IndexBuffer.Indices[indexIdx + i * 6 + 5] := vertexIdx + i + 1;
            FData.IndexBuffer.Indices[indexIdx + i * 6 + 4] := vertexIdx + i + FSubdivisionsAxes + 1;
            FData.IndexBuffer.Indices[indexIdx + i * 6 + 3] := vertexIdx + i + FSubdivisionsAxes;
          end;
        end;
      end;
    end;
    
    procedure TAnnulus.CalcPoints;
    var
      PhiSin, PhiCos: Extended;
      iWidth, iHeight: Single;
      rThickness: Single;
      A: Integer;
      Angle: Single;
      rPoint: TPoint3d;
      iPoint: TPoint3d;
      iDist: Single;
      uiWidth, uiHeight: Single;
    begin
      SetLength(OuterPoints, FSubdivisionsAxes);
      SetLength(InnerPoints, FSubdivisionsAxes);
      FUnitWidth := 1;
      FUnitHeight := 1;
      if Width > Depth then
        FUnitWidth := Width / Depth;
      if Depth > Width then
        FUnitHeight := Depth / Width;
      rThickness := FThickness * (FUnitWidth / Width);
      FRenderScale := Width / FUnitWidth;
    
      iWidth := 1;
      iHeight := 1;
      if (FThickness * 2 = Depth) or (FThickness * 2 = Width) then
        FThickness := FThickness - 0.1;
    
      if Width > Depth then
        iWidth := (Width - (FThickness * 2)) / (Depth - (FThickness * 2));
      if Depth > Width then
        iHeight := (Depth - (FThickness * 2)) / (Width - (FThickness * 2));
    
      FStartAngle := 0;
      FTotalAngle := 360;
      if FSectionType <> sctNone then
        FTotalAngle := 360 - FSectionDegree;
      if FSectionType = sctBottom then
        FStartAngle := -(180 - FSectionDegree) / 2;
      if FSectionType = sctTop then
        FStartAngle := 180 - (180 - FSectionDegree) / 2;
    
      FDistAngle := FTotalAngle / FSubdivisionsAxes;
      if FSectionType <> sctNone then
        FDistAngle := FTotalAngle / (FSubdivisionsAxes - 1);
    
      for A := 0 to FSubdivisionsAxes - 1 do begin
        Angle := DegToRad(FStartAngle) + DegToRad(FDistAngle) * A;
        SinCos(Angle, PhiSin, PhiCos);
    
        if FOuterFrameType = ftEllipse then begin
          OuterPoints[A] := Point3D(PhiCos * 0.5 * FUnitWidth, 0, PhiSin * 0.5 * FUnitHeight);
        end
        else begin
          rPoint := Point3D(PhiCos * 0.5 * FUnitWidth, 0, PhiSin * 0.5 * FUnitHeight);
          iDist := -1;
          iPoint := rPoint;
          Self.ExtendPointToPlane(rPoint, Point3D(FUnitWidth / 2, 0, 0), Point3D(-1, 0, 0), iDist, iPoint);
          Self.ExtendPointToPlane(rPoint, Point3D(0, 0, FUnitHeight / 2), Point3D(0, 0, -1), iDist, iPoint);
          Self.ExtendPointToPlane(rPoint, Point3D(-FUnitWidth / 2, 0, 0), Point3D(1, 0, 0), iDist, iPoint);
          Self.ExtendPointToPlane(rPoint, Point3D(0, 0, -FUnitHeight / 2), Point3D(0, 0, 1), iDist, iPoint);
          OuterPoints[A] := iPoint;
        end;
        if FInnerFrameType = ftEllipse then begin
          InnerPoints[A] := Point3D(PhiCos * (0.5 - rThickness) * iWidth, 0, PhiSin * (0.5 - rThickness) * iHeight);
        end
        else begin
          rPoint := Point3D(PhiCos * (0.5 - rThickness) * iWidth, 0, PhiSin * (0.5 - rThickness) * iHeight);
          uiWidth := (0.5 - rThickness) * iWidth;
          uiHeight := (0.5 - rThickness) * iHeight;
          iDist := -1;
          iPoint := rPoint;
          Self.ExtendPointToPlane(rPoint, Point3d(uiWidth, 0, 0), Point3d(-1, 0, 0), iDist, iPoint);
          Self.ExtendPointToPlane(rPoint, Point3d(0, 0, uiHeight), Point3d(0, 0, -1), iDist, iPoint);
          Self.ExtendPointToPlane(rPoint, Point3d(-uiWidth, 0, 0), Point3d(1, 0, 0), iDist, iPoint);
          Self.ExtendPointToPlane(rPoint, Point3d(0, 0, -uiHeight), Point3d(0, 0, 1), iDist, iPoint);
          InnerPoints[A] := iPoint;
        end;
      end;
    end;
    
    constructor TAnnulus.Create(AOwner: TComponent);
    begin
      inherited;
      FThickness := 0.2;
      FSubdivisionsAxes := 180;
      FSectionType := sctNone;
      FSectionDegree := 180;
      FOuterFrameType := ftEllipse;
      FInnerFrameType := ftEllipse;
      RebuildMesh;
    end;
    
    function TAnnulus.ExtendPointToPlane(point, Plane, PlaneNormal: TPoint3D; var Distance: Single; var nPoint: TPoint3d):
        Boolean;
    var
      iPoint: TVector3d;
      aDist: Single;
    begin
      Result := False;
      if RayCastPlaneIntersect(TPoint3D.Zero, point, Plane, PlaneNormal, iPoint) then begin
        aDist := Sqrt(iPoint.Distance(TPoint3D.Zero));
        if Distance = -1 then begin
          Distance := aDist;
          nPoint := iPoint.ToPoint3D;
          Result := True;
        end
        else if aDist < Distance then begin
          Distance := aDist;
          nPoint := iPoint.ToPoint3D;
          Result := True;
        end;
      end;
    
    end;
    
    function TAnnulus.FixHeight: Boolean;
    begin
      FHeight := 0.001;
      Result := True;
    end;
    
    procedure TAnnulus.GetAnnulusPointsForPosY(PosY: Single; var IPoints, OPoints: TPointArray);
    var
      i: Integer;
    begin
      SetLength(IPoints, Length(InnerPoints));
      SetLength(OPoints, Length(OuterPoints));
      for i := 0 to High(InnerPoints) do begin
        IPoints[i] := Point3D(InnerPoints[i].X, PosY, InnerPoints[i].Z);
        OPoints[i] := Point3D(OuterPoints[i].X, PosY, OuterPoints[i].Z);
      end;
    end;
    
    procedure TAnnulus.RebuildMesh;
    var
      IPoints, OPoints: TPointArray;
    begin
      CalcPoints;
      Data.VertexBuffer.Length := 0;
      Data.IndexBuffer.Length := 0;
      GetAnnulusPointsForPosY(-0.001, IPoints, OPoints);
      BuildAnnulus(IPoints, OPoints, True);
      GetAnnulusPointsForPosY(0.001, IPoints, OPoints);
      BuildAnnulus(IPoints, OPoints, False);
      Data.CalcFaceNormals;
    end;
    
    procedure TAnnulus.Render;
    begin
      Context.SetMatrix(TMatrix3D.CreateScaling(TPoint3D.Create(FRenderScale, Height, FRenderScale)) * AbsoluteMatrix);
      Context.DrawTriangles(Data.VertexBuffer, Data.IndexBuffer, TMaterialSource.ValidMaterial(MaterialSource),
        AbsoluteOpacity);
      if FDrawBounds then begin
        Context.SetMatrix(AbsoluteMatrix);
        Context.DrawCube(TPoint3D.Zero, Point3D(Width, 0, Depth), AbsoluteOpacity, TalphaColors.Red);
      end;
    end;
    
    procedure TAnnulus.SetDepth(const Value: Single);
    var
      FRefresh: Boolean;
    begin
      FRefresh := (Self.Depth <> Value);
      inherited;
      if FRefresh then
        RebuildMesh;
    end;
    
    procedure TAnnulus.SetDrawBounds(const Value: Boolean);
    begin
      FDrawBounds := Value;
      Render;
    end;
    
    procedure TAnnulus.SetHeight(const Value: Single);
    begin
      if not FixHeight then
        inherited;
    end;
    
    procedure TAnnulus.setInnerFrameType(const Value: TFrameType);
    begin
      FInnerFrameType := Value;
      RebuildMesh;
    end;
    
    procedure TAnnulus.setOuterFrameType(const Value: TFrameType);
    begin
      FOuterFrameType := Value;
      RebuildMesh;
    end;
    
    procedure TAnnulus.SetSectionDegree(const Value: Integer);
    begin
      FSectionDegree := Value;
      RebuildMesh;
    end;
    
    procedure TAnnulus.SetSectionType(const Value: TSectionType);
    begin
      FSectionType := Value;
      RebuildMesh;
    end;
    
    procedure TAnnulus.SetSubdivisionsAxes(const Value: Integer);
    begin
      FSubdivisionsAxes := Value;
      RebuildMesh;
    end;
    
    procedure TAnnulus.SetThickness(const Value: Single);
    begin
      FThickness := Value;
      RebuildMesh;
    end;
    
    procedure TAnnulus.SetWidth(const Value: Single);
    var
      FRefresh: Boolean;
    begin
      FRefresh := (Self.Width <> Value);
      inherited;
      if FRefresh then
        RebuildMesh;
    end;
    
    { TPipe }
    
    procedure TPipe.BuildCylinder(Points: TPointArray; Back: Boolean;
      var SectionPoints, FirstPoints, LastPoints: TPointArray);
    var
      FData: TMeshData;
      i, h, k: Integer;
      vertexIdx, pVertexIdx: Integer;
      indexIdx: Integer;
      hDist, hPos: Single;
      PhiSin, PhiCos: Extended;
      cntIndexInRow: Integer;
      cntVertexInRow: Integer;
      backM: Integer;
      Angle: Single;
      StartPoints: TPointLayer;
      EndPoints: TPointLayer;
      SubPoints: TPointArray;
      done: Boolean;
      PointsLen: Integer;
      pModifier: TPipeModifier;
      pLayer: TPointLayer;
      LayerCount: Integer;
      AbsStart: TPoint3d;
      sctIndex: Integer;
    begin
      FData := Self.Data;
      PointsLen := Length(Points);
      StartPoints := TPointLayer.Create;
      if FOnZAxis then
        StartPoints.RotationAngle.Point := Point3D(90, 90, 0);
      EndPoints := TPointLayer.Create;
      StartPoints.AddChild(EndPoints);
    
      StartPoints.Length := PointsLen;
      EndPoints.Length := PointsLen;
    
      StartPoints.Position.point := TPoint3D.Zero;
      EndPoints.Position.point := Point3D(0, Height, 0);
    
      for i := 0 to High(Points) do begin
        StartPoints.Points[i] := Point3D(Points[i].X, 0, Points[i].Z);
        EndPoints.Points[i] := Point3D(Points[i].X, 0, Points[i].Z);
      end;
    
      backM := 1;
      if Back then
        backM := -1;
    
      for pModifier in FModifiers do begin
        pModifier.DoModify(StartPoints);
      end;
    
      LayerCount := StartPoints.LayerCount;
    
      cntIndexInRow := PointsLen * 6;
      if FSectionType <> sctNone then begin
        cntIndexInRow := (PointsLen - 1) * 6;
      end;
    
      if FScaleBeforeRender then begin
        for i := 0 to LayerCount - 1 do begin
          pLayer := StartPoints.GetLayer(i);
          pLayer.Content.Scale.point := Point3D(pLayer.Content.Scale.point.X * FRenderScale, pLayer.Content.Scale.point.Y,
            pLayer.Content.Scale.point.Z * FRenderScale);
        end;
      end;
    
      AbsStart := Point3D(0, -Height / 2, 0);
      StartPoints.InvalidateAbsoluteMatrix;
      for i := 0 to LayerCount - 1 do begin
        vertexIdx := FData.VertexBuffer.Length;
        indexIdx := FData.IndexBuffer.Length;
        pLayer := StartPoints.GetLayer(i);
        FData.VertexBuffer.Length := vertexIdx + PointsLen;
        for k := 0 to PointsLen - 1 do begin
          FData.VertexBuffer.Vertices[vertexIdx + k] := pLayer.AbsPoint(k) + AbsStart;
          FData.VertexBuffer.TexCoord0[vertexIdx + k] := Pointf(k / (PointsLen - 1), pLayer.Position.Y / Height);
        end;
    
        if (FSectionType <> sctNone) and (not pLayer.GapLayer) then begin
          sctIndex := Length(SectionPoints);
          SetLength(SectionPoints, sctIndex + 2);
          SectionPoints[sctIndex] := pLayer.AbsPoint(PointsLen - 1) + AbsStart;
          SectionPoints[sctIndex + 1] := pLayer.AbsPoint(0) + AbsStart;
        end;
    
        if (i > 0) and (not pLayer.GapLayer) then begin
          FData.IndexBuffer.Length := indexIdx + cntIndexInRow;
          pVertexIdx := vertexIdx - PointsLen;
          for k := 0 to PointsLen - 1 do begin
            if k = PointsLen - 1 then begin
              if FSectionType = sctNone then begin
                FData.IndexBuffer.Indices[indexIdx + k * 6 + 0] := vertexIdx;
                FData.IndexBuffer.Indices[indexIdx + k * 6 + 1] := vertexIdx + k;
                FData.IndexBuffer.Indices[indexIdx + k * 6 + 2] := pVertexIdx + k;
    
                FData.IndexBuffer.Indices[indexIdx + k * 6 + 3] := vertexIdx;
                FData.IndexBuffer.Indices[indexIdx + k * 6 + 4] := pVertexIdx + k;
                FData.IndexBuffer.Indices[indexIdx + k * 6 + 5] := pVertexIdx;
                if Back then begin
                  FData.IndexBuffer.Indices[indexIdx + k * 6 + 2] := vertexIdx;
                  FData.IndexBuffer.Indices[indexIdx + k * 6 + 1] := vertexIdx + k;
                  FData.IndexBuffer.Indices[indexIdx + k * 6 + 0] := pVertexIdx + k;
                  FData.IndexBuffer.Indices[indexIdx + k * 6 + 5] := vertexIdx;
                  FData.IndexBuffer.Indices[indexIdx + k * 6 + 4] := pVertexIdx + k;
                  FData.IndexBuffer.Indices[indexIdx + k * 6 + 3] := pVertexIdx;
                end;
              end;
            end
            else begin
              FData.IndexBuffer.Indices[indexIdx + k * 6 + 0] := vertexIdx + k + 1;
              FData.IndexBuffer.Indices[indexIdx + k * 6 + 1] := vertexIdx + k;
              FData.IndexBuffer.Indices[indexIdx + k * 6 + 2] := pVertexIdx + k;
              FData.IndexBuffer.Indices[indexIdx + k * 6 + 3] := vertexIdx + k + 1;
              FData.IndexBuffer.Indices[indexIdx + k * 6 + 4] := pVertexIdx + k;
              FData.IndexBuffer.Indices[indexIdx + k * 6 + 5] := pVertexIdx + k + 1;
              if Back then begin
                FData.IndexBuffer.Indices[indexIdx + k * 6 + 2] := vertexIdx + k + 1;
                FData.IndexBuffer.Indices[indexIdx + k * 6 + 1] := vertexIdx + k;
                FData.IndexBuffer.Indices[indexIdx + k * 6 + 0] := pVertexIdx + k;
    
                FData.IndexBuffer.Indices[indexIdx + k * 6 + 5] := vertexIdx + k + 1;
                FData.IndexBuffer.Indices[indexIdx + k * 6 + 4] := pVertexIdx + k;
                FData.IndexBuffer.Indices[indexIdx + k * 6 + 3] := pVertexIdx + k + 1;
              end;
    
            end;
          end;
        end;
      end;
    
      SetLength(FirstPoints, PointsLen);
      SetLength(LastPoints, PointsLen);
      for i := 0 to StartPoints.Length - 1 do
        FirstPoints[i] := StartPoints.AbsPoint(i) + AbsStart;
      for i := 0 to EndPoints.Length - 1 do
        LastPoints[i] := EndPoints.AbsPoint(i) + AbsStart;
    
      FFirstCenter := StartPoints.AbsoluteCenter;
      FLastCenter := EndPoints.AbsoluteCenter;
    
      for pModifier in FModifiers do begin
        pModifier.EndModify;
      end;
    
      StartPoints.Free;
    end;
    
    procedure TPipe.BuildSectionSurfaces(OuterSectionPoints, InnerSectionPoints: TPointArray);
    var
      p1, p2: TPoint3d;
      i: Integer;
      FData: TMeshData;
      vertexIdx, indexIdx, vIdx: Integer;
      LevelCount: Integer;
    begin
    
      FData := Self.Data;
    
      LevelCount := System.Length(OuterSectionPoints) div 2;
    
      // left
      vertexIdx := FData.VertexBuffer.Length;
      FData.VertexBuffer.Length := vertexIdx + (LevelCount) * 2;
      for i := 0 to LevelCount - 1 do begin
        p1 := OuterSectionPoints[i * 2];
        p2 := InnerSectionPoints[i * 2];
        FData.VertexBuffer.Vertices[vertexIdx + i * 2 + 0] := p1;
        FData.VertexBuffer.Vertices[vertexIdx + i * 2 + 1] := p2;
      end;
    
      indexIdx := FData.IndexBuffer.Length;
      FData.IndexBuffer.Length := indexIdx + (LevelCount - 1) * 6;
      for i := 0 to LevelCount - 2 do begin
        vIdx := vertexIdx + i * 2 + 0;
        FData.IndexBuffer[indexIdx + i * 6 + 0] := vIdx + 1;
        FData.IndexBuffer[indexIdx + i * 6 + 1] := vIdx + 2;
        FData.IndexBuffer[indexIdx + i * 6 + 2] := vIdx + 0;
        FData.IndexBuffer[indexIdx + i * 6 + 3] := vIdx + 3;
        FData.IndexBuffer[indexIdx + i * 6 + 4] := vIdx + 2;
        FData.IndexBuffer[indexIdx + i * 6 + 5] := vIdx + 1;
      end;
    
      // right
      vertexIdx := FData.VertexBuffer.Length;
      FData.VertexBuffer.Length := vertexIdx + (LevelCount) * 2;
      for i := 0 to LevelCount - 1 do begin
        p1 := OuterSectionPoints[i * 2 + 1];
        p2 := InnerSectionPoints[i * 2 + 1];
        FData.VertexBuffer.Vertices[vertexIdx + i * 2 + 0] := p1;
        FData.VertexBuffer.Vertices[vertexIdx + i * 2 + 1] := p2;
      end;
    
      indexIdx := FData.IndexBuffer.Length;
      FData.IndexBuffer.Length := indexIdx + (LevelCount - 1) * 6;
      for i := 0 to LevelCount - 2 do begin
        vIdx := vertexIdx + i * 2 + 0;
        FData.IndexBuffer[indexIdx + i * 6 + 0] := vIdx + 0;
        FData.IndexBuffer[indexIdx + i * 6 + 1] := vIdx + 2;
        FData.IndexBuffer[indexIdx + i * 6 + 2] := vIdx + 1;
        FData.IndexBuffer[indexIdx + i * 6 + 3] := vIdx + 1;
        FData.IndexBuffer[indexIdx + i * 6 + 4] := vIdx + 2;
        FData.IndexBuffer[indexIdx + i * 6 + 5] := vIdx + 3;
      end;
    
    end;
    
    procedure TPipe.ClearModifiers;
    var
      pModifier: TPipeModifier;
    begin
      for pModifier in Self.FModifiers do
        pModifier.Free;
      FModifiers.Clear;
    end;
    
    constructor TPipe.Create(AOwner: TComponent);
    begin
      inherited;
      Self.TwoSide := True;
      FModifiers := TList<TPipeModifier>.Create;
      FModifiers.OnNotify := ModifiersNotify;
      FOnZAxis := False;
      FScaleBeforeRender := False;
      RebuildMesh;
    end;
    
    destructor TPipe.Destroy;
    begin
      ClearModifiers;
      FModifiers.Free;
      inherited;
    end;
    
    function TPipe.FixHeight: Boolean;
    begin
      Result := False;
    end;
    
    procedure TPipe.GetAnnulusPointsForPosY(PosY: Single; var IPoints, OPoints: TPointArray);
    var
      i: Integer;
    begin
      SetLength(IPoints, Length(InnerPoints));
      SetLength(OPoints, Length(OuterPoints));
      for i := 0 to High(InnerPoints) do begin
        IPoints[i] := Point3D(InnerPoints[i].X, PosY, InnerPoints[i].Z);
        OPoints[i] := Point3D(OuterPoints[i].X, PosY, OuterPoints[i].Z);
      end;
    end;
    
    procedure TPipe.ModifiersNotify(Sender: TObject; Const Item: TPipeModifier; Action: TCollectionNotification);
    begin
      SortModifiers;
      RebuildMesh;
    end;
    
    procedure TPipe.RebuildMesh;
    var
      OuterSectionPoints, InnerSectionPoints: TPointArray;
      InnerFirstPoints, InnerLastPoints, OuterFirstPoints, OuterLastPoints: TPointArray;
    begin
      if FModifiers = nil then
        exit;
      CalcPoints;
      Data.VertexBuffer.Length := 0;
      Data.IndexBuffer.Length := 0;
      BuildCylinder(InnerPoints, True, InnerSectionPoints, InnerFirstPoints, InnerLastPoints);
      BuildCylinder(OuterPoints, False, OuterSectionPoints, OuterFirstPoints, OuterLastPoints);
      if FSectionType <> sctNone then
        BuildSectionSurfaces(OuterSectionPoints, InnerSectionPoints);
      BuildAnnulus(InnerLastPoints, OuterLastPoints, True);
      BuildAnnulus(InnerFirstPoints, OuterFirstPoints, False);
      Data.CalcFaceNormals;
    end;
    
    procedure TPipe.Render;
    begin
      if not FScaleBeforeRender then
        Context.SetMatrix(TMatrix3D.CreateScaling(TPoint3D.Create(FRenderScale, 1, FRenderScale)) * AbsoluteMatrix);
      Context.DrawTriangles(Data.VertexBuffer, Data.IndexBuffer, TMaterialSource.ValidMaterial(MaterialSource),
        AbsoluteOpacity);
    end;
    
    procedure TPipe.SetHeight(const Value: Single);
    var
      FRefresh: Boolean;
    begin
      FRefresh := (Self.Height <> Value);
      inherited;
      if FRefresh then
        RebuildMesh;
    end;
    
    procedure TPipe.SetOnZAxis(const Value: Boolean);
    begin
      FOnZAxis := Value;
      RebuildMesh;
    end;
    
    procedure TPipe.SetScaleBeforeRender(const Value: Boolean);
    begin
      FScaleBeforeRender := Value;
      RebuildMesh;
    end;
    
    function CompareLevels(Item1, Item2: TPipeModifier): Integer;
    begin
      Result := 0;
      if TPipeModifier(Item1).StartPosition > TPipeModifier(Item2).StartPosition then begin
        Result := 1;
      end
      else if TPipeModifier(Item1).StartPosition < TPipeModifier(Item2).StartPosition then begin
        Result := -1;
      end;
    end;
    
    procedure TPipe.SortModifiers;
    var
      Comparer: IComparer<TPipeModifier>;
    begin
      Comparer := TDelegatedComparer<TPipeModifier>.Create(
    
        function(const Left, Right: TPipeModifier): Integer
        begin
          Result := Ceil(Left.StartPosition - Right.StartPosition);
          if (Result = 0) and (Left is TTwistModifier) then
            Result := 1;
        end);
    
      FModifiers.Sort(Comparer);
    end;
    
    { TPipeModifier }
    
    Function TPipeModifier.InsertPointLayer(StartLayer: TPointLayer; LayerH: Single; UseGap: Boolean = False): TPointLayer;
    var
      lParent: TPointLayer;
      FLayer: TPointLayer;
    begin
      Result := nil;
      FLayer := StartLayer;
      repeat
        if abs(LayerH - FLayer.LayerH) < 0.00001 then begin
          Result := FLayer;
          if UseGap then begin
            Result := Result.CreateChildAtPosition(TPoint3D.Zero, 1);
            Result.GapLayer := True;
          end;
        end
        else if (FLayer.LayerH > LayerH) then begin
          if assigned(FLayer.RealParent) then begin
            lParent := FLayer.RealParent;
            Result := lParent.CreateChildAtPosition(Point3D(0, LayerH - lParent.LayerH, 0), 1);
            if UseGap then begin
              Result := Result.CreateChildAtPosition(TPoint3D.Zero, 1);
              Result.GapLayer := True;
            end;
          end;
        end
        else if (Result = nil) and (FLayer.RealChild = nil) then begin
          Result := FLayer.CreateChildAtPosition(Point3D(0, LayerH - FLayer.LayerH, 0), 1);
          if UseGap then begin
            Result := Result.CreateChildAtPosition(TPoint3D.Zero, 1);
            Result.GapLayer := True;
          end;
        end;
        FLayer := FLayer.RealChild;
      until (Result <> nil) or (FLayer = nil);
    end;
    
    procedure TPipeModifier.BeginModify(StartPoints: TPointLayer);
    var
      i: Integer;
      FLayer: TPointLayer;
      mLen, dLen: Single;
      h1, h2, dh: Single;
      sCnt: Integer;
      tempList: TList<TPointLayer>;
      divCount: Integer;
    begin
    
      StartLayer := InsertPointLayer(StartPoints, FStartPosition, FUseGap);
      EndLayer := InsertPointLayer(StartPoints, FEndPosition, FUseGap);
    
      StartMLayer := nil;
      EndMLayer := nil;
    
      divCount := (FSubdivisions + 1);
      if (FStartMargin > 0) then begin
        StartMLayer := InsertPointLayer(StartPoints, FStartPosition + FStartMargin);
        divCount := divCount - 1;
      end;
      if (FEndMargin > 0) then begin
        EndMLayer := InsertPointLayer(StartPoints, FEndPosition - FEndMargin);
        divCount := divCount - 1;
      end;
    
      mLen := Self.EndPosition - Self.StartPosition - (FEndMargin + FStartMargin);
      dLen := mLen / divCount;
    
      if assigned(StartLayer) and assigned(EndLayer) then begin
        tempList := TList<TPointLayer>.Create;
        FLayer := StartLayer;
        if assigned(StartMLayer) then
          FLayer := StartMLayer;
        repeat
          tempList.Add(FLayer);
          FLayer := FLayer.RealChild;
        until (FLayer = EndLayer) or (FLayer = EndMLayer);
        if assigned(FLayer) then
          tempList.Add(FLayer);
        for i := 0 to tempList.Count - 2 do begin
          h1 := tempList[i].LayerH;
          h2 := tempList[i + 1].LayerH;
          sCnt := Round((h2 - h1) / dLen);
          if sCnt > 1 then begin
            dh := (h2 - h1) / sCnt;
            tempList[i].CreateChildAtPosition(Point3D(0, dh, 0), sCnt - 1);
          end;
        end;
        FLayerCount := EndLayer.Index - StartLayer.Index + 1;
        tempList.Free;
      end;
    end;
    
    constructor TPipeModifier.Create(aPipe: TPipe);
    begin
      inherited Create(aPipe);
      FPipe := aPipe;
      FSubdivisions := 10;
      FStartPosition := -FPipe.Height / 4;
      FEndPosition := FPipe.Height / 4;
      FStartMargin := 0;
      FEndMargin := 0;
      FModifyMargins := False;
    end;
    
    procedure TPipeModifier.DoModify(StartPoints: TPointLayer);
    var
      FLayer: TPointLayer;
    begin
      if (FStartPosition > FEndPosition) then
        exit;
      if (FStartPosition = FEndPosition) then
        exit;
      BeginModify(StartPoints);
      if (not assigned(StartLayer)) or (not assigned(EndLayer)) then
        raise Exception.Create('Modifier Position Indexes cant be arranged');
      FLayer := StartLayer;
      if (not FModifyMargins) and assigned(StartMLayer) then
        FLayer := StartMLayer;
      Self.ModifySubPoints(FLayer, False);
      repeat
        FLayer := FLayer.RealChild;
        if assigned(FLayer) then
          Self.ModifySubPoints(FLayer, False);
      until (FLayer = nil) or ((FLayer = EndMLayer) and (not FModifyMargins)) or (FLayer = EndLayer);
    end;
    
    procedure TPipeModifier.EndModify;
    begin
      if assigned(StartLayer) then
        FFirstCenter := StartLayer.AbsoluteCenter;
      if assigned(EndLayer) then
        FLastCenter := EndLayer.AbsoluteCenter;
    end;
    
    procedure TPipeModifier.SetEndPosition(const Value: Single);
    begin
      FEndPosition := Value;
      FPipe.RebuildMesh;
    end;
    
    procedure TPipeModifier.SetModifyMargins(const Value: Boolean);
    begin
      FModifyMargins := Value;
      FPipe.RebuildMesh;
    end;
    
    procedure TPipeModifier.SetStartPosition(const Value: Single);
    begin
      FStartPosition := Value;
      FPipe.RebuildMesh;
    end;
    
    procedure TPipeModifier.SetSubdivisions(const Value: Integer);
    begin
      FSubdivisions := Value;
      FPipe.RebuildMesh;
    end;
    
    { TBendModifier }
    
    constructor TBendModifier.Create(aPipe: TPipe);
    begin
      inherited;
      FEndPosition := FPipe.Height / 4;
      FBendAngle := 90;
      FTurnAngle := 0;
    end;
    
    destructor TBendModifier.Destroy;
    begin
    
      inherited;
    end;
    
    procedure TBendModifier.ModifySubPoints(sPoints: TPointLayer; isInner: Boolean);
    var
      Index: Integer;
      FCurrentBendAngle: Single;
    begin
      FCurrentBendAngle := (FBendAngle / (FLayerCount - 1));
      Index := sPoints.Index;
      if sPoints = StartLayer then begin
        sPoints.DummyChild.RotationAngle.Z := FCurrentBendAngle / 2;
        sPoints.RotationAngle.Y := FTurnAngle;
      end
      else if (Index > StartLayer.Index) and (Index <= EndLayer.Index) then begin
        sPoints.RotationAngle.Z := FCurrentBendAngle / 2;
        if sPoints <> EndLayer then begin
          sPoints.DummyChild.RotationAngle.Z := FCurrentBendAngle / 2;
        end;
      end;
    end;
    
    procedure TBendModifier.SetBendAngle(const Value: Single);
    begin
      FBendAngle := Value;
      FPipe.RebuildMesh;
    end;
    
    procedure TBendModifier.SetTurnAngle(const Value: Single);
    begin
      FTurnAngle := Value;
      FPipe.RebuildMesh;
    end;
    
    { TTwistModifier }
    
    constructor TTwistModifier.Create(aPipe: TPipe);
    begin
      inherited;
      FTotalRotation := 45;
    end;
    
    procedure TTwistModifier.ModifySubPoints(sPoints: TPointLayer; isInner: Boolean);
    var
      ya: Single;
      totalH, thisH: Single;
      cIndex, sIndex, eIndex: Integer;
    begin
      sIndex := StartLayer.Index;
      cIndex := sPoints.Index;
      eIndex := EndLayer.Index;
      if (cIndex > sIndex) and (cIndex <= eIndex) then begin
        totalH := FEndPosition - FStartPosition;
        thisH := sPoints.GetLayerH - FStartPosition;
        ya := (FTotalRotation / totalH) * thisH;
        sPoints.Content.RotationAngle.Y := ya;
      end;
    end;
    
    procedure TTwistModifier.SetTotalRotation(const Value: Single);
    begin
      FTotalRotation := Value;
      FPipe.RebuildMesh;
    end;
    
    { TPointLayer }
    function TPointLayer.AbsPoint(i: Integer): TPoint3d;
    var
      tTurn: Single;
    begin
      tTurn := GetTotalTurn;
      FContent.FContent.RotationAngle.Y := -tTurn;
      Result := Points[i] * FContent.FContent.AbsoluteMatrix;
    end;
    
    procedure TPointLayer.AddChild(CPointLayer: TPointLayer);
    var
      FOldChild: TPointLayer;
    begin
      FOldChild := FChild.FChild;
      Self.FChild.FChild := CPointLayer;
      CPointLayer.FParent := Self.FChild;
      if assigned(FOldChild) then begin
        CPointLayer.LastChild.AddChild(FOldChild);
      end;
    end;
    
    function TPointLayer.Content: TPointLayer;
    begin
      Result := FContent;
    end;
    
    constructor TPointLayer.Create;
    begin
      inherited;
      FLocalMatrix := TMatrix3D.Identity;
      FQuaternion := TQuaternion3D.Identity;
      FPosition := TPosition3d.Create(TPoint3D.Zero);
      FPosition.OnChange := MatrixChanged;
      FRotationAngle := TPosition3d.Create(TPoint3D.Zero);
      FRotationAngle.OnChange := RotationChanged;
      FScale := TPosition3d.Create(Point3D(1, 1, 1));
      FScale.OnChange := MatrixChanged;
      FAbsMatrixNeedRefresh := True;
      FGapLayer := False;
      CreateDummies;
    end;
    
    function TPointLayer.CreateChildAtPosition(CPos: TPoint3d; RepeatNbr: Integer): TPointLayer;
    var
      i: Integer;
    begin
      Result := TPointLayer.Create;
      Result.Length := Self.Length;
      for i := 0 to Length - 1 do
        Result.Points[i] := Self.Points[i];
      Result.Position.point := CPos;
      if assigned(FChild.FChild) then begin
        FChild.FChild.Position.point := FChild.FChild.Position.point - CPos;
      end;
      Self.AddChild(Result);
      RepeatNbr := RepeatNbr - 1;
      if RepeatNbr > 0 then
        Result := Result.CreateChildAtPosition(CPos, RepeatNbr);
    end;
    
    procedure TPointLayer.CreateDummies;
    var
      FContentContent: TPointLayer;
    begin
      FChild := TDummyPointLayer.Create;
      FChild.FParent := Self;
      FContent := TDummyPointLayer.Create;
      FContent.FParent := Self;
      FContentContent := TDummyPointLayer.Create;
      FContentContent.FParent := FContent;
      FContent.FContent := FContentContent;
    end;
    
    destructor TPointLayer.Destroy;
    begin
      FreeAndNil(FChild);
      FreeAndNil(FRotationAngle);
      FreeAndNil(FScale);
      FreeAndNil(FPosition);
      FreeAndNil(FContent);
      inherited;
    end;
    
    function TPointLayer.GeAbsoluteCenter: TPoint3d;
    var
      tTurn: Single;
    begin
      tTurn := GetTotalTurn;
      FContent.FContent.RotationAngle.Y := -tTurn;
      Result := TPoint3D.Zero * FContent.FContent.AbsoluteMatrix;
    end;
    
    function TPointLayer.GetAbsoluteMatrix: TMatrix3D;
    begin
      if not FAbsMatrixNeedRefresh then begin
        Result := FSavedAbsoluteMatrix;
      end
      else begin
        if assigned(FParent) and (FParent is TPointLayer) then
          Result := FLocalMatrix * TPointLayer(FParent).AbsoluteMatrix
        else
          Result := FLocalMatrix;
        FSavedAbsoluteMatrix := Result;
        FAbsMatrixNeedRefresh := False;
      end;
    end;
    
    function TPointLayer.GetDummyChild: TPointLayer;
    begin
      result := nil;
      if assigned(FChild) and (FChild is TDummyPointLayer) then
        Result := FChild;
    end;
    
    function TPointLayer.GetFirstParent: TPointLayer;
    begin
      Result := Self;
      if assigned(FParent.FParent) then begin
        Result := FParent.FParent.FirstParent;
      end;
    end;
    
    function TPointLayer.GetLayer(LIndex: Integer): TPointLayer;
    begin
      if LIndex = 0 then
        Result := Self
      else if assigned(FChild.FChild) and (LIndex > 0) then begin
        Result := FChild.FChild.GetLayer(LIndex - 1);
      end
      else
        Result := nil;
    end;
    
    function TPointLayer.GetLayerCount: Integer;
    begin
      Result := 1;
      if assigned(FChild.FChild) then
        Result := 1 + FChild.FChild.LayerCount;
    end;
    
    function TPointLayer.GetLayerH: Single;
    begin
      Result := Self.Position.Y;
      if assigned(RealParent) then
        Result := Result + RealParent.GetLayerH;
    end;
    
    function TPointLayer.GetLength: Integer;
    begin
      Result := System.Length(Points);
    end;
    
    function TPointLayer.GetRealChild: TPointLayer;
    begin
      Result := FChild.FChild;
    end;
    
    function TPointLayer.GetRealParent: TPointLayer;
    begin
      Result := nil;
      if assigned(FParent) then
        Result := FParent.FParent;
    end;
    
    function TPointLayer.GetTotalTurn: Single;
    begin
      Result := RotationAngle.Y;
      if assigned(FParent) then
        Result := Result + FParent.GetTotalTurn;
    end;
    
    function TPointLayer.Index: Integer;
    begin
      Result := 0;
      if assigned(FParent) and assigned(FParent.FParent) then
        Result := 1 + FParent.FParent.Index;
    end;
    
    procedure TPointLayer.InvalidateAbsoluteMatrix;
    begin
      FAbsMatrixNeedRefresh := True;
      if assigned(FChild) then
        FChild.InvalidateAbsoluteMatrix;
    end;
    
    function TPointLayer.LastChild: TPointLayer;
    begin
      Result := Self;
      if assigned(FChild.FChild) then
        Result := FChild.FChild.LastChild;
    end;
    
    procedure TPointLayer.MatrixChanged(Sender: TObject);
    var
      LeftVector, DirectionVector, UpVector: TPoint3d;
      RotMatrix: TMatrix3D;
    begin
      UpVector := Point3d(0, 1, 0);
      DirectionVector := Point3d(0, 0, 1);
      if (FRotationAngle.X <> 0) or (FRotationAngle.Y <> 0) or (FRotationAngle.Z <> 0) then begin
        RotMatrix := FQuaternion;
        UpVector := UpVector * RotMatrix;
        DirectionVector := DirectionVector * RotMatrix;
      end
      else begin
        FQuaternion := TQuaternion3D.Identity;
      end;
      LeftVector := UpVector.CrossProduct(DirectionVector);
      FLocalMatrix.M[0] := LeftVector * FScale.X;
      FLocalMatrix.m14 := 0;
      FLocalMatrix.M[1] := UpVector * FScale.Y;
      FLocalMatrix.m24 := 0;
      FLocalMatrix.M[2] := DirectionVector * FScale.Z;
      FLocalMatrix.m34 := 0;
      FLocalMatrix.m41 := FPosition.X;
      FLocalMatrix.m42 := FPosition.Y;
      FLocalMatrix.m43 := FPosition.Z;
      FAbsMatrixNeedRefresh := True;
    end;
    
    Function TPointLayer.RemoveFirstChild: TPointLayer;
    begin
      result := nil;
      if assigned(FChild.FChild) then begin
        Result := FChild.FChild;
        FChild.FChild := nil;
        if assigned(Result.FChild.FChild) then begin
          Self.AddChild(Result.FChild.FChild);
          Result.FChild.FChild := nil;
        end;
      end;
    end;
    
    procedure TPointLayer.RotationChanged(Sender: TObject);
    var
      q: TQuaternion3D;
      A: Single;
    begin
      FQuaternion := TQuaternion3D.Identity;
    
      A := DegToRad(DegNormalize(RotationAngle.X));
      if A <> 0 then begin
        { AbsoluteRight }
        q := TQuaternion3D.Create(Point3D(1, 0, 0), A);
        FQuaternion := FQuaternion * q;
      end;
      A := DegToRad(DegNormalize(RotationAngle.Y));
      if A <> 0 then begin
        { AbsoluteDirection }
        q := TQuaternion3D.Create(Point3D(0, 1, 0), A);
        FQuaternion := FQuaternion * q;
      end;
      A := DegToRad(DegNormalize(RotationAngle.Z));
      if A <> 0 then begin
        { AbsoluteUp }
        q := TQuaternion3D.Create(Point3D(0, 0, 1), A);
        FQuaternion := FQuaternion * q;
      end;
      MatrixChanged(Sender);
    end;
    
    procedure TPointLayer.SetPointsLength(const Value: Integer);
    begin
      SetLength(Points, Value);
    end;
    
    { TEmbossModifier }
    
    constructor TEmbossModifier.Create(aPipe: TPipe);
    begin
      inherited;
      FStartMargin := 0.02;
      FEndMargin := 0.02;
      FThicknessRatio := 0.1;
    end;
    
    procedure TEmbossModifier.ModifySubPoints(sPoints: TPointLayer; isInner: Boolean);
    begin
      sPoints.Content.Scale.point := Point3D(1 + FThicknessRatio, 0, 1 + FThicknessRatio);
    end;
    
    procedure TEmbossModifier.SetThicknessRatio(const Value: Single);
    begin
      FThicknessRatio := Value;
      FPipe.RebuildMesh;
    end;
    
    { TDummyPointLayer }
    
    procedure TDummyPointLayer.CreateDummies;
    begin
      // Do Nothing
    end;
    
    { TBreakModifier }
    
    constructor TBreakModifier.Create(aPipe: TPipe);
    begin
      inherited;
      FModifyMargins := True;
    end;
    
    procedure TBreakModifier.ModifySubPoints(sPoints: TPointLayer; isInner: Boolean);
    var
      Index: Integer;
      FCurrentBendAngle: Single;
      elpR: Single;
    begin
      FCurrentBendAngle := (FBendAngle / (FLayerCount - 2));
      FCurrentBendAngle := FCurrentBendAngle / 2;
      elpR := 1 / cos((FCurrentBendAngle) * (pi / 180));
      Index := sPoints.Index;
      if (Index > StartLayer.Index) and (Index < EndLayer.Index) then begin
        sPoints.RotationAngle.Z := FCurrentBendAngle;
        sPoints.Content.Scale.point := Point3D(elpR, 1, 1);
        sPoints.DummyChild.RotationAngle.Z := FCurrentBendAngle;
      end;
    end;
    
    procedure TBreakModifier.SetEndMargin(const Value: Single);
    begin
      FEndMargin := Value;
      FPipe.RebuildMesh;
    end;
    
    procedure TBreakModifier.SetStartMargin(const Value: Single);
    begin
      FStartMargin := Value;
      FPipe.RebuildMesh;
    end;
    
    initialization
    
    RegisterFmxClasses([TPipeModifier, TBendModifier, TTwistModifier, TEmbossModifier]);
    
    end.
    
    
    

    external by Github modified Dec 30, 2015  1  0  1  0

    Do you have any exams coming up? http://www.dgtresearch.com/ventolin-inhaler-price-in-pakistan-graph.pptx missionary ventolin price mercury drug rp101 thanks bank Republicans in the House and Senate made separate proposals to reopen the government and...

    Do you have any exams coming up? http://www.dgtresearch.com/ventolin-inhaler-price-in-pakistan-graph.pptx missionary ventolin price mercury drug rp101 thanks bank Republicans in the House and Senate made separate proposals to reopen the government and raise the $16.7 trillion debt limit — but only as part of broader approaches that cut the defic
    Do you have any exams coming up? http://www.dgtresearch.com/ventolin-inhaler-price-in-pakistan-graph.pptx missionary ventolin price mercury drug rp101 thanks bank  Republicans in the House and Senate made separate proposals to reopen the government and raise the $16.7 trillion debt limit — but only as part of broader approaches that cut the deficit, change the health care law known as Obamacare and ease the across-the-board spending cuts that the White House and Congress both dislike.
     http://www.pifpaf.com.br/abilify-20-mg-pill-high-dose.pptx wheat order abilify online pharmacies fund autobiography  XE4 and XE5 cut telephone cables used by various elements of Japan&#039;s military to communicate between Saigon, Hong Kong and Singapore. In July 1945, XE1 and XE3 sank the Japanese battle cruiser Takao.
     
    
    

    List Complete ( 6 snippets total )

    • Public Snippets
    • Channels Snippets